├── app ├── apk │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── values │ │ │ │ ├── ids.xml │ │ │ │ ├── theme_overlay.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── attrs.xml │ │ │ │ ├── styles_md2.xml │ │ │ │ └── themes_override.xml │ │ │ ├── values-night │ │ │ │ └── styles_md2.xml │ │ │ ├── color │ │ │ │ ├── color_error_transient.xml │ │ │ │ ├── color_primary_transient.xml │ │ │ │ ├── color_text_transient.xml │ │ │ │ ├── color_on_primary_transient.xml │ │ │ │ ├── color_card_background_color_selector.xml │ │ │ │ ├── color_primary_error_transient.xml │ │ │ │ ├── color_menu_tint.xml │ │ │ │ └── color_state_primary_transient.xml │ │ │ ├── drawable │ │ │ │ ├── bg_selection_circle_green.xml │ │ │ │ ├── ic_action_md2.xml │ │ │ │ ├── ic_superuser_filled_md2.xml │ │ │ │ ├── bg_line_top_rounded.xml │ │ │ │ ├── bg_line_bottom_rounded.xml │ │ │ │ ├── ic_home_filled_md2.xml │ │ │ │ ├── ic_superuser_outlined_md2.xml │ │ │ │ ├── ic_update_md2.xml │ │ │ │ ├── ic_folder_list.xml │ │ │ │ ├── ic_check_md2.xml │ │ │ │ ├── ic_download_md2.xml │ │ │ │ ├── ic_home_outlined_md2.xml │ │ │ │ ├── ic_install.xml │ │ │ │ ├── ic_save_md2.xml │ │ │ │ ├── ic_check_circle_unchecked_md2.xml │ │ │ │ ├── ic_paint.xml │ │ │ │ ├── ic_check_circle_checked_md2.xml │ │ │ │ ├── ic_close_md2.xml │ │ │ │ ├── ic_back_md2.xml │ │ │ │ ├── ic_notifications_md2.xml │ │ │ │ ├── ic_delete_md2.xml │ │ │ │ ├── ic_module_filled_md2.xml │ │ │ │ ├── ic_search_md2.xml │ │ │ │ ├── ic_restart.xml │ │ │ │ ├── ic_day.xml │ │ │ │ ├── ic_forth_md2.xml │ │ │ │ ├── ic_bug_md2.xml │ │ │ │ ├── ic_home_md2.xml │ │ │ │ ├── ic_module_md2.xml │ │ │ │ ├── ic_bug_filled_md2.xml │ │ │ │ ├── ic_settings_md2.xml │ │ │ │ ├── ic_superuser_md2.xml │ │ │ │ ├── ic_bug_outlined_md2.xml │ │ │ │ ├── ic_module_outlined_md2.xml │ │ │ │ ├── ic_check_circle_md2.xml │ │ │ │ ├── ic_night.xml │ │ │ │ ├── ic_module_storage_md2.xml │ │ │ │ ├── ic_day_night.xml │ │ │ │ ├── ic_settings_filled_md2.xml │ │ │ │ ├── ic_manager.xml │ │ │ │ ├── avd_home_from_filled.xml │ │ │ │ ├── ic_settings_outlined_md2.xml │ │ │ │ └── avd_home_to_filled.xml │ │ │ ├── menu │ │ │ │ ├── menu_flash.xml │ │ │ │ ├── menu_log_md2.xml │ │ │ │ ├── menu_home_md2.xml │ │ │ │ ├── menu_deny_md2.xml │ │ │ │ ├── menu_bottom_nav.xml │ │ │ │ └── menu_reboot.xml │ │ │ ├── layout │ │ │ │ ├── item_theme_container.xml │ │ │ │ ├── item_log_textview.xml │ │ │ │ ├── item_spinner.xml │ │ │ │ ├── item_console_md2.xml │ │ │ │ ├── item_text.xml │ │ │ │ ├── markdown_window_md2.xml │ │ │ │ ├── item_module_download.xml │ │ │ │ ├── item_list_single_line.xml │ │ │ │ ├── item_icon_link.xml │ │ │ │ ├── item_settings_section.xml │ │ │ │ └── fragment_theme_md2.xml │ │ │ ├── anim │ │ │ │ ├── fragment_enter.xml │ │ │ │ ├── fragment_exit.xml │ │ │ │ ├── fragment_exit_pop.xml │ │ │ │ └── fragment_enter_pop.xml │ │ │ └── values-v27 │ │ │ │ └── themes.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── topjohnwu │ │ │ │ └── magisk │ │ │ │ ├── view │ │ │ │ ├── TextItem.kt │ │ │ │ └── TappableHeadlineItem.kt │ │ │ │ ├── utils │ │ │ │ ├── AccessibilityUtils.kt │ │ │ │ └── TextHolder.kt │ │ │ │ ├── arch │ │ │ │ ├── ViewEvent.kt │ │ │ │ └── AsyncLoadViewModel.kt │ │ │ │ ├── dialog │ │ │ │ ├── SecondSlotWarningDialog.kt │ │ │ │ ├── SuperuserRevokeDialog.kt │ │ │ │ ├── ManagerInstallDialog.kt │ │ │ │ ├── LocalModuleInstallDialog.kt │ │ │ │ └── MarkDownDialog.kt │ │ │ │ ├── ui │ │ │ │ ├── install │ │ │ │ │ └── InstallFragment.kt │ │ │ │ ├── theme │ │ │ │ │ ├── ThemeViewModel.kt │ │ │ │ │ └── Theme.kt │ │ │ │ ├── log │ │ │ │ │ └── LogRvItem.kt │ │ │ │ ├── superuser │ │ │ │ │ └── SuperuserFragment.kt │ │ │ │ ├── flash │ │ │ │ │ └── ConsoleItem.kt │ │ │ │ └── settings │ │ │ │ │ └── SettingsFragment.kt │ │ │ │ └── databinding │ │ │ │ └── RecyclerViewItems.kt │ │ │ └── AndroidManifest.xml │ └── build.gradle.kts ├── shared │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── main │ │ └── java │ │ └── com │ │ └── topjohnwu │ │ └── magisk │ │ ├── utils │ │ └── CompoundEnumeration.java │ │ └── ProviderInstaller.java ├── test │ ├── .gitignore │ ├── proguard-rules.pro │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── topjohnwu │ │ └── magisk │ │ └── test │ │ └── Runners.kt ├── buildSrc │ ├── .gitignore │ ├── settings.gradle.kts │ └── build.gradle.kts ├── core │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── values-night │ │ │ │ └── colors.xml │ │ │ ├── values-v34 │ │ │ │ └── resources.xml │ │ │ ├── drawable │ │ │ │ ├── ic_logo.xml │ │ │ │ ├── sc_extension.xml │ │ │ │ ├── sc_superuser.xml │ │ │ │ ├── ic_favorite.xml │ │ │ │ ├── ic_patreon.xml │ │ │ │ ├── ic_more.xml │ │ │ │ ├── ic_superuser.xml │ │ │ │ ├── ic_extension.xml │ │ │ │ ├── ic_twitter.xml │ │ │ │ ├── ic_github.xml │ │ │ │ └── ic_paypal.xml │ │ │ ├── drawable-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ ├── sc_extension.xml │ │ │ │ └── sc_superuser.xml │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── themes.xml │ │ │ │ └── resources.xml │ │ │ └── values-v31 │ │ │ │ └── themes.xml │ │ │ ├── aidl │ │ │ └── com │ │ │ │ └── topjohnwu │ │ │ │ └── magisk │ │ │ │ └── core │ │ │ │ └── utils │ │ │ │ └── IRootUtils.aidl │ │ │ └── java │ │ │ └── com │ │ │ └── topjohnwu │ │ │ └── magisk │ │ │ ├── core │ │ │ ├── base │ │ │ │ ├── BaseJobService.kt │ │ │ │ ├── BaseReceiver.kt │ │ │ │ ├── BaseService.kt │ │ │ │ └── BaseProvider.kt │ │ │ ├── utils │ │ │ │ ├── DummyList.kt │ │ │ │ ├── RequestAuthentication.kt │ │ │ │ ├── ProgressInputStream.kt │ │ │ │ └── RequestInstall.kt │ │ │ ├── model │ │ │ │ ├── module │ │ │ │ │ ├── Module.kt │ │ │ │ │ └── OnlineModule.kt │ │ │ │ └── su │ │ │ │ │ └── SuPolicy.kt │ │ │ ├── download │ │ │ │ └── Interfaces.kt │ │ │ ├── Provider.kt │ │ │ ├── ktx │ │ │ │ └── XSU.kt │ │ │ ├── data │ │ │ │ ├── magiskdb │ │ │ │ │ ├── StringDao.kt │ │ │ │ │ └── SettingsDao.kt │ │ │ │ └── RetrofitInterfaces.kt │ │ │ ├── App.kt │ │ │ ├── signing │ │ │ │ └── ByteArrayStream.java │ │ │ └── Service.kt │ │ │ └── test │ │ │ └── BaseTest.kt │ └── proguard-rules.pro ├── stub │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── values-cs │ │ │ │ └── strings.xml │ │ │ ├── values-el │ │ │ │ └── strings.xml │ │ │ ├── values-sv │ │ │ │ └── strings.xml │ │ │ ├── values-vi │ │ │ │ └── strings.xml │ │ │ ├── values-th │ │ │ │ └── strings.xml │ │ │ ├── values-zh-rTW │ │ │ │ └── strings.xml │ │ │ ├── values-az │ │ │ │ └── strings.xml │ │ │ ├── values-ja │ │ │ │ └── strings.xml │ │ │ ├── values-zh-rCN │ │ │ │ └── strings.xml │ │ │ ├── values-lt │ │ │ │ └── strings.xml │ │ │ ├── values-ko │ │ │ │ └── strings.xml │ │ │ ├── values-mk │ │ │ │ └── strings.xml │ │ │ ├── values-iw │ │ │ │ └── strings.xml │ │ │ ├── values-bg │ │ │ │ └── strings.xml │ │ │ ├── values-es │ │ │ │ └── strings.xml │ │ │ ├── values-uk │ │ │ │ └── strings.xml │ │ │ ├── values-ru │ │ │ │ └── strings.xml │ │ │ ├── values-nb │ │ │ │ └── strings.xml │ │ │ ├── values-ar │ │ │ │ └── strings.xml │ │ │ ├── values-ka │ │ │ │ └── strings.xml │ │ │ ├── values-nl │ │ │ │ └── strings.xml │ │ │ ├── values-ku │ │ │ │ └── strings.xml │ │ │ ├── values │ │ │ │ └── strings.xml │ │ │ ├── values-ta │ │ │ │ └── strings.xml │ │ │ ├── values-kk │ │ │ │ └── strings.xml │ │ │ ├── values-hu │ │ │ │ └── strings.xml │ │ │ ├── values-sk │ │ │ │ └── strings.xml │ │ │ ├── values-pa │ │ │ │ └── strings.xml │ │ │ ├── values-ast │ │ │ │ └── strings.xml │ │ │ ├── values-sw │ │ │ │ └── strings.xml │ │ │ ├── values-be │ │ │ │ └── strings.xml │ │ │ ├── values-de │ │ │ │ └── strings.xml │ │ │ ├── values-et │ │ │ │ └── strings.xml │ │ │ ├── values-hi │ │ │ │ └── strings.xml │ │ │ ├── values-hr │ │ │ │ └── strings.xml │ │ │ ├── values-pl │ │ │ │ └── strings.xml │ │ │ ├── values-tr │ │ │ │ └── strings.xml │ │ │ ├── values-in │ │ │ │ └── strings.xml │ │ │ ├── values-pt-rBR │ │ │ │ └── strings.xml │ │ │ ├── values-fa │ │ │ │ └── strings.xml │ │ │ ├── values-it │ │ │ │ └── strings.xml │ │ │ ├── values-pt-rPT │ │ │ │ └── strings.xml │ │ │ ├── values-ro │ │ │ │ └── strings.xml │ │ │ ├── values-ml │ │ │ │ └── strings.xml │ │ │ ├── values-sr │ │ │ │ └── strings.xml │ │ │ ├── values-b+sr+Latn │ │ │ │ └── strings.xml │ │ │ ├── values-sq │ │ │ │ └── strings.xml │ │ │ ├── values-ca │ │ │ │ └── strings.xml │ │ │ └── values-fr │ │ │ │ └── strings.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── topjohnwu │ │ │ │ └── magisk │ │ │ │ ├── net │ │ │ │ ├── ResponseListener.java │ │ │ │ ├── ErrorHandler.java │ │ │ │ ├── BadRequest.java │ │ │ │ └── Networking.java │ │ │ │ ├── dummy │ │ │ │ ├── DummyService.java │ │ │ │ ├── DummyReceiver.java │ │ │ │ └── DummyProvider.java │ │ │ │ ├── StubApplication.java │ │ │ │ └── StubRootService.java │ │ │ └── AndroidManifest.xml │ ├── .gitignore │ ├── proguard-rules.pro │ └── build.gradle.kts ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── build.gradle.kts ├── settings.gradle.kts └── gradle.properties ├── .github ├── ci.prop ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.md └── actions │ └── setup │ └── sccache.sh ├── tools ├── elf-cleaner │ ├── .gitignore │ └── Cargo.toml ├── rustup-wrapper │ ├── .gitignore │ └── Cargo.toml ├── bootctl ├── futility ├── keys │ ├── verity.pk8 │ ├── kernel.keyblock │ ├── kernel_data_key.vbprivk │ └── verity.x509.pem └── bootctl.patch ├── native ├── src │ ├── exported_sym.txt │ ├── boot │ │ ├── .gitignore │ │ ├── build.rs │ │ ├── magiskboot.hpp │ │ └── Cargo.toml │ ├── core │ │ ├── resetprop │ │ │ ├── .gitignore │ │ │ └── proto │ │ │ │ └── persistent_properties.proto │ │ ├── zygisk │ │ │ └── mod.rs │ │ ├── resetprop.rs │ │ ├── su │ │ │ └── mod.rs │ │ ├── derive │ │ │ ├── lib.rs │ │ │ └── Cargo.toml │ │ ├── applet_stub.cpp │ │ ├── build.rs │ │ ├── Cargo.toml │ │ ├── deny │ │ │ └── deny.hpp │ │ └── include │ │ │ └── resetprop.hpp │ ├── base │ │ ├── build.rs │ │ ├── include │ │ │ └── base.hpp │ │ ├── logging.hpp │ │ ├── Cargo.toml │ │ ├── Android.mk │ │ └── new.cpp │ ├── init │ │ ├── build.rs │ │ ├── Cargo.toml │ │ ├── preload.c │ │ └── init.hpp │ ├── sepolicy │ │ ├── build.rs │ │ ├── Cargo.toml │ │ └── include │ │ │ └── sepolicy.hpp │ ├── external │ │ ├── lz4-sys │ │ │ └── Cargo.toml │ │ ├── lzma-sys │ │ │ └── Cargo.toml │ │ └── xz-embedded │ │ │ └── xz_crc32.c │ ├── .cargo │ │ └── config.toml │ ├── Application.mk │ ├── Android-rs.mk │ └── include │ │ └── codegen.rs └── .gitignore ├── docs ├── images │ ├── logo.png │ ├── ota_done.png │ ├── device_info.png │ ├── restore_img.png │ ├── disable_auto_ota.png │ ├── manager_reboot.png │ └── install_inactive_slot.png └── README.md ├── .gitignore ├── .gitattributes ├── scripts ├── module_installer.sh └── update_binary.sh ├── .gitmodules └── config.prop.sample /app/apk/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/shared/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/test/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.github/ci.prop: -------------------------------------------------------------------------------- 1 | abiList=arm64-v8a 2 | -------------------------------------------------------------------------------- /app/buildSrc/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /tools/elf-cleaner/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /tools/rustup-wrapper/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /app/core/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | src/debug 3 | src/release 4 | -------------------------------------------------------------------------------- /native/src/exported_sym.txt: -------------------------------------------------------------------------------- 1 | { 2 | NativeBridgeItf; 3 | }; 4 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-cs/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-el/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-sv/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-vi/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /native/src/boot/.gitignore: -------------------------------------------------------------------------------- 1 | proto/update_metadata.rs 2 | proto/mod.rs 3 | -------------------------------------------------------------------------------- /native/src/core/resetprop/.gitignore: -------------------------------------------------------------------------------- 1 | proto/mod.rs 2 | proto/persistent_properties.rs 3 | -------------------------------------------------------------------------------- /tools/bootctl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/tools/bootctl -------------------------------------------------------------------------------- /tools/futility: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/tools/futility -------------------------------------------------------------------------------- /native/src/core/zygisk/mod.rs: -------------------------------------------------------------------------------- 1 | mod daemon; 2 | 3 | pub use daemon::zygisk_should_load_module; 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /dict.txt 2 | 3 | # Gradle 4 | .gradle 5 | .kotlin 6 | /local.properties 7 | /build 8 | -------------------------------------------------------------------------------- /app/stub/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /src/release/AndroidManifest.xml 3 | /src/debug/AndroidManifest.xml 4 | -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/logo.png -------------------------------------------------------------------------------- /tools/keys/verity.pk8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/tools/keys/verity.pk8 -------------------------------------------------------------------------------- /docs/images/ota_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/ota_done.png -------------------------------------------------------------------------------- /docs/images/device_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/device_info.png -------------------------------------------------------------------------------- /docs/images/restore_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/restore_img.png -------------------------------------------------------------------------------- /tools/keys/kernel.keyblock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/tools/keys/kernel.keyblock -------------------------------------------------------------------------------- /app/stub/src/main/res/values-th/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/images/disable_auto_ota.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/disable_auto_ota.png -------------------------------------------------------------------------------- /docs/images/manager_reboot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/manager_reboot.png -------------------------------------------------------------------------------- /tools/keys/kernel_data_key.vbprivk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/tools/keys/kernel_data_key.vbprivk -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /docs/images/install_inactive_slot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metalex201/MagiskSafe/master/docs/images/install_inactive_slot.png -------------------------------------------------------------------------------- /native/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | obj 3 | libs 4 | /.externalNativeBuild 5 | /.cxx 6 | *-rs.cpp 7 | *-rs.hpp 8 | /compile_commands.json 9 | -------------------------------------------------------------------------------- /app/apk/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /native/src/core/resetprop.rs: -------------------------------------------------------------------------------- 1 | pub use persist::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop}; 2 | 3 | mod persist; 4 | mod proto; 5 | -------------------------------------------------------------------------------- /native/src/core/su/mod.rs: -------------------------------------------------------------------------------- 1 | mod connect; 2 | mod daemon; 3 | mod db; 4 | mod pts; 5 | 6 | pub use daemon::SuInfo; 7 | pub use pts::{get_pty_num, pump_tty, restore_stdin}; 8 | -------------------------------------------------------------------------------- /app/core/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #0D0D0D 4 | 5 | -------------------------------------------------------------------------------- /app/core/src/main/res/values-v34/resources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 5 | -------------------------------------------------------------------------------- /app/shared/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.library") 3 | } 4 | 5 | setupCommon() 6 | 7 | android { 8 | namespace = "com.topjohnwu.shared" 9 | } 10 | -------------------------------------------------------------------------------- /native/src/base/build.rs: -------------------------------------------------------------------------------- 1 | use crate::codegen::gen_cxx_binding; 2 | 3 | #[path = "../include/codegen.rs"] 4 | mod codegen; 5 | 6 | fn main() { 7 | gen_cxx_binding("base-rs"); 8 | } 9 | -------------------------------------------------------------------------------- /native/src/init/build.rs: -------------------------------------------------------------------------------- 1 | use crate::codegen::gen_cxx_binding; 2 | 3 | #[path = "../include/codegen.rs"] 4 | mod codegen; 5 | 6 | fn main() { 7 | gen_cxx_binding("init-rs"); 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | *.zip 3 | *.jks 4 | *.apk 5 | *.log 6 | /config.prop 7 | /notes.md 8 | 9 | # Built binaries 10 | native/out 11 | 12 | # Android Studio 13 | *.iml 14 | .idea 15 | -------------------------------------------------------------------------------- /app/apk/src/main/res/values-night/styles_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("MagiskPlugin") 3 | } 4 | 5 | tasks.register("clean", Delete::class) { 6 | delete(rootProject.layout.buildDirectory) 7 | 8 | subprojects.forEach { 9 | dependsOn(":${it.name}:clean") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-zh-rTW/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 需要升級到完整版 Magisk Manager。是否下載並安裝? 3 | 請連上網路!升級到完整版 Magisk Manager 是必須的。 4 | 正在下載 5 | 6 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_error_transient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_primary_transient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_text_transient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tools/elf-cleaner/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "elf-cleaner" 3 | version = "0.0.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | object = { version = "0.36", features = ["build"] } 8 | anyhow = "1.0" 9 | 10 | [profile.release] 11 | strip = true 12 | lto = true 13 | codegen-units = 1 14 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_on_primary_transient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/shared/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-az/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Qurmanı sonlandırmaq üçün full Magisk Manager`ə yüksəldin. Yüklənib qurulsun? 3 | Lütfən internetə qoşulun! Full Magisk Manager\'ə yüksəltmə lazımidir. 4 | 5 | -------------------------------------------------------------------------------- /native/src/core/derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "derive" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [lib] 7 | path = "lib.rs" 8 | proc-macro = true 9 | 10 | [dependencies] 11 | syn = { workspace = true } 12 | quote = { workspace = true } 13 | proc-macro2 = { workspace = true } 14 | -------------------------------------------------------------------------------- /app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Magisk Manager のフルバージョンにアップグレードしてセットアップを完了します。ダウンロードしてインストールしますか? 3 | ダウンロード中 4 | インターネットに接続してください!フルバージョンの Magisk Manager が必要です。 5 | 6 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/bg_selection_circle_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /native/src/base/include/base.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../xwrap.hpp" 4 | #include "../files.hpp" 5 | #include "../misc.hpp" 6 | #include "../logging.hpp" 7 | #include "../base-rs.hpp" 8 | 9 | using rust::xpipe2; 10 | using rust::fd_path; 11 | using kv_pairs = std::vector>; 12 | -------------------------------------------------------------------------------- /native/src/core/applet_stub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | if (argc < 1) 8 | return 1; 9 | cmdline_logging(); 10 | init_argv0(argc, argv); 11 | umask(0); 12 | return APPLET_STUB_MAIN(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_card_background_color_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_action_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 需要下载完整版 Magisk 才能正常运行。开始下载? 4 | 下载需要网络,请检查网络连接。 5 | 正在下载 6 | 请重新打开本应用 7 | 8 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-lt/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Atsinaujinkite į pilną Magisk Manager versiją, kad baigtumėte pasiruošimą. Atsisiųsti ir instaliuoti? 3 | Prašome prisijungti prie interneto! Atsinaujinimas į pilną Magisk Manager versiją yra privalomas. 4 | 5 | -------------------------------------------------------------------------------- /app/stub/src/main/java/com/topjohnwu/magisk/dummy/DummyService.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dummy; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | public class DummyService extends Service { 8 | @Override 9 | public IBinder onBind(Intent intent) { 10 | return null; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-ko/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 완전한 Magisk Manager로 업데이트하여 설치를 마치십시오. 다운로드하고 설치하시겠습니까? 3 | 인터넷에 연결해 주시기 바랍니다! 완전한 Magisk Manager로 업데이트 해야 합니다. 4 | 다운로드중 5 | 앱을 수동으로 재시작 하세요 6 | 7 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-mk/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Надградете до целосната верзија на Magisk Manager за да го завршите поставувањето. Преземете и инсталирајте? 3 | Ве молиме поврзете се на интернет бидејќи е потребна надградба на целосната верзија на Magisk Manager. 4 | 5 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_primary_error_transient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-iw/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | יש לעדכן לגירסה מלאה של מנהל Magisk בכדי לסיים את העדכון. להוריד ולהתקין? 4 | נא להתחבר לאינטרנט! עדכון לגירסה מלאה של מנהל Magisk נדרש. 5 | מוריד 6 | 7 | -------------------------------------------------------------------------------- /app/apk/src/main/res/color/color_menu_tint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/core/src/main/res/drawable/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | @Suppress("UnstableApiUsage") 2 | dependencyResolutionManagement { 3 | repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS 4 | repositories { 5 | google() 6 | mavenCentral() 7 | maven("https://jitpack.io") 8 | } 9 | } 10 | rootProject.name = "Magisk" 11 | include(":apk", ":core", ":shared", ":stub", ":test") 12 | -------------------------------------------------------------------------------- /app/stub/src/main/java/com/topjohnwu/magisk/dummy/DummyReceiver.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dummy; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | public class DummyReceiver extends BroadcastReceiver { 8 | @Override 9 | public void onReceive(Context context, Intent intent) {} 10 | } 11 | -------------------------------------------------------------------------------- /app/core/src/main/res/drawable-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/core/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #00AF9C 4 | #00796B 5 | #e0e0e0 6 | #e0e0e0 7 | @color/ic_launcher_background 8 | 9 | -------------------------------------------------------------------------------- /app/core/src/main/aidl/com/topjohnwu/magisk/core/utils/IRootUtils.aidl: -------------------------------------------------------------------------------- 1 | // IRootUtils.aidl 2 | package com.topjohnwu.magisk.core.utils; 3 | 4 | // Declare any non-default types here with import statements 5 | 6 | interface IRootUtils { 7 | android.app.ActivityManager.RunningAppProcessInfo getAppProcess(int pid); 8 | IBinder getFileSystem(); 9 | boolean addSystemlessHosts(); 10 | } 11 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-bg/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Надградете до пълната версия на Magisk Manager, за да довършите първоначалната настройка. Изтегляне и инсталиране сега? 3 | Моля да се свържете към работеща интернет мрежа, защото надграждането до пълната версия на Magisk Manager е задължително. 4 | 5 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-es/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Actualiza a la versión completa de Magisk para finalizar la instalación. ¿Descargar e instalar? 3 | Sin conexión disponible 4 | Descargando... 5 | Por favor, relanza la app 6 | 7 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-uk/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Оновіть додаток Magisk для завершення встановлення. Завантажити і встановити? 4 | Будь ласка, підключіться до Інтернету! Потрібно оновити додаток Magisk. 5 | Завантаження 6 | 7 | -------------------------------------------------------------------------------- /app/apk/src/main/res/menu/menu_flash.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/stub/src/main/res/values-ru/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Обновите Magisk для завершения установки. Продолжить? 3 | Пожалуйста, подключитесь к Интернету! Требуется обновление Magisk. 4 | Загрузка 5 | Пожалуйста, перезапустите приложение 6 | 7 | -------------------------------------------------------------------------------- /native/src/external/lz4-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lz4-sys" 3 | license = "MIT" 4 | version = "1.11.1+lz4-1.10.0" 5 | authors = [ "Jens Heyens ", "Artem V. Navrotskiy ", "Patrick Marks "] 6 | description = "Rust LZ4 sys package." 7 | repository = "https://github.com/10xGenomics/lz4-rs" 8 | 9 | [dependencies] 10 | libc = "0.2" 11 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/base/BaseJobService.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.base 2 | 3 | import android.app.job.JobService 4 | import android.content.Context 5 | import com.topjohnwu.magisk.core.patch 6 | 7 | abstract class BaseJobService : JobService() { 8 | override fun attachBaseContext(base: Context) { 9 | super.attachBaseContext(base.patch()) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /native/src/init/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "magiskinit" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | cxx-gen = { workspace = true } 12 | 13 | [dependencies] 14 | base = { path = "../base" } 15 | magiskpolicy = { path = "../sepolicy", default-features = false } 16 | cxx = { workspace = true } 17 | -------------------------------------------------------------------------------- /app/core/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /native/src/external/lzma-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lzma-sys" 3 | version = "0.1.20" 4 | authors = ["Alex Crichton "] 5 | license = "MIT/Apache-2.0" 6 | repository = "https://github.com/alexcrichton/xz2-rs" 7 | homepage = "https://github.com/alexcrichton/xz2-rs" 8 | documentation = "https://docs.rs/lzma-sys" 9 | description = """ 10 | Raw bindings to liblzma which contains an implementation of LZMA and xz stream 11 | encoding/decoding. 12 | 13 | High level Rust bindings are available in the `xz2` crate. 14 | """ 15 | categories = ["external-ffi-bindings"] 16 | edition = "2018" 17 | 18 | [dependencies] 19 | libc = "0.2.51" 20 | 21 | [features] 22 | static = [] 23 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_module_filled_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_search_md2.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /native/src/boot/build.rs: -------------------------------------------------------------------------------- 1 | use pb_rs::{ConfigBuilder, types::FileDescriptor}; 2 | 3 | use crate::codegen::gen_cxx_binding; 4 | 5 | #[path = "../include/codegen.rs"] 6 | mod codegen; 7 | 8 | fn main() { 9 | println!("cargo:rerun-if-changed=proto/update_metadata.proto"); 10 | 11 | gen_cxx_binding("boot-rs"); 12 | 13 | let cb = ConfigBuilder::new( 14 | &["proto/update_metadata.proto"], 15 | None, 16 | Some(&"proto"), 17 | &["."], 18 | ) 19 | .unwrap(); 20 | FileDescriptor::run( 21 | &cb.single_module(true) 22 | .dont_use_cow(true) 23 | .generate_getters(true) 24 | .build(), 25 | ) 26 | .unwrap(); 27 | } 28 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_restart.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/dialog/SecondSlotWarningDialog.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dialog 2 | 3 | import com.topjohnwu.magisk.core.R 4 | import com.topjohnwu.magisk.events.DialogBuilder 5 | import com.topjohnwu.magisk.view.MagiskDialog 6 | 7 | class SecondSlotWarningDialog : DialogBuilder { 8 | 9 | override fun build(dialog: MagiskDialog) { 10 | dialog.apply { 11 | setTitle(android.R.string.dialog_alert_title) 12 | setMessage(R.string.install_inactive_slot_msg) 13 | setButton(MagiskDialog.ButtonType.POSITIVE) { 14 | text = android.R.string.ok 15 | } 16 | setCancelable(true) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/ui/install/InstallFragment.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.ui.install 2 | 3 | import com.topjohnwu.magisk.R 4 | import com.topjohnwu.magisk.arch.BaseFragment 5 | import com.topjohnwu.magisk.arch.viewModel 6 | import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding 7 | import com.topjohnwu.magisk.core.R as CoreR 8 | 9 | class InstallFragment : BaseFragment() { 10 | 11 | override val layoutRes = R.layout.fragment_install_md2 12 | override val viewModel by viewModel() 13 | 14 | override fun onStart() { 15 | super.onStart() 16 | requireActivity().setTitle(CoreR.string.install) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_spinner.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/ktx/XSU.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.ktx 2 | 3 | import com.topjohnwu.magisk.core.Config 4 | import com.topjohnwu.superuser.Shell 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.withContext 7 | 8 | fun reboot(reason: String = if (Config.recovery) "recovery" else "") { 9 | if (reason == "recovery") { 10 | // KEYCODE_POWER = 26, hide incorrect "Factory data reset" message 11 | Shell.cmd("/system/bin/input keyevent 26").submit() 12 | } 13 | Shell.cmd("/system/bin/svc power reboot $reason || /system/bin/reboot $reason").submit() 14 | } 15 | 16 | suspend fun Shell.Job.await() = withContext(Dispatchers.IO) { exec() } 17 | -------------------------------------------------------------------------------- /app/test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | kotlin("android") 4 | } 5 | 6 | android { 7 | namespace = "com.topjohnwu.magisk.test" 8 | 9 | defaultConfig { 10 | applicationId = "com.topjohnwu.magisk.test" 11 | versionCode = 1 12 | versionName = "1.0" 13 | proguardFile("proguard-rules.pro") 14 | } 15 | 16 | buildTypes { 17 | release { 18 | isMinifyEnabled = true 19 | } 20 | } 21 | } 22 | 23 | setupTestApk() 24 | 25 | dependencies { 26 | implementation(libs.test.runner) 27 | implementation(libs.test.rules) 28 | implementation(libs.test.junit) 29 | implementation(libs.test.uiautomator) 30 | } 31 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/arch/AsyncLoadViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.arch 2 | 3 | import androidx.annotation.MainThread 4 | import androidx.lifecycle.viewModelScope 5 | import kotlinx.coroutines.Job 6 | import kotlinx.coroutines.launch 7 | 8 | abstract class AsyncLoadViewModel : BaseViewModel() { 9 | 10 | private var loadingJob: Job? = null 11 | 12 | @MainThread 13 | fun startLoading() { 14 | if (loadingJob?.isActive == true) { 15 | // Prevent multiple jobs from running at the same time 16 | return 17 | } 18 | loadingJob = viewModelScope.launch { doLoadWork() } 19 | } 20 | 21 | protected abstract suspend fun doLoadWork() 22 | } 23 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_console_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/utils/RequestAuthentication.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.utils 2 | 3 | import android.app.Activity 4 | import android.app.KeyguardManager 5 | import android.content.Context 6 | import android.content.Intent 7 | import androidx.activity.result.contract.ActivityResultContract 8 | 9 | class RequestAuthentication: ActivityResultContract() { 10 | 11 | override fun createIntent(context: Context, input: Unit) = 12 | context.getSystemService(KeyguardManager::class.java) 13 | .createConfirmDeviceCredentialIntent(null, null) 14 | 15 | override fun parseResult(resultCode: Int, intent: Intent?) = 16 | resultCode == Activity.RESULT_OK 17 | } 18 | -------------------------------------------------------------------------------- /native/src/init/preload.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "init.hpp" 6 | 7 | __attribute__((constructor)) 8 | static void preload_init() { 9 | // Make sure our next exec won't get bugged 10 | unsetenv("LD_PRELOAD"); 11 | unlink(PRELOAD_LIB); 12 | } 13 | 14 | int security_load_policy(void *data, size_t len) { 15 | int policy = open(PRELOAD_POLICY, O_WRONLY | O_CREAT, 0644); 16 | if (policy < 0) return -1; 17 | 18 | // Write the policy 19 | write(policy, data, len); 20 | close(policy); 21 | 22 | // Wait for ack 23 | int ack = open(PRELOAD_ACK, O_RDONLY); 24 | char c; 25 | read(ack, &c, 1); 26 | close(ack); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_day.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/core/src/main/res/values/resources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Magisk 6 | Zygisk 7 | 8 | 9 | PayPal 10 | Patreon 11 | Twitter 12 | GitHub 13 | 14 | @drawable/ic_logo 15 | 16 | true 17 | 18 | 19 | -------------------------------------------------------------------------------- /native/src/core/build.rs: -------------------------------------------------------------------------------- 1 | use pb_rs::{ConfigBuilder, types::FileDescriptor}; 2 | 3 | use crate::codegen::gen_cxx_binding; 4 | 5 | #[path = "../include/codegen.rs"] 6 | mod codegen; 7 | 8 | fn main() { 9 | println!("cargo:rerun-if-changed=resetprop/proto/persistent_properties.proto"); 10 | 11 | gen_cxx_binding("core-rs"); 12 | 13 | let cb = ConfigBuilder::new( 14 | &["resetprop/proto/persistent_properties.proto"], 15 | None, 16 | Some(&"resetprop/proto"), 17 | &["."], 18 | ) 19 | .unwrap(); 20 | FileDescriptor::run( 21 | &cb.single_module(true) 22 | .dont_use_cow(true) 23 | .generate_getters(true) 24 | .build(), 25 | ) 26 | .unwrap(); 27 | } 28 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /native/src/base/new.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Override libc++ new implementation 5 | * to optimize final build size */ 6 | 7 | void* operator new(std::size_t s) { return std::malloc(s); } 8 | void* operator new[](std::size_t s) { return std::malloc(s); } 9 | void operator delete(void *p) { std::free(p); } 10 | void operator delete[](void *p) { std::free(p); } 11 | void* operator new(std::size_t s, const std::nothrow_t&) noexcept { return std::malloc(s); } 12 | void* operator new[](std::size_t s, const std::nothrow_t&) noexcept { return std::malloc(s); } 13 | void operator delete(void *p, const std::nothrow_t&) noexcept { std::free(p); } 14 | void operator delete[](void *p, const std::nothrow_t&) noexcept { std::free(p); } 15 | -------------------------------------------------------------------------------- /native/src/core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "magisk" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | path = "lib.rs" 9 | 10 | [features] 11 | default = ["check-signature"] 12 | check-signature = [] 13 | 14 | [build-dependencies] 15 | cxx-gen = { workspace = true } 16 | pb-rs = { workspace = true } 17 | 18 | [dependencies] 19 | base = { path = "../base", features = ["selinux"] } 20 | derive = { path = "derive" } 21 | cxx = { workspace = true } 22 | num-traits = { workspace = true } 23 | num-derive = { workspace = true } 24 | quick-protobuf = { workspace = true } 25 | bytemuck = { workspace = true, features = ["derive"] } 26 | thiserror = { workspace = true } 27 | bit-set = { workspace = true } 28 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_forth_md2.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /scripts/module_installer.sh: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.4+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk 31 | 32 | install_module 33 | exit 0 34 | -------------------------------------------------------------------------------- /app/buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.KotlinVersion 2 | 3 | plugins { 4 | `kotlin-dsl` 5 | } 6 | 7 | repositories { 8 | google() 9 | mavenCentral() 10 | } 11 | 12 | gradlePlugin { 13 | plugins { 14 | register("MagiskPlugin") { 15 | id = "MagiskPlugin" 16 | implementationClass = "MagiskPlugin" 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation(kotlin("gradle-plugin", libs.versions.kotlin.get())) 23 | implementation(libs.android.gradle.plugin) 24 | implementation(libs.ksp.plugin) 25 | implementation(libs.navigation.safe.args.plugin) 26 | implementation(libs.lsparanoid.plugin) 27 | implementation(libs.moshi.plugin) 28 | implementation(libs.jgit) 29 | } 30 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/StringDao.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.data.magiskdb 2 | 3 | class StringDao : MagiskDB() { 4 | 5 | suspend fun delete(key: String) { 6 | val query = "DELETE FROM ${Table.STRINGS} WHERE key=\"$key\"" 7 | exec(query) 8 | } 9 | 10 | suspend fun put(key: String, value: String) { 11 | val kv = mapOf("key" to key, "value" to value) 12 | val query = "REPLACE INTO ${Table.STRINGS} ${kv.toQuery()}" 13 | exec(query) 14 | } 15 | 16 | suspend fun fetch(key: String, default: String = ""): String { 17 | val query = "SELECT value FROM ${Table.STRINGS} WHERE key=\"$key\" LIMIT 1" 18 | return exec(query) { it["value"] }.firstOrNull() ?: default 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/data/magiskdb/SettingsDao.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.data.magiskdb 2 | 3 | class SettingsDao : MagiskDB() { 4 | 5 | suspend fun delete(key: String) { 6 | val query = "DELETE FROM ${Table.SETTINGS} WHERE key=\"$key\"" 7 | exec(query) 8 | } 9 | 10 | suspend fun put(key: String, value: Int) { 11 | val kv = mapOf("key" to key, "value" to value) 12 | val query = "REPLACE INTO ${Table.SETTINGS} ${kv.toQuery()}" 13 | exec(query) 14 | } 15 | 16 | suspend fun fetch(key: String, default: Int = -1): Int { 17 | val query = "SELECT value FROM ${Table.SETTINGS} WHERE key=\"$key\" LIMIT 1" 18 | return exec(query) { it["value"]?.toInt() }.firstOrNull() ?: default 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_bug_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 12 | 13 | 17 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_home_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 12 | 13 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/markdown_window_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/apk/src/main/res/values-v27/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 13 | 14 | 17 | 18 | 23 | 24 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /native/src/boot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "magiskboot" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | cxx-gen = { workspace = true } 12 | pb-rs = { workspace = true } 13 | 14 | [dependencies] 15 | base = { path = "../base" } 16 | cxx = { workspace = true } 17 | byteorder = { workspace = true } 18 | size = { workspace = true } 19 | quick-protobuf = { workspace = true } 20 | argh = { workspace = true } 21 | sha1 = { workspace = true } 22 | sha2 = { workspace = true } 23 | digest = { workspace = true } 24 | p256 = { workspace = true } 25 | p384 = { workspace = true } 26 | p521 = { workspace = true } 27 | rsa = { workspace = true, features = ["sha2"] } 28 | x509-cert = { workspace = true } 29 | der = { workspace = true, features = ["derive", "pem"] } 30 | fdt = { workspace = true } 31 | bytemuck = { workspace = true, features = ["derive", "min_const_generics"] } 32 | num-traits = { workspace = true } 33 | flate2 = { workspace = true, features = ["zlib-rs"] } 34 | bzip2 = { workspace = true } 35 | lz4 = { workspace = true } 36 | xz2 = { workspace = true } 37 | zopfli = { workspace = true, features = ["gzip"] } 38 | -------------------------------------------------------------------------------- /app/shared/src/main/java/com/topjohnwu/magisk/ProviderInstaller.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | 6 | public class ProviderInstaller { 7 | 8 | private static final String GMS_PACKAGE_NAME = "com.google.android.gms"; 9 | 10 | public static void install(Context context) { 11 | try { 12 | // Check if gms is a system app 13 | ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(GMS_PACKAGE_NAME, 0); 14 | if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 15 | return; 16 | } 17 | 18 | // Try installing new SSL provider from Google Play Service 19 | Context gms = context.createPackageContext(GMS_PACKAGE_NAME, 20 | Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 21 | gms.getClassLoader() 22 | .loadClass("com.google.android.gms.common.security.ProviderInstallerImpl") 23 | .getMethod("insertProvider", Context.class) 24 | .invoke(null, gms); 25 | } catch (Exception ignored) { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_list_single_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | 17 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/dialog/ManagerInstallDialog.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dialog 2 | 3 | import com.topjohnwu.magisk.core.AppContext 4 | import com.topjohnwu.magisk.core.Info 5 | import com.topjohnwu.magisk.core.R 6 | import com.topjohnwu.magisk.core.download.DownloadEngine 7 | import com.topjohnwu.magisk.core.download.Subject 8 | import com.topjohnwu.magisk.view.MagiskDialog 9 | import java.io.File 10 | 11 | class ManagerInstallDialog : MarkDownDialog() { 12 | 13 | override suspend fun getMarkdownText(): String { 14 | val text = Info.update.note 15 | // Cache the changelog 16 | File(AppContext.cacheDir, "${Info.update.versionCode}.md").writeText(text) 17 | return text 18 | } 19 | 20 | override fun build(dialog: MagiskDialog) { 21 | super.build(dialog) 22 | dialog.apply { 23 | setCancelable(true) 24 | setButton(MagiskDialog.ButtonType.POSITIVE) { 25 | text = R.string.install 26 | onClick { DownloadEngine.startWithActivity(activity, Subject.App()) } 27 | } 28 | setButton(MagiskDialog.ButtonType.NEGATIVE) { 29 | text = android.R.string.cancel 30 | } 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_settings_filled_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/stub/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 | -obfuscationdictionary ../dict.txt 24 | -classobfuscationdictionary ../dict.txt 25 | -packageobfuscationdictionary ../dict.txt 26 | 27 | # Excessive obfuscation 28 | -repackageclasses 29 | -allowaccessmodification 30 | -keepclassmembers class com.topjohnwu.magisk.dummy.* { (); } 31 | -keepclassmembers class com.topjohnwu.magisk.DownloadActivity { (); } 32 | -keepclassmembers class com.topjohnwu.magisk.StubRootService { (); } 33 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/utils/ProgressInputStream.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.utils 2 | 3 | import java.io.FilterInputStream 4 | import java.io.InputStream 5 | 6 | class ProgressInputStream( 7 | base: InputStream, 8 | val progressEmitter: (Long) -> Unit 9 | ) : FilterInputStream(base) { 10 | 11 | private var bytesRead = 0L 12 | private var lastUpdate = 0L 13 | 14 | private fun emitProgress() { 15 | val cur = System.currentTimeMillis() 16 | if (cur - lastUpdate > 1000) { 17 | lastUpdate = cur 18 | progressEmitter(bytesRead) 19 | } 20 | } 21 | 22 | override fun read(): Int { 23 | val b = read() 24 | if (b >= 0) { 25 | bytesRead++ 26 | emitProgress() 27 | } 28 | return b 29 | } 30 | 31 | override fun read(b: ByteArray): Int { 32 | return read(b, 0, b.size) 33 | } 34 | 35 | override fun read(b: ByteArray, off: Int, len: Int): Int { 36 | val sz = super.read(b, off, len) 37 | if (sz > 0) { 38 | bytesRead += sz 39 | emitProgress() 40 | } 41 | return sz 42 | } 43 | 44 | override fun close() { 45 | super.close() 46 | progressEmitter(bytesRead) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/utils/RequestInstall.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.utils 2 | 3 | import android.annotation.TargetApi 4 | import android.app.Activity 5 | import android.content.Context 6 | import android.content.Intent 7 | import android.net.Uri 8 | import android.os.Build 9 | import android.provider.Settings 10 | import androidx.activity.result.contract.ActivityResultContract 11 | 12 | class RequestInstall : ActivityResultContract() { 13 | 14 | @TargetApi(26) 15 | override fun createIntent(context: Context, input: Unit): Intent { 16 | // This will only be called on API 26+ 17 | return Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) 18 | .setData(Uri.parse("package:${context.packageName}")) 19 | } 20 | 21 | override fun parseResult(resultCode: Int, intent: Intent?) = 22 | resultCode == Activity.RESULT_OK 23 | 24 | override fun getSynchronousResult( 25 | context: Context, 26 | input: Unit 27 | ): SynchronousResult? { 28 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) 29 | return SynchronousResult(true) 30 | if (context.packageManager.canRequestPackageInstalls()) 31 | return SynchronousResult(true) 32 | return null 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/apk/src/main/res/values/themes_override.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 14 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/dialog/LocalModuleInstallDialog.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dialog 2 | 3 | import android.net.Uri 4 | import com.topjohnwu.magisk.MainDirections 5 | import com.topjohnwu.magisk.core.Const 6 | import com.topjohnwu.magisk.core.R 7 | import com.topjohnwu.magisk.events.DialogBuilder 8 | import com.topjohnwu.magisk.ui.module.ModuleViewModel 9 | import com.topjohnwu.magisk.view.MagiskDialog 10 | 11 | class LocalModuleInstallDialog( 12 | private val viewModel: ModuleViewModel, 13 | private val uri: Uri, 14 | private val displayName: String 15 | ) : DialogBuilder { 16 | override fun build(dialog: MagiskDialog) { 17 | dialog.apply { 18 | setTitle(R.string.confirm_install_title) 19 | setMessage(context.getString(R.string.confirm_install, displayName)) 20 | setButton(MagiskDialog.ButtonType.POSITIVE) { 21 | text = android.R.string.ok 22 | onClick { 23 | viewModel.apply { 24 | MainDirections.actionFlashFragment(Const.Value.FLASH_ZIP, uri).navigate() 25 | } 26 | } 27 | } 28 | setButton(MagiskDialog.ButtonType.NEGATIVE) { 29 | text = android.R.string.cancel 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/test/src/main/java/com/topjohnwu/magisk/test/Runners.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.test 2 | 3 | import android.os.Bundle 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import androidx.test.runner.AndroidJUnitRunner 6 | 7 | open class TestRunner : AndroidJUnitRunner() { 8 | override fun onCreate(arguments: Bundle) { 9 | // Support short-hand ".ClassName" 10 | arguments.getString("class")?.let { 11 | val classArg = it.split(",").joinToString(separator = ",") { clz -> 12 | if (clz.startsWith(".")) { 13 | "com.topjohnwu.magisk.test$clz" 14 | } else { 15 | clz 16 | } 17 | } 18 | arguments.putString("class", classArg) 19 | } 20 | super.onCreate(arguments) 21 | } 22 | } 23 | 24 | class AppTestRunner : TestRunner() { 25 | override fun onCreate(arguments: Bundle) { 26 | // Force using the target context's classloader to run tests 27 | arguments.putString("classLoader", TestClassLoader::class.java.name) 28 | super.onCreate(arguments) 29 | } 30 | } 31 | 32 | private val targetClassLoader inline get() = 33 | InstrumentationRegistry.getInstrumentation().targetContext.classLoader 34 | 35 | class TestClassLoader : ClassLoader(targetClassLoader) 36 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_icon_link.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 15 | 16 | 17 | 18 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserFragment.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.ui.superuser 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import com.topjohnwu.magisk.R 6 | import com.topjohnwu.magisk.arch.BaseFragment 7 | import com.topjohnwu.magisk.arch.viewModel 8 | import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding 9 | import rikka.recyclerview.addEdgeSpacing 10 | import rikka.recyclerview.addItemSpacing 11 | import rikka.recyclerview.fixEdgeEffect 12 | import com.topjohnwu.magisk.core.R as CoreR 13 | 14 | class SuperuserFragment : BaseFragment() { 15 | 16 | override val layoutRes = R.layout.fragment_superuser_md2 17 | override val viewModel by viewModel() 18 | 19 | override fun onStart() { 20 | super.onStart() 21 | activity?.title = resources.getString(CoreR.string.superuser) 22 | } 23 | 24 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 25 | super.onViewCreated(view, savedInstanceState) 26 | 27 | binding.superuserList.apply { 28 | addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1) 29 | addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) 30 | fixEdgeEffect() 31 | } 32 | } 33 | 34 | override fun onPreBind(binding: FragmentSuperuserMd2Binding) {} 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/core/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Parcelable 2 | -keepclassmembers class * implements android.os.Parcelable { 3 | public static final ** CREATOR; 4 | } 5 | 6 | # Kotlin 7 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics { 8 | public static void check*(...); 9 | public static void throw*(...); 10 | } 11 | -assumenosideeffects class java.util.Objects { 12 | public static ** requireNonNull(...); 13 | } 14 | -assumenosideeffects public class kotlin.coroutines.jvm.internal.DebugMetadataKt { 15 | private static ** getDebugMetadataAnnotation(...) return null; 16 | } 17 | 18 | # Stub 19 | -keep class com.topjohnwu.magisk.core.App { (java.lang.Object); } 20 | -keepclassmembers class androidx.appcompat.app.AppCompatDelegateImpl { 21 | boolean mActivityHandlesConfigFlagsChecked; 22 | int mActivityHandlesConfigFlags; 23 | } 24 | 25 | # Strip Timber verbose and debug logging 26 | -assumenosideeffects class timber.log.Timber$Tree { 27 | public void v(**); 28 | public void d(**); 29 | } 30 | 31 | # With R8 full mode generic signatures are stripped for classes that are not 32 | # kept. Suspend functions are wrapped in continuations where the type argument 33 | # is used. 34 | -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation 35 | 36 | # Excessive obfuscation 37 | -flattenpackagehierarchy 38 | -allowaccessmodification 39 | 40 | -dontwarn org.junit.** 41 | -dontwarn org.apache.** 42 | -------------------------------------------------------------------------------- /native/src/Android-rs.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | ########################### 4 | # Rust compilation outputs 5 | ########################### 6 | 7 | include $(CLEAR_VARS) 8 | LOCAL_MODULE := magisk-rs 9 | LOCAL_EXPORT_C_INCLUDES := src/core/include 10 | LOCAL_LIB = ../out/$(TARGET_ARCH_ABI)/libmagisk-rs.a 11 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_LIB))) 12 | LOCAL_SRC_FILES := $(LOCAL_LIB) 13 | include $(PREBUILT_STATIC_LIBRARY) 14 | else 15 | include $(BUILD_STATIC_LIBRARY) 16 | endif 17 | 18 | include $(CLEAR_VARS) 19 | LOCAL_MODULE := boot-rs 20 | LOCAL_LIB = ../out/$(TARGET_ARCH_ABI)/libmagiskboot-rs.a 21 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_LIB))) 22 | LOCAL_SRC_FILES := $(LOCAL_LIB) 23 | include $(PREBUILT_STATIC_LIBRARY) 24 | else 25 | include $(BUILD_STATIC_LIBRARY) 26 | endif 27 | 28 | include $(CLEAR_VARS) 29 | LOCAL_MODULE := init-rs 30 | LOCAL_LIB = ../out/$(TARGET_ARCH_ABI)/libmagiskinit-rs.a 31 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_LIB))) 32 | LOCAL_SRC_FILES := $(LOCAL_LIB) 33 | include $(PREBUILT_STATIC_LIBRARY) 34 | else 35 | include $(BUILD_STATIC_LIBRARY) 36 | endif 37 | 38 | include $(CLEAR_VARS) 39 | LOCAL_MODULE := policy-rs 40 | LOCAL_LIB = ../out/$(TARGET_ARCH_ABI)/libmagiskpolicy-rs.a 41 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_LIB))) 42 | LOCAL_SRC_FILES := $(LOCAL_LIB) 43 | include $(PREBUILT_STATIC_LIBRARY) 44 | else 45 | include $(BUILD_STATIC_LIBRARY) 46 | endif 47 | -------------------------------------------------------------------------------- /native/src/core/include/resetprop.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct prop_cb { 8 | virtual void exec(const char *name, const char *value, uint32_t serial) = 0; 9 | }; 10 | 11 | using prop_list = std::map; 12 | 13 | struct prop_collector : prop_cb { 14 | explicit prop_collector(prop_list &list) : list(list) {} 15 | void exec(const char *name, const char *value, uint32_t) override { 16 | list.insert({name, value}); 17 | } 18 | private: 19 | prop_list &list; 20 | }; 21 | 22 | // System properties 23 | std::string get_prop(const char *name, bool persist = false); 24 | int delete_prop(const char *name, bool persist = false); 25 | int set_prop(const char *name, const char *value, bool skip_svc = false); 26 | void load_prop_file(const char *filename, bool skip_svc = false); 27 | 28 | // Rust bindings 29 | rust::String get_prop_rs(rust::Utf8CStr name, bool persist); 30 | static inline int set_prop_rs(rust::Utf8CStr name, rust::Utf8CStr value, bool skip_svc) { 31 | return set_prop(name.data(), value.data(), skip_svc); 32 | } 33 | static inline void load_prop_file_rs(rust::Utf8CStr filename, bool skip_svc) { 34 | load_prop_file(filename.data(), skip_svc); 35 | } 36 | static inline void prop_cb_exec(prop_cb &cb, rust::Utf8CStr name, rust::Utf8CStr value, uint32_t serial) { 37 | cb.exec(name.data(), value.data(), serial); 38 | } -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/ui/flash/ConsoleItem.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.ui.flash 2 | 3 | import android.view.View 4 | import android.widget.TextView 5 | import androidx.core.view.updateLayoutParams 6 | import androidx.databinding.ViewDataBinding 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.topjohnwu.magisk.R 9 | import com.topjohnwu.magisk.databinding.DiffItem 10 | import com.topjohnwu.magisk.databinding.ItemWrapper 11 | import com.topjohnwu.magisk.databinding.RvItem 12 | import com.topjohnwu.magisk.databinding.ViewAwareItem 13 | import kotlin.math.max 14 | 15 | class ConsoleItem( 16 | override val item: String 17 | ) : RvItem(), ViewAwareItem, DiffItem, ItemWrapper { 18 | override val layoutRes = R.layout.item_console_md2 19 | 20 | private var parentWidth = -1 21 | 22 | override fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView) { 23 | if (parentWidth < 0) 24 | parentWidth = (recyclerView.parent as View).width 25 | 26 | val view = binding.root as TextView 27 | view.measure(0, 0) 28 | 29 | // We want our recyclerView at least as wide as screen 30 | val desiredWidth = max(view.measuredWidth, parentWidth) 31 | 32 | view.updateLayoutParams { width = desiredWidth } 33 | 34 | if (recyclerView.width < desiredWidth) { 35 | recyclerView.requestLayout() 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_manager.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /native/src/include/codegen.rs: -------------------------------------------------------------------------------- 1 | // This file hosts shared build script logic 2 | 3 | use std::fmt::Display; 4 | use std::fs::File; 5 | use std::io::Write; 6 | use std::path::Path; 7 | use std::{fs, io, process}; 8 | 9 | use cxx_gen::Opt; 10 | 11 | trait ResultExt { 12 | fn ok_or_exit(self) -> T; 13 | } 14 | 15 | impl ResultExt for Result { 16 | fn ok_or_exit(self) -> T { 17 | match self { 18 | Ok(r) => r, 19 | Err(e) => { 20 | eprintln!("error occurred: {e}"); 21 | process::exit(1); 22 | } 23 | } 24 | } 25 | } 26 | 27 | fn write_if_diff>(path: P, bytes: &[u8]) -> io::Result<()> { 28 | let path = path.as_ref(); 29 | if let Ok(orig) = fs::read(path) { 30 | // Do not modify the file if content is the same to make incremental build more optimal 31 | if orig.as_slice() == bytes { 32 | return Ok(()); 33 | } 34 | } 35 | let mut f = File::create(path)?; 36 | f.write_all(bytes) 37 | } 38 | 39 | pub fn gen_cxx_binding(name: &str) { 40 | println!("cargo:rerun-if-changed=lib.rs"); 41 | let opt = Opt::default(); 42 | let code = cxx_gen::generate_header_and_cc_with_path("lib.rs", &opt); 43 | write_if_diff(format!("{name}.cpp"), code.implementation.as_slice()).ok_or_exit(); 44 | write_if_diff(format!("{name}.hpp"), code.header.as_slice()).ok_or_exit(); 45 | } 46 | -------------------------------------------------------------------------------- /app/apk/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/item_settings_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 19 | 20 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/stub/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("org.lsposed.lsparanoid") 4 | } 5 | 6 | lsparanoid { 7 | seed = if (RAND_SEED != 0) RAND_SEED else null 8 | includeDependencies = true 9 | classFilter = { true } 10 | } 11 | 12 | android { 13 | namespace = "com.topjohnwu.magisk" 14 | 15 | val canary = !Config.version.contains(".") 16 | val base = "https://github.com/topjohnwu/Magisk/releases/download/" 17 | val url = base + "v${Config.version}/Magisk-v${Config.version}.apk" 18 | val canaryUrl = base + "canary-${Config.versionCode}/" 19 | 20 | defaultConfig { 21 | applicationId = "com.topjohnwu.magisk" 22 | versionCode = 1 23 | versionName = "1.0" 24 | buildConfigField("String", "APK_URL", "\"$url\"") 25 | buildConfigField("int", "STUB_VERSION", Config.stubVersion) 26 | } 27 | 28 | buildTypes { 29 | release { 30 | if (canary) buildConfigField("String", "APK_URL", "\"${canaryUrl}app-release.apk\"") 31 | proguardFiles("proguard-rules.pro") 32 | isMinifyEnabled = true 33 | isShrinkResources = false 34 | } 35 | debug { 36 | if (canary) buildConfigField("String", "APK_URL", "\"${canaryUrl}app-debug.apk\"") 37 | } 38 | } 39 | 40 | buildFeatures { 41 | buildConfig = true 42 | } 43 | } 44 | 45 | setupStubApk() 46 | 47 | dependencies { 48 | implementation(project(":shared")) 49 | } 50 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.ui.settings 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import com.topjohnwu.magisk.R 6 | import com.topjohnwu.magisk.arch.BaseFragment 7 | import com.topjohnwu.magisk.arch.viewModel 8 | import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding 9 | import rikka.recyclerview.addEdgeSpacing 10 | import rikka.recyclerview.addItemSpacing 11 | import rikka.recyclerview.fixEdgeEffect 12 | import com.topjohnwu.magisk.core.R as CoreR 13 | 14 | class SettingsFragment : BaseFragment() { 15 | 16 | override val layoutRes = R.layout.fragment_settings_md2 17 | override val viewModel by viewModel() 18 | override val snackbarView: View get() = binding.snackbarContainer 19 | 20 | override fun onStart() { 21 | super.onStart() 22 | 23 | activity?.title = resources.getString(CoreR.string.settings) 24 | } 25 | 26 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 27 | super.onViewCreated(view, savedInstanceState) 28 | binding.settingsList.apply { 29 | addEdgeSpacing(bottom = R.dimen.l1) 30 | addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) 31 | fixEdgeEffect() 32 | } 33 | } 34 | 35 | override fun onResume() { 36 | super.onResume() 37 | viewModel.items.forEach { it.refresh() } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/core/src/main/res/drawable/ic_paypal.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /tools/keys/verity.x509.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID/TCCAuWgAwIBAgIJAJcPmDkJqolJMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD 3 | VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g 4 | VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE 5 | AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe 6 | Fw0xNDExMDYxOTA3NDBaFw00MjAzMjQxOTA3NDBaMIGUMQswCQYDVQQGEwJVUzET 7 | MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G 8 | A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p 9 | ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZI 10 | hvcNAQEBBQADggEPADCCAQoCggEBAOjreE0vTVSRenuzO9vnaWfk0eQzYab0gqpi 11 | 6xAzi6dmD+ugoEKJmbPiuE5Dwf21isZ9uhUUu0dQM46dK4ocKxMRrcnmGxydFn6o 12 | fs3ODJMXOkv2gKXL/FdbEPdDbxzdu8z3yk+W67udM/fW7WbaQ3DO0knu+izKak/3 13 | T41c5uoXmQ81UNtAzRGzGchNVXMmWuTGOkg6U+0I2Td7K8yvUMWhAWPPpKLtVH9r 14 | AL5TzjYNR92izdKcz3AjRsI3CTjtpiVABGeX0TcjRSuZB7K9EK56HV+OFNS6I1NP 15 | jdD7FIShyGlqqZdUOkAUZYanbpgeT5N7QL6uuqcGpoTOkalu6kkCAwEAAaNQME4w 16 | HQYDVR0OBBYEFH5DM/m7oArf4O3peeKO0ZIEkrQPMB8GA1UdIwQYMBaAFH5DM/m7 17 | oArf4O3peeKO0ZIEkrQPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB 18 | AHO3NSvDE5jFvMehGGtS8BnFYdFKRIglDMc4niWSzhzOVYRH4WajxdtBWc5fx0ix 19 | NF/+hVKVhP6AIOQa+++sk+HIi7RvioPPbhjcsVlZe7cUEGrLSSveGouQyc+j0+m6 20 | JF84kszIl5GGNMTnx0XRPO+g8t6h5LWfnVydgZfpGRRg+WHewk1U2HlvTjIceb0N 21 | dcoJ8WKJAFWdcuE7VIm4w+vF/DYX/A2Oyzr2+QRhmYSv1cusgAeC1tvH4ap+J1Lg 22 | UnOu5Kh/FqPLLSwNVQp4Bu7b9QFfqK8Moj84bj88NqRGZgDyqzuTrFxn6FW7dmyA 23 | yttuAJAEAymk1mipd9+zp38= 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | 32 | 33 | Device: 34 | Android version: 35 | Magisk version name: 36 | Magisk version code: 37 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/dialog/MarkDownDialog.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.dialog 2 | 3 | import android.view.LayoutInflater 4 | import android.widget.TextView 5 | import androidx.annotation.CallSuper 6 | import androidx.lifecycle.lifecycleScope 7 | import com.topjohnwu.magisk.R 8 | import com.topjohnwu.magisk.core.di.ServiceLocator 9 | import com.topjohnwu.magisk.events.DialogBuilder 10 | import com.topjohnwu.magisk.view.MagiskDialog 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.launch 13 | import kotlinx.coroutines.withContext 14 | import timber.log.Timber 15 | import java.io.IOException 16 | import com.topjohnwu.magisk.core.R as CoreR 17 | 18 | abstract class MarkDownDialog : DialogBuilder { 19 | 20 | abstract suspend fun getMarkdownText(): String 21 | 22 | @CallSuper 23 | override fun build(dialog: MagiskDialog) { 24 | with(dialog) { 25 | val view = LayoutInflater.from(context).inflate(R.layout.markdown_window_md2, null) 26 | setView(view) 27 | val tv = view.findViewById(R.id.md_txt) 28 | activity.lifecycleScope.launch { 29 | try { 30 | val text = withContext(Dispatchers.IO) { getMarkdownText() } 31 | ServiceLocator.markwon.setMarkdown(tv, text) 32 | } catch (e: IOException) { 33 | Timber.e(e) 34 | tv.setText(CoreR.string.download_file_error) 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.ui.theme 2 | 3 | import com.topjohnwu.magisk.R 4 | import com.topjohnwu.magisk.core.Config 5 | 6 | enum class Theme( 7 | val themeName: String, 8 | val themeRes: Int 9 | ) { 10 | 11 | Piplup( 12 | themeName = "Piplup", 13 | themeRes = R.style.ThemeFoundationMD2_Piplup 14 | ), 15 | PiplupAmoled( 16 | themeName = "AMOLED", 17 | themeRes = R.style.ThemeFoundationMD2_Amoled 18 | ), 19 | Rayquaza( 20 | themeName = "Rayquaza", 21 | themeRes = R.style.ThemeFoundationMD2_Rayquaza 22 | ), 23 | Zapdos( 24 | themeName = "Zapdos", 25 | themeRes = R.style.ThemeFoundationMD2_Zapdos 26 | ), 27 | Charmeleon( 28 | themeName = "Charmeleon", 29 | themeRes = R.style.ThemeFoundationMD2_Charmeleon 30 | ), 31 | Mew( 32 | themeName = "Mew", 33 | themeRes = R.style.ThemeFoundationMD2_Mew 34 | ), 35 | Salamence( 36 | themeName = "Salamence", 37 | themeRes = R.style.ThemeFoundationMD2_Salamence 38 | ), 39 | Fraxure( 40 | themeName = "Fraxure (Legacy)", 41 | themeRes = R.style.ThemeFoundationMD2_Fraxure 42 | ); 43 | 44 | val isSelected get() = Config.themeOrdinal == ordinal 45 | 46 | fun select() { 47 | Config.themeOrdinal = ordinal 48 | } 49 | 50 | companion object { 51 | val selected get() = values().getOrNull(Config.themeOrdinal) ?: Piplup 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/stub/src/main/java/com/topjohnwu/magisk/net/BadRequest.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.net; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONObject; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | class BadRequest extends Request { 11 | 12 | private final IOException ex; 13 | 14 | BadRequest(IOException e) { super(null); ex = e; } 15 | 16 | @Override 17 | public Request addHeaders(String key, String value) { return this; } 18 | 19 | @Override 20 | public Result execForInputStream() { fail(); return new Result<>(); } 21 | 22 | @Override 23 | public void getAsFile(File out, ResponseListener rs) { fail(); } 24 | 25 | @Override 26 | public void execForFile(File out) { fail(); } 27 | 28 | @Override 29 | public void getAsString(ResponseListener rs) { fail(); } 30 | 31 | @Override 32 | public Result execForString() { fail(); return new Result<>(); } 33 | 34 | @Override 35 | public void getAsJSONObject(ResponseListener rs) { fail(); } 36 | 37 | @Override 38 | public Result execForJSONObject() { fail(); return new Result<>(); } 39 | 40 | @Override 41 | public void getAsJSONArray(ResponseListener rs) { fail(); } 42 | 43 | @Override 44 | public Result execForJSONArray() { fail(); return new Result<>(); } 45 | 46 | private void fail() { 47 | if (err != null) 48 | err.onError(null, ex); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/stub/src/main/java/com/topjohnwu/magisk/net/Networking.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.net; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | import android.os.Handler; 7 | import android.os.Looper; 8 | 9 | import java.io.IOException; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | 13 | public class Networking { 14 | 15 | private static final int READ_TIMEOUT = 15000; 16 | private static final int CONNECT_TIMEOUT = 15000; 17 | static Handler mainHandler = new Handler(Looper.getMainLooper()); 18 | 19 | private static Request request(String url, String method) { 20 | try { 21 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 22 | conn.setRequestMethod(method); 23 | conn.setReadTimeout(READ_TIMEOUT); 24 | conn.setConnectTimeout(CONNECT_TIMEOUT); 25 | return new Request(conn); 26 | } catch (IOException e) { 27 | return new BadRequest(e); 28 | } 29 | } 30 | 31 | public static Request get(String url) { 32 | return request(url, "GET"); 33 | } 34 | 35 | public static boolean checkNetworkStatus(Context context) { 36 | ConnectivityManager manager = (ConnectivityManager) 37 | context.getSystemService(Context.CONNECTIVITY_SERVICE); 38 | NetworkInfo networkInfo = manager.getActiveNetworkInfo(); 39 | return networkInfo != null && networkInfo.isConnected(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/apk/src/main/java/com/topjohnwu/magisk/utils/TextHolder.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.utils 2 | 3 | import android.content.res.Resources 4 | 5 | abstract class TextHolder { 6 | 7 | open val isEmpty: Boolean get() = false 8 | abstract fun getText(resources: Resources): CharSequence 9 | 10 | // --- 11 | 12 | class String( 13 | private val value: CharSequence 14 | ) : TextHolder() { 15 | override val isEmpty get() = value.isEmpty() 16 | override fun getText(resources: Resources) = value 17 | } 18 | 19 | open class Resource( 20 | protected val value: Int 21 | ) : TextHolder() { 22 | override val isEmpty get() = value == 0 23 | override fun getText(resources: Resources) = resources.getString(value) 24 | } 25 | 26 | class ResourceArgs( 27 | value: Int, 28 | private vararg val params: Any 29 | ) : Resource(value) { 30 | override fun getText(resources: Resources): kotlin.String { 31 | // Replace TextHolder with strings 32 | val args = params.map { if (it is TextHolder) it.getText(resources) else it } 33 | return resources.getString(value, *args.toTypedArray()) 34 | } 35 | } 36 | 37 | // --- 38 | 39 | companion object { 40 | val EMPTY = String("") 41 | } 42 | } 43 | 44 | fun Int.asText(): TextHolder = TextHolder.Resource(this) 45 | fun Int.asText(vararg params: Any): TextHolder = TextHolder.ResourceArgs(this, *params) 46 | fun CharSequence.asText(): TextHolder = TextHolder.String(this) 47 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/avd_home_from_filled.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 10 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/apk/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | kotlin("android") 4 | kotlin("plugin.parcelize") 5 | kotlin("kapt") 6 | id("androidx.navigation.safeargs.kotlin") 7 | } 8 | 9 | setupMainApk() 10 | 11 | kapt { 12 | correctErrorTypes = true 13 | useBuildCache = true 14 | mapDiagnosticLocations = true 15 | javacOptions { 16 | option("-Xmaxerrs", "1000") 17 | } 18 | } 19 | 20 | android { 21 | buildFeatures { 22 | dataBinding = true 23 | } 24 | 25 | compileOptions { 26 | isCoreLibraryDesugaringEnabled = true 27 | } 28 | 29 | buildTypes { 30 | release { 31 | isMinifyEnabled = true 32 | isShrinkResources = true 33 | } 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation(project(":core")) 39 | coreLibraryDesugaring(libs.jdk.libs) 40 | 41 | implementation(libs.indeterminate.checkbox) 42 | implementation(libs.rikka.layoutinflater) 43 | implementation(libs.rikka.insets) 44 | implementation(libs.rikka.recyclerview) 45 | 46 | implementation(libs.navigation.fragment.ktx) 47 | implementation(libs.navigation.ui.ktx) 48 | 49 | implementation(libs.constraintlayout) 50 | implementation(libs.swiperefreshlayout) 51 | implementation(libs.recyclerview) 52 | implementation(libs.transition) 53 | implementation(libs.fragment.ktx) 54 | implementation(libs.appcompat) 55 | implementation(libs.material) 56 | 57 | // Make sure kapt runs with a proper kotlin-stdlib 58 | kapt(kotlin("stdlib")) 59 | } 60 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/ic_settings_outlined_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/data/RetrofitInterfaces.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core.data 2 | 3 | import com.topjohnwu.magisk.core.model.ModuleJson 4 | import com.topjohnwu.magisk.core.model.Release 5 | import com.topjohnwu.magisk.core.model.UpdateJson 6 | import okhttp3.ResponseBody 7 | import retrofit2.Response 8 | import retrofit2.http.GET 9 | import retrofit2.http.Headers 10 | import retrofit2.http.Path 11 | import retrofit2.http.Query 12 | import retrofit2.http.Streaming 13 | import retrofit2.http.Url 14 | 15 | interface RawUrl { 16 | 17 | @GET 18 | @Streaming 19 | suspend fun fetchFile(@Url url: String): ResponseBody 20 | 21 | @GET 22 | suspend fun fetchString(@Url url: String): String 23 | 24 | @GET 25 | suspend fun fetchModuleJson(@Url url: String): ModuleJson 26 | 27 | @GET 28 | suspend fun fetchUpdateJson(@Url url: String): UpdateJson 29 | } 30 | 31 | interface GithubApiServices { 32 | 33 | @GET("/repos/{owner}/{repo}/releases") 34 | @Headers("Accept: application/vnd.github+json") 35 | suspend fun fetchReleases( 36 | @Path("owner") owner: String = "topjohnwu", 37 | @Path("repo") repo: String = "Magisk", 38 | @Query("per_page") per: Int = 10, 39 | @Query("page") page: Int = 1, 40 | ): Response> 41 | 42 | @GET("/repos/{owner}/{repo}/releases/latest") 43 | @Headers("Accept: application/vnd.github+json") 44 | suspend fun fetchLatestRelease( 45 | @Path("owner") owner: String = "topjohnwu", 46 | @Path("repo") repo: String = "Magisk", 47 | ): Release 48 | } 49 | -------------------------------------------------------------------------------- /native/src/external/xz-embedded/xz_crc32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CRC32 using the polynomial from IEEE-802.3 3 | * 4 | * Authors: Lasse Collin 5 | * Igor Pavlov 6 | * 7 | * This file has been put into the public domain. 8 | * You can do whatever you want with this file. 9 | */ 10 | 11 | /* 12 | * This is not the fastest implementation, but it is pretty compact. 13 | * The fastest versions of xz_crc32() on modern CPUs without hardware 14 | * accelerated CRC instruction are 3-5 times as fast as this version, 15 | * but they are bigger and use more memory for the lookup table. 16 | */ 17 | 18 | #include "xz_private.h" 19 | 20 | /* 21 | * STATIC_RW_DATA is used in the pre-boot environment on some architectures. 22 | * See for details. 23 | */ 24 | #ifndef STATIC_RW_DATA 25 | # define STATIC_RW_DATA static 26 | #endif 27 | 28 | STATIC_RW_DATA uint32_t xz_crc32_table[256]; 29 | 30 | XZ_EXTERN void xz_crc32_init(void) 31 | { 32 | const uint32_t poly = 0xEDB88320; 33 | 34 | uint32_t i; 35 | uint32_t j; 36 | uint32_t r; 37 | 38 | for (i = 0; i < 256; ++i) { 39 | r = i; 40 | for (j = 0; j < 8; ++j) 41 | r = (r >> 1) ^ (poly & ~((r & 1) - 1)); 42 | 43 | xz_crc32_table[i] = r; 44 | } 45 | 46 | return; 47 | } 48 | 49 | XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) 50 | { 51 | crc = ~crc; 52 | 53 | while (size != 0) { 54 | crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); 55 | --size; 56 | } 57 | 58 | return ~crc; 59 | } 60 | -------------------------------------------------------------------------------- /app/apk/src/main/res/drawable/avd_home_to_filled.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 10 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/apk/src/main/res/layout/fragment_theme_md2.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 25 | 26 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/core/src/main/java/com/topjohnwu/magisk/core/Service.kt: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk.core 2 | 3 | import android.app.Notification 4 | import android.content.Intent 5 | import android.os.Build 6 | import androidx.core.app.ServiceCompat 7 | import androidx.core.content.IntentCompat 8 | import com.topjohnwu.magisk.core.base.BaseService 9 | import com.topjohnwu.magisk.core.download.DownloadEngine 10 | import com.topjohnwu.magisk.core.download.DownloadSession 11 | import com.topjohnwu.magisk.core.download.Subject 12 | 13 | class Service : BaseService(), DownloadSession { 14 | 15 | private var mEngine: DownloadEngine? = null 16 | override val context get() = this 17 | 18 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { 19 | if (intent.action == DownloadEngine.ACTION) { 20 | IntentCompat 21 | .getParcelableExtra(intent, DownloadEngine.SUBJECT_KEY, Subject::class.java) 22 | ?.let { subject -> 23 | val engine = mEngine ?: DownloadEngine(this).also { mEngine = it } 24 | engine.download(subject) 25 | } 26 | } 27 | return START_NOT_STICKY 28 | } 29 | 30 | override fun attachNotification(id: Int, builder: Notification.Builder) { 31 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) 32 | builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE) 33 | startForeground(id, builder.build()) 34 | } 35 | 36 | override fun onDownloadComplete() { 37 | ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/stub/src/main/java/com/topjohnwu/magisk/StubRootService.java: -------------------------------------------------------------------------------- 1 | package com.topjohnwu.magisk; 2 | 3 | import android.content.Context; 4 | import android.content.ContextWrapper; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | import android.util.Log; 8 | 9 | import java.io.File; 10 | import java.lang.reflect.Constructor; 11 | 12 | public class StubRootService extends ContextWrapper { 13 | 14 | public StubRootService() { 15 | super(null); 16 | } 17 | 18 | @Override 19 | protected void attachBaseContext(Context base) { 20 | ClassLoader loader = DynLoad.loadApk(base); 21 | if (loader == null) 22 | return; 23 | 24 | try { 25 | // Create application to get the real root service class 26 | var data = DynLoad.createApkData(); 27 | File apk = StubApk.current(base); 28 | PackageManager pm = base.getPackageManager(); 29 | PackageInfo pkgInfo = pm.getPackageArchiveInfo(apk.getPath(), 0); 30 | loader.loadClass(pkgInfo.applicationInfo.className) 31 | .getConstructor(Object.class) 32 | .newInstance(data.getObject()); 33 | 34 | // Create the actual RootService and call its attachBaseContext 35 | Constructor ctor = data.getRootService().getConstructor(Object.class); 36 | ctor.setAccessible(true); 37 | Object service = ctor.newInstance(this); 38 | DynLoad.attachContext(service, base); 39 | } catch (Exception e) { 40 | Log.e(StubRootService.class.getSimpleName(), "", e); 41 | } 42 | } 43 | } 44 | --------------------------------------------------------------------------------