├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── config.yml
└── workflows
│ └── build.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.MD
├── app
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
├── shared
│ ├── .gitignore
│ ├── build.gradle.kts
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── topjohnwu
│ │ └── magisk
│ │ ├── ProviderInstaller.java
│ │ ├── StubApk.java
│ │ └── utils
│ │ ├── APKInstall.java
│ │ ├── CompoundEnumeration.java
│ │ └── DynamicClassLoader.java
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── aidl
│ └── com
│ │ └── topjohnwu
│ │ └── magisk
│ │ └── core
│ │ └── utils
│ │ └── IRootUtils.aidl
│ ├── java
│ ├── androidx
│ │ └── lifecycle
│ │ │ └── ProcessLifecycleAccessor.java
│ └── com
│ │ └── topjohnwu
│ │ └── magisk
│ │ ├── arch
│ │ ├── AsyncLoadViewModel.kt
│ │ ├── BaseFragment.kt
│ │ ├── BaseViewModel.kt
│ │ ├── NavigationActivity.kt
│ │ ├── UIActivity.kt
│ │ ├── ViewEvent.kt
│ │ └── ViewModelHolder.kt
│ │ ├── core
│ │ ├── App.kt
│ │ ├── Config.kt
│ │ ├── Const.kt
│ │ ├── Hacks.kt
│ │ ├── Info.kt
│ │ ├── JobService.kt
│ │ ├── Provider.kt
│ │ ├── Receiver.kt
│ │ ├── base
│ │ │ ├── BaseActivity.kt
│ │ │ ├── BaseJobService.kt
│ │ │ ├── BaseProvider.kt
│ │ │ ├── BaseReceiver.kt
│ │ │ └── BaseService.kt
│ │ ├── data
│ │ │ ├── NetworkServices.kt
│ │ │ ├── SuLogDao.kt
│ │ │ └── magiskdb
│ │ │ │ ├── MagiskDB.kt
│ │ │ │ ├── PolicyDao.kt
│ │ │ │ ├── SettingsDao.kt
│ │ │ │ └── StringDao.kt
│ │ ├── di
│ │ │ ├── Networking.kt
│ │ │ └── ServiceLocator.kt
│ │ ├── download
│ │ │ ├── DownloadService.kt
│ │ │ ├── NotificationService.kt
│ │ │ └── Subject.kt
│ │ ├── model
│ │ │ ├── UpdateInfo.kt
│ │ │ ├── module
│ │ │ │ ├── LocalModule.kt
│ │ │ │ ├── Module.kt
│ │ │ │ └── OnlineModule.kt
│ │ │ └── su
│ │ │ │ ├── SuLog.kt
│ │ │ │ └── SuPolicy.kt
│ │ ├── repository
│ │ │ ├── DBConfig.kt
│ │ │ ├── LogRepository.kt
│ │ │ ├── NetworkService.kt
│ │ │ └── PreferenceConfig.kt
│ │ ├── su
│ │ │ ├── SuCallbackHandler.kt
│ │ │ └── SuRequestHandler.kt
│ │ ├── tasks
│ │ │ ├── FlashZip.kt
│ │ │ ├── HideAPK.kt
│ │ │ └── MagiskInstaller.kt
│ │ └── utils
│ │ │ ├── AXML.kt
│ │ │ ├── BiometricHelper.kt
│ │ │ ├── DispatcherExecutor.kt
│ │ │ ├── Keygen.kt
│ │ │ ├── Locales.kt
│ │ │ ├── MediaStoreUtils.kt
│ │ │ ├── NetworkObserver.kt
│ │ │ ├── ProgressInputStream.kt
│ │ │ ├── RequestInstall.kt
│ │ │ ├── RootUtils.kt
│ │ │ ├── ShellInit.kt
│ │ │ └── ZipUtils.kt
│ │ ├── databinding
│ │ ├── DataBindingAdapters.kt
│ │ ├── DiffObservableList.kt
│ │ ├── FilterableDiffObservableList.kt
│ │ ├── MergeObservableList.kt
│ │ ├── ObservableHost.kt
│ │ ├── RecyclerViewItems.kt
│ │ └── RvItemAdapter.kt
│ │ ├── events
│ │ ├── RebootEvent.kt
│ │ ├── ViewEvents.kt
│ │ └── dialog
│ │ │ ├── BiometricEvent.kt
│ │ │ ├── DarkThemeDialog.kt
│ │ │ ├── DialogEvent.kt
│ │ │ ├── EnvFixDialog.kt
│ │ │ ├── ManagerInstallDialog.kt
│ │ │ ├── MarkDownDialog.kt
│ │ │ ├── ModuleInstallDialog.kt
│ │ │ ├── SecondSlotWarningDialog.kt
│ │ │ ├── SuperuserRevokeDialog.kt
│ │ │ └── UninstallDialog.kt
│ │ ├── ktx
│ │ ├── XAndroid.kt
│ │ ├── XJVM.kt
│ │ └── XSU.kt
│ │ ├── signing
│ │ ├── ApkSignerV2.java
│ │ ├── ByteArrayStream.java
│ │ ├── CryptoUtils.java
│ │ ├── JarMap.java
│ │ ├── SignApk.java
│ │ ├── SignBoot.java
│ │ └── ZipUtils.java
│ │ ├── ui
│ │ ├── MainActivity.kt
│ │ ├── SplashActivity.kt
│ │ ├── deny
│ │ │ ├── AppProcessInfo.kt
│ │ │ ├── DenyListFragment.kt
│ │ │ ├── DenyListRvItem.kt
│ │ │ └── DenyListViewModel.kt
│ │ ├── flash
│ │ │ ├── ConsoleItem.kt
│ │ │ ├── FlashFragment.kt
│ │ │ └── FlashViewModel.kt
│ │ ├── home
│ │ │ ├── DeveloperItem.kt
│ │ │ ├── HomeFragment.kt
│ │ │ └── HomeViewModel.kt
│ │ ├── install
│ │ │ ├── InstallFragment.kt
│ │ │ └── InstallViewModel.kt
│ │ ├── log
│ │ │ ├── LogFragment.kt
│ │ │ ├── LogRvItem.kt
│ │ │ ├── LogViewModel.kt
│ │ │ └── SuLogRvItem.kt
│ │ ├── module
│ │ │ ├── ModuleFragment.kt
│ │ │ ├── ModuleRvItem.kt
│ │ │ └── ModuleViewModel.kt
│ │ ├── settings
│ │ │ ├── BaseSettingsItem.kt
│ │ │ ├── SettingsFragment.kt
│ │ │ ├── SettingsItems.kt
│ │ │ └── SettingsViewModel.kt
│ │ ├── superuser
│ │ │ ├── PolicyRvItem.kt
│ │ │ ├── SuperuserFragment.kt
│ │ │ └── SuperuserViewModel.kt
│ │ ├── surequest
│ │ │ ├── SuRequestActivity.kt
│ │ │ └── SuRequestViewModel.kt
│ │ └── theme
│ │ │ ├── Theme.kt
│ │ │ ├── ThemeFragment.kt
│ │ │ └── ThemeViewModel.kt
│ │ ├── utils
│ │ ├── MotionRevealHelper.kt
│ │ ├── TextHolder.kt
│ │ └── Utils.kt
│ │ ├── view
│ │ ├── MagiskDialog.kt
│ │ ├── Notifications.kt
│ │ ├── Shortcuts.kt
│ │ ├── TappableHeadlineItem.kt
│ │ └── TextItem.kt
│ │ └── widget
│ │ └── ConcealableBottomNavigationView.java
│ └── res
│ ├── anim
│ ├── fragment_enter.xml
│ ├── fragment_enter_pop.xml
│ ├── fragment_exit.xml
│ └── fragment_exit_pop.xml
│ ├── color
│ ├── color_card_background_color_selector.xml
│ ├── color_error_transient.xml
│ ├── color_menu_tint.xml
│ ├── color_on_primary_transient.xml
│ ├── color_primary_error_transient.xml
│ ├── color_primary_transient.xml
│ ├── color_state_primary_transient.xml
│ └── color_text_transient.xml
│ ├── drawable-v26
│ ├── ic_launcher.xml
│ ├── sc_extension.xml
│ └── sc_superuser.xml
│ ├── drawable
│ ├── avd_bug_from_filled.xml
│ ├── avd_bug_to_filled.xml
│ ├── avd_circle_check_from_filled.xml
│ ├── avd_circle_check_to_filled.xml
│ ├── avd_delete_magisk.xml
│ ├── avd_home_from_filled.xml
│ ├── avd_home_to_filled.xml
│ ├── avd_magisk_delete.xml
│ ├── avd_module_from_filled.xml
│ ├── avd_module_to_filled.xml
│ ├── avd_settings_from_filled.xml
│ ├── avd_settings_to_filled.xml
│ ├── avd_superuser_from_filled.xml
│ ├── avd_superuser_to_filled.xml
│ ├── bg_line_bottom_rounded.xml
│ ├── bg_line_top_rounded.xml
│ ├── ic_add.xml
│ ├── ic_back_md2.xml
│ ├── ic_bug_filled_md2.xml
│ ├── ic_bug_md2.xml
│ ├── ic_bug_outlined_md2.xml
│ ├── ic_check_circle_checked_md2.xml
│ ├── ic_check_circle_md2.xml
│ ├── ic_check_circle_unchecked_md2.xml
│ ├── ic_check_md2.xml
│ ├── ic_close_md2.xml
│ ├── ic_day.xml
│ ├── ic_day_night.xml
│ ├── ic_delete_md2.xml
│ ├── ic_deny_list.xml
│ ├── ic_device.xml
│ ├── ic_divider.xml
│ ├── ic_dns.xml
│ ├── ic_download.xml
│ ├── ic_download_md2.xml
│ ├── ic_extension.xml
│ ├── ic_favorite.xml
│ ├── ic_fingerprint.xml
│ ├── ic_folder_list.xml
│ ├── ic_forth_md2.xml
│ ├── ic_github.xml
│ ├── ic_hide.xml
│ ├── ic_home_filled_md2.xml
│ ├── ic_home_md2.xml
│ ├── ic_home_outlined_md2.xml
│ ├── ic_install.xml
│ ├── ic_logo.xml
│ ├── ic_loop.xml
│ ├── ic_magisk.xml
│ ├── ic_magisk_delete.xml
│ ├── ic_magisk_outline.xml
│ ├── ic_magisk_padded.xml
│ ├── ic_magisk_padded_outline.xml
│ ├── ic_manager.xml
│ ├── ic_module_filled_md2.xml
│ ├── ic_module_md2.xml
│ ├── ic_module_outlined_md2.xml
│ ├── ic_more.xml
│ ├── ic_multiuser.xml
│ ├── ic_night.xml
│ ├── ic_notifications_filled_md2.xml
│ ├── ic_notifications_md2.xml
│ ├── ic_order_date.xml
│ ├── ic_order_name.xml
│ ├── ic_paint.xml
│ ├── ic_patreon.xml
│ ├── ic_paypal.xml
│ ├── ic_refresh_data_md2.xml
│ ├── ic_restart.xml
│ ├── ic_restore.xml
│ ├── ic_save_md2.xml
│ ├── ic_search_md2.xml
│ ├── ic_settings_filled_md2.xml
│ ├── ic_settings_md2.xml
│ ├── ic_settings_outlined_md2.xml
│ ├── ic_shortcut.xml
│ ├── ic_splash_activity.xml
│ ├── ic_supersu_access.xml
│ ├── ic_superuser.xml
│ ├── ic_superuser_filled_md2.xml
│ ├── ic_superuser_md2.xml
│ ├── ic_superuser_outlined_md2.xml
│ ├── ic_theme_magisk.xml
│ ├── ic_translate.xml
│ ├── ic_twitter.xml
│ ├── ic_update.xml
│ ├── ic_update_md2.xml
│ ├── ic_zygisk.xml
│ ├── sc_extension.xml
│ ├── sc_superuser.xml
│ └── shape_divider.xml
│ ├── font
│ └── googlesans.ttf
│ ├── layout
│ ├── activity_main_md2.xml
│ ├── activity_request.xml
│ ├── dialog_magisk_base.xml
│ ├── dialog_settings_app_name.xml
│ ├── dialog_settings_download_path.xml
│ ├── dialog_settings_update_channel.xml
│ ├── fragment_deny_md2.xml
│ ├── fragment_flash_md2.xml
│ ├── fragment_home_md2.xml
│ ├── fragment_install_md2.xml
│ ├── fragment_log_md2.xml
│ ├── fragment_module_md2.xml
│ ├── fragment_settings_md2.xml
│ ├── fragment_superuser_md2.xml
│ ├── fragment_theme_md2.xml
│ ├── include_home_magisk.xml
│ ├── include_home_manager.xml
│ ├── include_log_magisk.xml
│ ├── include_log_superuser.xml
│ ├── item_console_md2.xml
│ ├── item_developer.xml
│ ├── item_hide_md2.xml
│ ├── item_hide_process_md2.xml
│ ├── item_icon_link.xml
│ ├── item_list_single_line.xml
│ ├── item_log_access_md2.xml
│ ├── item_log_textview.xml
│ ├── item_log_track_md2.xml
│ ├── item_module_download.xml
│ ├── item_module_md2.xml
│ ├── item_policy_md2.xml
│ ├── item_settings.xml
│ ├── item_settings_section.xml
│ ├── item_spinner.xml
│ ├── item_tappable_headline.xml
│ ├── item_text.xml
│ ├── item_theme.xml
│ └── markdown_window_md2.xml
│ ├── menu
│ ├── menu_bottom_nav.xml
│ ├── menu_deny_md2.xml
│ ├── menu_flash.xml
│ ├── menu_home_md2.xml
│ ├── menu_log_md2.xml
│ ├── menu_reboot.xml
│ └── menu_theme.xml
│ ├── navigation
│ └── main.xml
│ ├── raw
│ └── manager.sh
│ ├── values-ar
│ └── strings.xml
│ ├── values-ast
│ └── strings.xml
│ ├── values-az
│ └── strings.xml
│ ├── values-be
│ └── strings.xml
│ ├── values-bg
│ └── strings.xml
│ ├── values-bn
│ └── strings.xml
│ ├── values-ca
│ └── strings.xml
│ ├── values-cs
│ └── strings.xml
│ ├── values-de
│ └── strings.xml
│ ├── values-el
│ └── strings.xml
│ ├── values-es
│ └── strings.xml
│ ├── values-et
│ └── strings.xml
│ ├── values-fa
│ └── strings.xml
│ ├── values-fr
│ └── strings.xml
│ ├── values-hi
│ └── strings.xml
│ ├── values-hr
│ └── strings.xml
│ ├── values-hu
│ └── strings.xml
│ ├── values-in
│ └── strings.xml
│ ├── values-it
│ └── strings.xml
│ ├── values-iw
│ └── strings.xml
│ ├── values-ja
│ └── strings.xml
│ ├── values-ka
│ └── strings.xml
│ ├── values-ko
│ └── strings.xml
│ ├── values-lt
│ └── strings.xml
│ ├── values-mk
│ └── strings.xml
│ ├── values-ml
│ └── strings.xml
│ ├── values-nb
│ └── strings.xml
│ ├── values-night
│ ├── colors.xml
│ ├── styles_md2.xml
│ ├── themes.xml
│ └── themes_md2.xml
│ ├── values-nl
│ └── strings.xml
│ ├── values-pa
│ └── strings.xml
│ ├── values-pl
│ └── strings.xml
│ ├── values-pt-rBR
│ └── strings.xml
│ ├── values-pt-rPT
│ └── strings.xml
│ ├── values-ro
│ └── strings.xml
│ ├── values-ru
│ └── strings.xml
│ ├── values-sk
│ └── strings.xml
│ ├── values-sq
│ └── strings.xml
│ ├── values-sr
│ └── strings.xml
│ ├── values-sv
│ └── strings.xml
│ ├── values-sw
│ └── strings.xml
│ ├── values-ta
│ └── strings.xml
│ ├── values-th
│ └── strings.xml
│ ├── values-tr
│ └── strings.xml
│ ├── values-uk
│ └── strings.xml
│ ├── values-v27
│ └── themes.xml
│ ├── values-v28
│ └── styles_md2_impl.xml
│ ├── values-v31
│ └── themes.xml
│ ├── values-vi
│ └── strings.xml
│ ├── values-zh-rCN
│ └── strings.xml
│ ├── values-zh-rTW
│ └── strings.xml
│ └── values
│ ├── arrays.xml
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── ids.xml
│ ├── resources.xml
│ ├── strings.xml
│ ├── styles_md2.xml
│ ├── styles_md2_appearance.xml
│ ├── styles_md2_impl.xml
│ ├── styles_view_md2.xml
│ ├── theme_overlay.xml
│ ├── themes.xml
│ ├── themes_md2.xml
│ └── themes_override.xml
├── build.gradle.kts
├── build.py
├── buildSrc
├── .gitignore
├── build.gradle.kts
└── src
│ └── main
│ └── java
│ ├── Codegen.kt
│ ├── Plugin.kt
│ └── Setup.kt
├── config.prop.sample
├── docs
├── README.md
├── app_changes.md
├── boot.md
├── changes.md
├── details.md
├── faq.md
├── guides.md
├── images
│ ├── device_info.png
│ ├── disable_auto_ota.png
│ ├── install_inactive_slot.png
│ ├── logo.png
│ ├── manager_reboot.png
│ ├── ota_done.png
│ └── restore_img.png
├── install.md
├── ota.md
├── releases
│ ├── 18000.md
│ ├── 18100.md
│ ├── 19000.md
│ ├── 19100.md
│ ├── 19200.md
│ ├── 19300.md
│ ├── 19400.md
│ ├── 20000.md
│ ├── 20100.md
│ ├── 20200.md
│ ├── 20300.md
│ ├── 20400.md
│ ├── 21000.md
│ ├── 21100.md
│ ├── 21200.md
│ ├── 21400.md
│ ├── 22000.md
│ ├── 22100.md
│ ├── 23000.md
│ ├── 24000.md
│ ├── 24100.md
│ ├── 24200.md
│ ├── 24300.md
│ ├── 25000.md
│ ├── 25100.md
│ ├── 25200.md
│ └── index.md
└── tools.md
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── native
├── .gitignore
├── README.md
├── build.gradle.kts
└── src
│ ├── .cargo
│ └── config.toml
│ ├── .gitignore
│ ├── Android-rs.mk
│ ├── Android.mk
│ ├── AndroidManifest.xml
│ ├── Application.mk
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── base
│ ├── Android.mk
│ ├── Cargo.toml
│ ├── compat
│ │ ├── compat.cpp
│ │ └── fortify.hpp
│ ├── files.cpp
│ ├── files.hpp
│ ├── files.rs
│ ├── include
│ │ ├── base.hpp
│ │ ├── embed.hpp
│ │ ├── selinux.hpp
│ │ └── stream.hpp
│ ├── lib.rs
│ ├── logging.cpp
│ ├── logging.hpp
│ ├── logging.rs
│ ├── misc.cpp
│ ├── misc.hpp
│ ├── misc.rs
│ ├── missing.hpp
│ ├── new.cpp
│ ├── selinux.cpp
│ ├── stream.cpp
│ ├── xwrap.hpp
│ └── xwrap.rs
│ ├── boot
│ ├── Cargo.toml
│ ├── bootimg.cpp
│ ├── bootimg.hpp
│ ├── compress.cpp
│ ├── compress.hpp
│ ├── cpio.cpp
│ ├── cpio.hpp
│ ├── dtb.cpp
│ ├── dtb.hpp
│ ├── format.cpp
│ ├── format.hpp
│ ├── hexpatch.cpp
│ ├── lib.rs
│ ├── magiskboot.hpp
│ ├── main.cpp
│ ├── pattern.cpp
│ └── ramdisk.cpp
│ ├── core
│ ├── Cargo.toml
│ ├── applet_stub.cpp
│ ├── applets.cpp
│ ├── bootstages.cpp
│ ├── cert.cpp
│ ├── core.hpp
│ ├── daemon.cpp
│ ├── db.cpp
│ ├── lib.rs
│ ├── logging.cpp
│ ├── logging.rs
│ ├── magisk.cpp
│ ├── module.cpp
│ ├── node.hpp
│ ├── package.cpp
│ ├── restorecon.cpp
│ ├── scripting.cpp
│ ├── socket.cpp
│ └── thread.cpp
│ ├── exported_sym.txt
│ ├── external
│ ├── Android.mk
│ ├── pcre2_workaround.c
│ ├── systemproperties
│ │ ├── Android.mk
│ │ ├── context_node.cpp
│ │ ├── contexts_serialized.cpp
│ │ ├── contexts_split.cpp
│ │ ├── include
│ │ │ ├── _system_properties.h
│ │ │ ├── async_safe
│ │ │ │ └── log.h
│ │ │ ├── private
│ │ │ │ ├── ErrnoRestorer.h
│ │ │ │ ├── bionic_defs.h
│ │ │ │ ├── bionic_futex.h
│ │ │ │ ├── bionic_lock.h
│ │ │ │ ├── bionic_macros.h
│ │ │ │ └── hacks.h
│ │ │ ├── property_info_parser
│ │ │ │ └── property_info_parser.h
│ │ │ ├── system_properties.h
│ │ │ └── system_properties
│ │ │ │ ├── context_node.h
│ │ │ │ ├── contexts.h
│ │ │ │ ├── contexts_pre_split.h
│ │ │ │ ├── contexts_serialized.h
│ │ │ │ ├── contexts_split.h
│ │ │ │ ├── prop_area.h
│ │ │ │ ├── prop_info.h
│ │ │ │ └── system_properties.h
│ │ ├── prop_area.cpp
│ │ ├── prop_info.cpp
│ │ ├── property_info_parser.cpp
│ │ ├── system_properties.cpp
│ │ ├── system_property_api.cpp
│ │ └── system_property_set.cpp
│ ├── xz-embedded
│ │ ├── xz.h
│ │ ├── xz_config.h
│ │ ├── xz_crc32.c
│ │ ├── xz_dec_lzma2.c
│ │ ├── xz_dec_stream.c
│ │ ├── xz_lzma2.h
│ │ ├── xz_private.h
│ │ └── xz_stream.h
│ └── xz_config
│ │ └── config.h
│ ├── include
│ ├── daemon.hpp
│ ├── db.hpp
│ ├── magisk.hpp
│ ├── resetprop.hpp
│ └── socket.hpp
│ ├── init
│ ├── Cargo.toml
│ ├── getinfo.cpp
│ ├── init.cpp
│ ├── init.hpp
│ ├── lib.rs
│ ├── logging.rs
│ ├── mount.cpp
│ ├── preload.c
│ ├── rootdir.cpp
│ ├── selinux.cpp
│ └── twostage.cpp
│ ├── lto_fix.lds
│ ├── resetprop
│ ├── persist.cpp
│ ├── prop.hpp
│ └── resetprop.cpp
│ ├── sepolicy
│ ├── Cargo.toml
│ ├── api.cpp
│ ├── include
│ │ └── sepolicy.hpp
│ ├── lib.rs
│ ├── main.cpp
│ ├── policy.hpp
│ ├── policydb.cpp
│ ├── rules.cpp
│ ├── sepolicy.cpp
│ └── statement.cpp
│ ├── su
│ ├── connect.cpp
│ ├── pts.cpp
│ ├── pts.hpp
│ ├── su.cpp
│ ├── su.hpp
│ └── su_daemon.cpp
│ └── zygisk
│ ├── api.hpp
│ ├── deny
│ ├── cli.cpp
│ ├── deny.hpp
│ ├── revert.cpp
│ └── utils.cpp
│ ├── entry.cpp
│ ├── gen_jni_hooks.py
│ ├── hook.cpp
│ ├── jni_hooks.hpp
│ ├── loader.c
│ ├── main.cpp
│ ├── memory.cpp
│ ├── memory.hpp
│ ├── module.hpp
│ ├── ptrace.cpp
│ ├── ptrace.hpp
│ ├── utils.cpp
│ └── zygisk.hpp
├── scripts
├── addon.d.sh
├── avd_magisk.sh
├── avd_patch.sh
├── avd_test.sh
├── boot_patch.sh
├── flash_script.sh
├── module_installer.sh
├── uninstaller.sh
├── update_binary.sh
└── util_functions.sh
├── settings.gradle.kts
├── stub
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── topjohnwu
│ │ └── magisk
│ │ ├── ClassLoaders.java
│ │ ├── DelegateApplication.java
│ │ ├── DelegateComponentFactory.java
│ │ ├── DelegateRootService.java
│ │ ├── DownloadActivity.java
│ │ ├── DynLoad.java
│ │ ├── dummy
│ │ ├── DummyProvider.java
│ │ ├── DummyReceiver.java
│ │ └── DummyService.java
│ │ └── net
│ │ ├── BadRequest.java
│ │ ├── ErrorHandler.java
│ │ ├── Networking.java
│ │ ├── Request.java
│ │ └── ResponseListener.java
│ └── res
│ ├── values-ar
│ └── strings.xml
│ ├── values-ast
│ └── strings.xml
│ ├── values-az
│ └── strings.xml
│ ├── values-be
│ └── strings.xml
│ ├── values-bg
│ └── strings.xml
│ ├── values-ca
│ └── strings.xml
│ ├── values-cs
│ └── strings.xml
│ ├── values-de
│ └── strings.xml
│ ├── values-el
│ └── strings.xml
│ ├── values-es
│ └── strings.xml
│ ├── values-et
│ └── strings.xml
│ ├── values-fa
│ └── strings.xml
│ ├── values-fr
│ └── strings.xml
│ ├── values-hi
│ └── strings.xml
│ ├── values-hr
│ └── strings.xml
│ ├── values-hu
│ └── strings.xml
│ ├── values-in
│ └── strings.xml
│ ├── values-it
│ └── strings.xml
│ ├── values-iw
│ └── strings.xml
│ ├── values-ja
│ └── strings.xml
│ ├── values-ka
│ └── strings.xml
│ ├── values-ko
│ └── strings.xml
│ ├── values-lt
│ └── strings.xml
│ ├── values-mk
│ └── strings.xml
│ ├── values-ml
│ └── strings.xml
│ ├── values-nb
│ └── strings.xml
│ ├── values-nl
│ └── strings.xml
│ ├── values-pa
│ └── strings.xml
│ ├── values-pl
│ └── strings.xml
│ ├── values-pt-rBR
│ └── strings.xml
│ ├── values-pt-rPT
│ └── strings.xml
│ ├── values-ro
│ └── strings.xml
│ ├── values-ru
│ └── strings.xml
│ ├── values-sk
│ └── strings.xml
│ ├── values-sq
│ └── strings.xml
│ ├── values-sr
│ └── strings.xml
│ ├── values-sv
│ └── strings.xml
│ ├── values-sw
│ └── strings.xml
│ ├── values-ta
│ └── strings.xml
│ ├── values-th
│ └── strings.xml
│ ├── values-tr
│ └── strings.xml
│ ├── values-uk
│ └── strings.xml
│ ├── values-vi
│ └── strings.xml
│ ├── values-zh-rCN
│ └── strings.xml
│ ├── values-zh-rTW
│ └── strings.xml
│ └── values
│ └── strings.xml
└── tools
├── bootctl
├── bootctl.patch
├── elf-cleaner.exe
├── futility
├── keys
├── kernel.keyblock
├── kernel_data_key.vbprivk
├── verity.pk8
└── verity.x509.pem
└── ndk-bins
├── 21
├── aarch64
│ ├── crtbegin_dynamic.o
│ ├── crtbegin_so.o
│ ├── crtbegin_static.o
│ ├── crtend_android.o
│ ├── crtend_so.o
│ ├── libc.a
│ ├── libm.a
│ ├── libstdc++.a
│ └── libz.a
├── arm
│ ├── crtbegin_dynamic.o
│ ├── crtbegin_so.o
│ ├── crtbegin_static.o
│ ├── crtend_android.o
│ ├── crtend_so.o
│ ├── libc.a
│ ├── libm.a
│ ├── libstdc++.a
│ └── libz.a
├── i686
│ ├── crtbegin_dynamic.o
│ ├── crtbegin_so.o
│ ├── crtbegin_static.o
│ ├── crtend_android.o
│ ├── crtend_so.o
│ ├── libc.a
│ ├── libm.a
│ ├── libstdc++.a
│ └── libz.a
└── x86_64
│ ├── crtbegin_dynamic.o
│ ├── crtbegin_so.o
│ ├── crtbegin_static.o
│ ├── crtend_android.o
│ ├── crtend_so.o
│ ├── libc.a
│ ├── libm.a
│ ├── libstdc++.a
│ └── libz.a
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text eol=lf
3 |
4 | # Explicitly declare text files you want to always be normalized and converted
5 | # to native line endings on checkout.
6 | # *.c text
7 | # *.h text
8 |
9 | # Declare files that will always have CRLF line endings on checkout.
10 | *.cmd text eol=crlf
11 | *.bat text eol=crlf
12 |
13 | # Denote all files that are truly binary and should not be modified.
14 | tools/** binary
15 | *.jar binary
16 | *.exe binary
17 | *.apk binary
18 | *.png binary
19 | *.jpg binary
20 | *.ttf binary
21 |
22 | # Help GitHub detect languages
23 | native/jni/external/** linguist-vendored
24 | native/jni/systemproperties/** linguist-language=C++
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: XDA Community Support
4 | url: https://forum.xda-developers.com/f/magisk.5903/
5 | about: Please ask and answer questions here.
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | *.zip
3 | *.jks
4 | *.apk
5 | /config.prop
6 | /update.sh
7 | /dict.txt
8 |
9 | # Built binaries
10 | native/out
11 |
12 | # Android Studio / Gradle
13 | *.iml
14 | .gradle
15 | /local.properties
16 | /.idea
17 | /build
18 | /captures
19 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea/
5 | /build
6 | *.hprof
7 | .externalNativeBuild/
8 | *.apk
9 | src/*/assets
10 | src/*/jniLibs
11 | src/*/resources
12 |
--------------------------------------------------------------------------------
/app/shared/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/shared/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/shared/src/main/java/com/topjohnwu/magisk/ProviderInstaller.java:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk;
2 |
3 | import android.content.Context;
4 |
5 | public class ProviderInstaller {
6 |
7 | public static boolean install(Context context) {
8 | try {
9 | // Try installing new SSL provider from Google Play Service
10 | Context gms = context.createPackageContext("com.google.android.gms",
11 | Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
12 | gms.getClassLoader()
13 | .loadClass("com.google.android.gms.common.security.ProviderInstallerImpl")
14 | .getMethod("insertProvider", Context.class)
15 | .invoke(null, gms);
16 | } catch (Exception e) {
17 | return false;
18 | }
19 | return true;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/shared/src/main/java/com/topjohnwu/magisk/utils/CompoundEnumeration.java:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.utils;
2 |
3 | import java.util.Enumeration;
4 | import java.util.NoSuchElementException;
5 |
6 | public class CompoundEnumeration implements Enumeration {
7 | private Enumeration[] enums;
8 | private int index = 0;
9 |
10 | @SafeVarargs
11 | public CompoundEnumeration(Enumeration ...enums) {
12 | this.enums = enums;
13 | }
14 |
15 | private boolean next() {
16 | while (index < enums.length) {
17 | if (enums[index] != null && enums[index].hasMoreElements()) {
18 | return true;
19 | }
20 | index++;
21 | }
22 | return false;
23 | }
24 |
25 | public boolean hasMoreElements() {
26 | return next();
27 | }
28 |
29 | public E nextElement() {
30 | if (!next()) {
31 | throw new NoSuchElementException();
32 | }
33 | return enums[index].nextElement();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/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 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/androidx/lifecycle/ProcessLifecycleAccessor.java:
--------------------------------------------------------------------------------
1 | package androidx.lifecycle;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | public class ProcessLifecycleAccessor {
8 | public static void init(@NonNull Context context) {
9 | LifecycleDispatcher.init(context);
10 | ProcessLifecycleOwner.init(context);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/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/src/main/java/com/topjohnwu/magisk/arch/NavigationActivity.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.arch
2 |
3 | import android.view.KeyEvent
4 | import androidx.databinding.ViewDataBinding
5 | import androidx.navigation.NavController
6 | import androidx.navigation.NavDirections
7 | import androidx.navigation.fragment.NavHostFragment
8 |
9 | abstract class NavigationActivity : UIActivity() {
10 |
11 | abstract val navHostId: Int
12 |
13 | private val navHostFragment by lazy {
14 | supportFragmentManager.findFragmentById(navHostId) as NavHostFragment
15 | }
16 |
17 | protected val currentFragment get() =
18 | navHostFragment.childFragmentManager.fragments.getOrNull(0) as? BaseFragment<*>
19 |
20 | val navigation: NavController get() = navHostFragment.navController
21 |
22 | override fun dispatchKeyEvent(event: KeyEvent): Boolean {
23 | return if (binded && currentFragment?.onKeyEvent(event) == true) true else super.dispatchKeyEvent(event)
24 | }
25 |
26 | override fun onBackPressed() {
27 | if (binded) {
28 | if (currentFragment?.onBackPressed() == false) {
29 | super.onBackPressed()
30 | }
31 | }
32 | }
33 |
34 | fun NavDirections.navigate() {
35 | navigation.navigate(this)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/arch/ViewEvent.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.arch
2 |
3 | import android.content.Context
4 | import kotlinx.coroutines.CoroutineScope
5 |
6 | /**
7 | * Class for passing events from ViewModels to Activities/Fragments
8 | * (see https://medium.com/google-developers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150)
9 | */
10 | abstract class ViewEvent
11 |
12 | abstract class ViewEventWithScope: ViewEvent() {
13 | lateinit var scope: CoroutineScope
14 | }
15 |
16 | interface ContextExecutor {
17 | operator fun invoke(context: Context)
18 | }
19 |
20 | interface ActivityExecutor {
21 | operator fun invoke(activity: UIActivity<*>)
22 | }
23 |
24 | interface FragmentExecutor {
25 | operator fun invoke(fragment: BaseFragment<*>)
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core
2 |
3 | import android.net.Uri
4 | import android.os.Bundle
5 | import android.os.ParcelFileDescriptor
6 | import android.os.ParcelFileDescriptor.MODE_READ_ONLY
7 | import com.topjohnwu.magisk.core.base.BaseProvider
8 | import com.topjohnwu.magisk.core.su.SuCallbackHandler
9 |
10 | class Provider : BaseProvider() {
11 |
12 | override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
13 | SuCallbackHandler.run(context!!, method, extras)
14 | return Bundle.EMPTY
15 | }
16 |
17 | override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
18 | return when (uri.encodedPath ?: return null) {
19 | "/prefs_file" -> ParcelFileDescriptor.open(Config.prefsFile, MODE_READ_ONLY)
20 | else -> super.openFile(uri, mode)
21 | }
22 | }
23 |
24 | companion object {
25 | fun preferencesUri(pkg: String): Uri =
26 | Uri.Builder().scheme("content").authority("$pkg.provider").path("prefs_file").build()
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/base/BaseProvider.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.base
2 |
3 | import android.content.ContentProvider
4 | import android.content.ContentValues
5 | import android.content.Context
6 | import android.content.pm.ProviderInfo
7 | import android.database.Cursor
8 | import android.net.Uri
9 | import com.topjohnwu.magisk.core.patch
10 |
11 | open class BaseProvider : ContentProvider() {
12 | override fun attachInfo(context: Context, info: ProviderInfo) {
13 | super.attachInfo(context.patch(), info)
14 | }
15 | override fun onCreate() = true
16 | override fun getType(uri: Uri): String? = null
17 | override fun insert(uri: Uri, values: ContentValues?): Uri? = null
18 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?) = 0
19 | override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?) = 0
20 | override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? = null
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/base/BaseReceiver.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.base
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import androidx.annotation.CallSuper
7 | import com.topjohnwu.magisk.core.patch
8 |
9 | abstract class BaseReceiver : BroadcastReceiver() {
10 | @CallSuper
11 | override fun onReceive(context: Context, intent: Intent?) {
12 | context.patch()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/base/BaseService.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.base
2 |
3 | import android.app.Service
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.os.IBinder
7 | import com.topjohnwu.magisk.core.patch
8 |
9 | open class BaseService : Service() {
10 | override fun attachBaseContext(base: Context) {
11 | super.attachBaseContext(base.patch())
12 | }
13 | override fun onBind(intent: Intent?): IBinder? = null
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/data/NetworkServices.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.data
2 |
3 | import com.topjohnwu.magisk.core.model.BranchInfo
4 | import com.topjohnwu.magisk.core.model.ModuleJson
5 | import com.topjohnwu.magisk.core.model.UpdateInfo
6 | import okhttp3.ResponseBody
7 | import retrofit2.http.*
8 |
9 | private const val BRANCH = "branch"
10 | private const val REPO = "repo"
11 | private const val FILE = "file"
12 |
13 | interface GithubPageServices {
14 |
15 | @GET
16 | suspend fun fetchUpdateJSON(@Url file: String): UpdateInfo
17 | }
18 |
19 | interface RawServices {
20 |
21 | @GET
22 | @Streaming
23 | suspend fun fetchFile(@Url url: String): ResponseBody
24 |
25 | @GET
26 | suspend fun fetchString(@Url url: String): String
27 |
28 | @GET
29 | suspend fun fetchModuleJson(@Url url: String): ModuleJson
30 |
31 | }
32 |
33 | interface GithubApiServices {
34 |
35 | @GET("repos/{$REPO}/branches/{$BRANCH}")
36 | @Headers("Accept: application/vnd.github.v3+json")
37 | suspend fun fetchBranch(
38 | @Path(REPO, encoded = true) repo: String,
39 | @Path(BRANCH) branch: String
40 | ): BranchInfo
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/data/SuLogDao.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.data
2 |
3 | import androidx.room.*
4 | import com.topjohnwu.magisk.core.model.su.SuLog
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlinx.coroutines.withContext
7 | import java.util.*
8 |
9 | @Database(version = 1, entities = [SuLog::class], exportSchema = false)
10 | abstract class SuLogDatabase : RoomDatabase() {
11 |
12 | abstract fun suLogDao(): SuLogDao
13 | }
14 |
15 | @Dao
16 | abstract class SuLogDao(private val db: SuLogDatabase) {
17 |
18 | private val twoWeeksAgo =
19 | Calendar.getInstance().apply { add(Calendar.WEEK_OF_YEAR, -2) }.timeInMillis
20 |
21 | suspend fun deleteAll() = withContext(Dispatchers.IO) { db.clearAllTables() }
22 |
23 | suspend fun fetchAll(): MutableList {
24 | deleteOutdated()
25 | return fetch()
26 | }
27 |
28 | @Query("SELECT * FROM logs ORDER BY time DESC")
29 | protected abstract suspend fun fetch(): MutableList
30 |
31 | @Query("DELETE FROM logs WHERE time < :timeout")
32 | protected abstract suspend fun deleteOutdated(timeout: Long = twoWeeksAgo)
33 |
34 | @Insert
35 | abstract suspend fun insert(log: SuLog)
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/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/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/src/main/java/com/topjohnwu/magisk/core/model/UpdateInfo.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.model
2 |
3 | import android.os.Parcelable
4 | import com.squareup.moshi.JsonClass
5 | import kotlinx.parcelize.Parcelize
6 |
7 | @JsonClass(generateAdapter = true)
8 | data class UpdateInfo(
9 | val magisk: MagiskJson = MagiskJson(),
10 | )
11 |
12 | @Parcelize
13 | @JsonClass(generateAdapter = true)
14 | data class MagiskJson(
15 | val version: String = "",
16 | val versionCode: Int = -1,
17 | val link: String = "",
18 | val note: String = ""
19 | ) : Parcelable
20 |
21 | @JsonClass(generateAdapter = true)
22 | data class ModuleJson(
23 | val version: String,
24 | val versionCode: Int,
25 | val zipUrl: String,
26 | val changelog: String,
27 | )
28 |
29 | @JsonClass(generateAdapter = true)
30 | data class CommitInfo(
31 | val sha: String
32 | )
33 |
34 | @JsonClass(generateAdapter = true)
35 | data class BranchInfo(
36 | val commit: CommitInfo
37 | )
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/model/module/Module.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.model.module
2 |
3 | abstract class Module : Comparable {
4 | abstract var id: String
5 | protected set
6 | abstract var name: String
7 | protected set
8 | abstract var version: String
9 | protected set
10 | abstract var versionCode: Int
11 | protected set
12 |
13 | override operator fun compareTo(other: Module) = id.compareTo(other.id)
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/model/module/OnlineModule.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.model.module
2 |
3 | import android.os.Parcelable
4 | import com.topjohnwu.magisk.core.model.ModuleJson
5 | import kotlinx.parcelize.Parcelize
6 |
7 | @Parcelize
8 | data class OnlineModule(
9 | override var id: String,
10 | override var name: String,
11 | override var version: String,
12 | override var versionCode: Int,
13 | val zipUrl: String,
14 | val changelog: String,
15 | ) : Module(), Parcelable {
16 | constructor(local: LocalModule, json: ModuleJson) :
17 | this(local.id, local.name, json.version, json.versionCode, json.zipUrl, json.changelog)
18 |
19 | val downloadFilename get() = "$name-$version($versionCode).zip".legalFilename()
20 |
21 | private fun String.legalFilename() = replace(" ", "_")
22 | .replace("'", "").replace("\"", "")
23 | .replace("$", "").replace("`", "")
24 | .replace("*", "").replace("/", "_")
25 | .replace("#", "").replace("@", "")
26 | .replace("\\", "_")
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/model/su/SuPolicy.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.model.su
2 |
3 | class SuPolicy(val uid: Int) {
4 | companion object {
5 | const val INTERACTIVE = 0
6 | const val DENY = 1
7 | const val ALLOW = 2
8 | }
9 |
10 | var policy: Int = INTERACTIVE
11 | var until: Long = -1L
12 | var logging: Boolean = true
13 | var notification: Boolean = true
14 |
15 | fun toMap(): MutableMap = mutableMapOf(
16 | "uid" to uid,
17 | "policy" to policy,
18 | "until" to until,
19 | "logging" to logging,
20 | "notification" to notification
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/core/utils/DispatcherExecutor.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.core.utils
2 |
3 | import kotlinx.coroutines.*
4 | import java.util.concurrent.AbstractExecutorService
5 | import java.util.concurrent.CountDownLatch
6 | import java.util.concurrent.TimeUnit
7 |
8 | class DispatcherExecutor(dispatcher: CoroutineDispatcher) : AbstractExecutorService() {
9 |
10 | private val job = SupervisorJob()
11 | private val scope = CoroutineScope(job + dispatcher)
12 | private val latch = CountDownLatch(1)
13 |
14 | init {
15 | job.invokeOnCompletion { latch.countDown() }
16 | }
17 |
18 | override fun execute(command: Runnable) {
19 | scope.launch {
20 | command.run()
21 | }
22 | }
23 |
24 | override fun shutdown() = job.cancel()
25 |
26 | override fun shutdownNow(): List {
27 | job.cancel()
28 | return emptyList()
29 | }
30 |
31 | override fun isShutdown() = job.isCancelled
32 |
33 | override fun isTerminated() = job.isCancelled && job.isCompleted
34 |
35 | override fun awaitTermination(timeout: Long, unit: TimeUnit) = latch.await(timeout, unit)
36 | }
37 |
--------------------------------------------------------------------------------
/app/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/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/src/main/java/com/topjohnwu/magisk/databinding/FilterableDiffObservableList.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.databinding
2 |
3 | import kotlinx.coroutines.CoroutineScope
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.Job
6 | import kotlinx.coroutines.launch
7 | import kotlinx.coroutines.withContext
8 |
9 | open class FilterableDiffObservableList(
10 | callback: Callback,
11 | private val scope: CoroutineScope
12 | ) : DiffObservableList(callback) {
13 |
14 | private var sublist: List = emptyList()
15 | private var job: Job? = null
16 |
17 | // ---
18 |
19 | fun filter(filter: (T) -> Boolean) {
20 | job?.cancel()
21 | job = scope.launch(Dispatchers.Default) {
22 | val oldList = sublist
23 | val newList = list.filter(filter)
24 | val diff = doCalculateDiff(oldList, newList)
25 | withContext(Dispatchers.Main) {
26 | sublist = newList
27 | diff.dispatchUpdatesTo(listCallback)
28 | }
29 | }
30 | }
31 |
32 | // ---
33 |
34 | override fun get(index: Int): T {
35 | return sublist[index]
36 | }
37 |
38 | override val size: Int
39 | get() = sublist.size
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/events/dialog/BiometricEvent.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.events.dialog
2 |
3 | import com.topjohnwu.magisk.arch.ActivityExecutor
4 | import com.topjohnwu.magisk.arch.UIActivity
5 | import com.topjohnwu.magisk.arch.ViewEvent
6 | import com.topjohnwu.magisk.core.utils.BiometricHelper
7 |
8 | class BiometricEvent(
9 | builder: Builder.() -> Unit
10 | ) : ViewEvent(), ActivityExecutor {
11 |
12 | private var listenerOnFailure: GenericDialogListener = {}
13 | private var listenerOnSuccess: GenericDialogListener = {}
14 |
15 | init {
16 | builder(Builder())
17 | }
18 |
19 | override fun invoke(activity: UIActivity<*>) {
20 | BiometricHelper.authenticate(
21 | activity,
22 | onError = listenerOnFailure,
23 | onSuccess = listenerOnSuccess
24 | )
25 | }
26 |
27 | inner class Builder internal constructor() {
28 |
29 | fun onFailure(listener: GenericDialogListener) {
30 | listenerOnFailure = listener
31 | }
32 |
33 | fun onSuccess(listener: GenericDialogListener) {
34 | listenerOnSuccess = listener
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/events/dialog/DialogEvent.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.events.dialog
2 |
3 | import com.topjohnwu.magisk.arch.ActivityExecutor
4 | import com.topjohnwu.magisk.arch.UIActivity
5 | import com.topjohnwu.magisk.arch.ViewEvent
6 | import com.topjohnwu.magisk.view.MagiskDialog
7 |
8 | abstract class DialogEvent : ViewEvent(), ActivityExecutor {
9 |
10 | override fun invoke(activity: UIActivity<*>) {
11 | MagiskDialog(activity).apply(this::build).show()
12 | }
13 |
14 | abstract fun build(dialog: MagiskDialog)
15 |
16 | }
17 |
18 | typealias GenericDialogListener = () -> Unit
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/events/dialog/SecondSlotWarningDialog.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.events.dialog
2 |
3 | import com.topjohnwu.magisk.R
4 | import com.topjohnwu.magisk.view.MagiskDialog
5 |
6 | class SecondSlotWarningDialog : DialogEvent() {
7 |
8 | override fun build(dialog: MagiskDialog) {
9 | dialog.apply {
10 | setTitle(android.R.string.dialog_alert_title)
11 | setMessage(R.string.install_inactive_slot_msg)
12 | setButton(MagiskDialog.ButtonType.POSITIVE) {
13 | text = android.R.string.ok
14 | }
15 | setCancelable(true)
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/events/dialog/SuperuserRevokeDialog.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.events.dialog
2 |
3 | import com.topjohnwu.magisk.R
4 | import com.topjohnwu.magisk.view.MagiskDialog
5 |
6 | class SuperuserRevokeDialog(
7 | builder: Builder.() -> Unit
8 | ) : DialogEvent() {
9 |
10 | private val callbacks = Builder().apply(builder)
11 |
12 | override fun build(dialog: MagiskDialog) {
13 | dialog.apply {
14 | setTitle(R.string.su_revoke_title)
15 | setMessage(R.string.su_revoke_msg, callbacks.appName)
16 | setButton(MagiskDialog.ButtonType.POSITIVE) {
17 | text = android.R.string.ok
18 | onClick { callbacks.listenerOnSuccess() }
19 | }
20 | setButton(MagiskDialog.ButtonType.NEGATIVE) {
21 | text = android.R.string.cancel
22 | }
23 | }
24 | }
25 |
26 | inner class Builder internal constructor() {
27 | var appName: String = ""
28 |
29 | internal var listenerOnSuccess: GenericDialogListener = {}
30 |
31 | fun onSuccess(listener: GenericDialogListener) {
32 | listenerOnSuccess = listener
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/events/dialog/UninstallDialog.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.events.dialog
2 |
3 | import android.app.ProgressDialog
4 | import android.content.Context
5 | import android.util.Log
6 | import android.widget.Toast
7 | import com.topjohnwu.magisk.R
8 | import com.topjohnwu.magisk.arch.NavigationActivity
9 | import com.topjohnwu.magisk.ui.flash.FlashFragment
10 | import com.topjohnwu.magisk.utils.Utils
11 | import com.topjohnwu.magisk.view.MagiskDialog
12 | import com.topjohnwu.superuser.Shell
13 |
14 | class UninstallDialog : DialogEvent() {
15 |
16 | override fun build(dialog: MagiskDialog) {
17 | dialog.apply {
18 | setTitle(R.string.uninstall_magisk_title)
19 | setMessage(R.string.uninstall_magisk_msg)
20 | setButton(MagiskDialog.ButtonType.POSITIVE) {
21 | text = "Yes"
22 | onClick { completeUninstall(dialog) }
23 | }
24 | setButton(MagiskDialog.ButtonType.NEGATIVE) {
25 | text = "No"
26 | dialog.dismiss()
27 | }
28 | }
29 | }
30 |
31 | private fun completeUninstall(dialog: MagiskDialog) {
32 | (dialog.ownerActivity as NavigationActivity<*>)
33 | .navigation.navigate(FlashFragment.uninstall())
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/ktx/XSU.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.ktx
2 |
3 | import android.content.Context
4 | import com.topjohnwu.magisk.core.Config
5 | import com.topjohnwu.magisk.core.Const
6 | import com.topjohnwu.superuser.Shell
7 | import kotlinx.coroutines.Dispatchers
8 | import kotlinx.coroutines.withContext
9 |
10 | fun reboot(reason: String = if (Config.recovery) "recovery" else "") {
11 | if (reason == "recovery") {
12 | // KEYCODE_POWER = 26, hide incorrect "Factory data reset" message
13 | Shell.cmd("/system/bin/input keyevent 26").submit()
14 | }
15 | Shell.cmd("/system/bin/svc power reboot $reason || /system/bin/reboot $reason").submit()
16 | }
17 |
18 | fun relaunchApp(context: Context) {
19 | val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) ?: return
20 | val args = mutableListOf("am", "start", "--user", Const.USER_ID.toString())
21 | val cmd = intent.toCommand(args).joinToString(separator = " ")
22 | Shell.cmd("run_delay 1 \"$cmd\"").exec()
23 | Runtime.getRuntime().exit(0)
24 | }
25 |
26 | suspend fun Shell.Job.await() = withContext(Dispatchers.IO) { exec() }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/signing/ByteArrayStream.java:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.signing;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 |
8 | public class ByteArrayStream extends ByteArrayOutputStream {
9 |
10 | public synchronized void readFrom(InputStream is) {
11 | readFrom(is, Integer.MAX_VALUE);
12 | }
13 |
14 | public synchronized void readFrom(InputStream is, int len) {
15 | int read;
16 | byte buffer[] = new byte[4096];
17 | try {
18 | while ((read = is.read(buffer, 0, Math.min(len, buffer.length))) > 0) {
19 | write(buffer, 0, read);
20 | len -= read;
21 | }
22 | } catch (IOException e) {
23 | e.printStackTrace();
24 | }
25 | }
26 |
27 | public ByteArrayInputStream getInputStream() {
28 | return new ByteArrayInputStream(buf, 0, count);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/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.DiffRvItem
10 | import com.topjohnwu.magisk.databinding.RvContainer
11 | import com.topjohnwu.magisk.databinding.ViewAwareRvItem
12 | import kotlin.math.max
13 |
14 | class ConsoleItem(
15 | override val item: String
16 | ) : DiffRvItem(), ViewAwareRvItem, RvContainer {
17 | override val layoutRes = R.layout.item_console_md2
18 |
19 | private var parentWidth = -1
20 |
21 | override fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView) {
22 | if (parentWidth < 0)
23 | parentWidth = (recyclerView.parent as View).width
24 |
25 | val view = binding.root as TextView
26 | view.measure(0, 0)
27 |
28 | // We want our recyclerView at least as wide as screen
29 | val desiredWidth = max(view.measuredWidth, parentWidth)
30 |
31 | view.updateLayoutParams { width = desiredWidth }
32 |
33 | if (recyclerView.width < desiredWidth) {
34 | recyclerView.requestLayout()
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/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 |
8 | class InstallFragment : BaseFragment() {
9 |
10 | override val layoutRes = R.layout.fragment_install_md2
11 | override val viewModel by viewModel()
12 |
13 | override fun onStart() {
14 | super.onStart()
15 | requireActivity().setTitle(R.string.install)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/ui/log/LogRvItem.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.ui.log
2 |
3 | import androidx.databinding.ViewDataBinding
4 | import androidx.recyclerview.widget.RecyclerView
5 | import com.google.android.material.textview.MaterialTextView
6 | import com.topjohnwu.magisk.R
7 | import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
8 | import com.topjohnwu.magisk.databinding.RvContainer
9 | import com.topjohnwu.magisk.databinding.ViewAwareRvItem
10 |
11 | class LogRvItem(
12 | override val item: String
13 | ) : ObservableDiffRvItem(), RvContainer, ViewAwareRvItem {
14 |
15 | override val layoutRes = R.layout.item_log_textview
16 |
17 | override fun itemSameAs(other: LogRvItem) = item == other.item
18 |
19 | override fun onBind(binding: ViewDataBinding, recyclerView: RecyclerView) {
20 | val view = binding.root as MaterialTextView
21 | view.measure(0, 0)
22 | val desiredWidth = view.measuredWidth
23 | val layoutParams = view.layoutParams
24 | layoutParams.width = desiredWidth
25 | if (recyclerView.width < desiredWidth) {
26 | recyclerView.requestLayout()
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/ui/log/SuLogRvItem.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.ui.log
2 |
3 | import androidx.databinding.Bindable
4 | import com.topjohnwu.magisk.BR
5 | import com.topjohnwu.magisk.R
6 | import com.topjohnwu.magisk.core.model.su.SuLog
7 | import com.topjohnwu.magisk.databinding.ObservableDiffRvItem
8 | import com.topjohnwu.magisk.databinding.RvContainer
9 | import com.topjohnwu.magisk.databinding.set
10 | import com.topjohnwu.magisk.ktx.timeDateFormat
11 | import com.topjohnwu.magisk.ktx.toTime
12 |
13 | class SuLogRvItem(
14 | override val item: SuLog
15 | ) : ObservableDiffRvItem(), RvContainer {
16 |
17 | override val layoutRes = R.layout.item_log_access_md2
18 |
19 | val date = item.time.toTime(timeDateFormat)
20 |
21 | @get:Bindable
22 | var isTop = false
23 | set(value) = set(value, field, { field = it }, BR.top)
24 |
25 | @get:Bindable
26 | var isBottom = false
27 | set(value) = set(value, field, { field = it }, BR.bottom)
28 |
29 | override fun itemSameAs(other: SuLogRvItem) = item.appName == other.item.appName
30 | }
31 |
--------------------------------------------------------------------------------
/app/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 |
13 | class SettingsFragment : BaseFragment() {
14 |
15 | override val layoutRes = R.layout.fragment_settings_md2
16 | override val viewModel by viewModel()
17 | override val snackbarView: View get() = binding.snackbarContainer
18 |
19 | override fun onStart() {
20 | super.onStart()
21 |
22 | activity?.title = resources.getString(R.string.settings)
23 | }
24 |
25 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
26 | super.onViewCreated(view, savedInstanceState)
27 | binding.settingsList.apply {
28 | addEdgeSpacing(bottom = R.dimen.l1)
29 | addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
30 | fixEdgeEffect()
31 | }
32 | }
33 |
34 | override fun onResume() {
35 | super.onResume()
36 | viewModel.items.forEach { it.refresh() }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/app/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 |
13 | class SuperuserFragment : BaseFragment() {
14 |
15 | override val layoutRes = R.layout.fragment_superuser_md2
16 | override val viewModel by viewModel()
17 |
18 | override fun onStart() {
19 | super.onStart()
20 | activity?.title = resources.getString(R.string.superuser)
21 | }
22 |
23 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
24 | super.onViewCreated(view, savedInstanceState)
25 |
26 | binding.superuserList.apply {
27 | addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
28 | addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
29 | fixEdgeEffect()
30 | }
31 | }
32 |
33 | override fun onPreBind(binding: FragmentSuperuserMd2Binding) {}
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/ui/theme/ThemeViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.ui.theme
2 |
3 | import android.view.MenuItem
4 | import com.topjohnwu.magisk.R
5 | import com.topjohnwu.magisk.arch.BaseViewModel
6 | import com.topjohnwu.magisk.core.Config
7 | import com.topjohnwu.magisk.events.RecreateEvent
8 | import com.topjohnwu.magisk.events.dialog.DarkThemeDialog
9 | import com.topjohnwu.magisk.view.TappableHeadlineItem
10 |
11 | class ThemeViewModel : BaseViewModel(){
12 | fun onThemeModeOptionClicked(){
13 | DarkThemeDialog().publish()
14 | }
15 | fun saveTheme(theme: Theme) {
16 | if (!theme.isSelected) {
17 | Config.themeOrdinal = theme.ordinal
18 | RecreateEvent().publish()
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/view/TappableHeadlineItem.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.view
2 |
3 | import com.topjohnwu.magisk.R
4 | import com.topjohnwu.magisk.databinding.DiffRvItem
5 |
6 | sealed class TappableHeadlineItem : DiffRvItem() {
7 |
8 | abstract val title: Int
9 | abstract val icon: Int
10 |
11 | override val layoutRes = R.layout.item_tappable_headline
12 |
13 | // --- listener
14 |
15 | interface Listener {
16 |
17 | fun onItemPressed(item: TappableHeadlineItem)
18 |
19 | }
20 |
21 | // --- objects
22 |
23 | object ThemeMode : TappableHeadlineItem() {
24 | override val title = R.string.settings_dark_mode_title
25 | override val icon = R.drawable.ic_day_night
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/topjohnwu/magisk/view/TextItem.kt:
--------------------------------------------------------------------------------
1 | package com.topjohnwu.magisk.view
2 |
3 | import com.topjohnwu.magisk.R
4 | import com.topjohnwu.magisk.databinding.DiffRvItem
5 |
6 | class TextItem(val text: Int) : DiffRvItem() {
7 | override val layoutRes = R.layout.item_text
8 |
9 | override fun contentSameAs(other: TextItem) = text == other.text
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/fragment_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/fragment_enter_pop.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/fragment_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/fragment_exit_pop.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_card_background_color_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_error_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_menu_tint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_on_primary_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_primary_error_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_primary_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_state_primary_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/color/color_text_transient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v26/sc_extension.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v26/sc_superuser.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_line_bottom_rounded.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_line_top_rounded.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back_md2.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bug_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bug_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bug_outlined_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle_checked_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
14 |
15 |
19 |
20 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle_unchecked_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_close_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_day.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_day_night.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_divider.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dns.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_download.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_download_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_extension.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_favorite.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_forth_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_github.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_hide.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_outlined_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_install.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_logo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_loop.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_magisk_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_module_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_module_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_module_outlined_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_multiuser.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_night.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_order_name.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_paint.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_patreon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_refresh_data_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_restart.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_restore.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_save_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_shortcut.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_splash_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_superuser.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_superuser_filled_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_superuser_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_superuser_outlined_md2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_translate.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_twitter.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_update.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_update_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sc_extension.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sc_superuser.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/font/googlesans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/app/src/main/res/font/googlesans.ttf
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_theme_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_console_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/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/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/src/main/res/layout/item_log_textview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_module_download.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_spinner.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/markdown_window_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_bottom_nav.xml:
--------------------------------------------------------------------------------
1 |
2 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_deny_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_flash.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_home_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_log_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_reboot.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #0D0D0D
4 | #E4801401
5 | #ffdad7
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/styles_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v28/styles_md2_impl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v31/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00AF9C
4 | #00796B
5 | #e0e0e0
6 | #e0e0e0
7 | @color/ic_launcher_background
8 | #ffdad7
9 | #410102
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 |
6 | 2dp
7 | 4dp
8 | 8dp
9 | 12dp
10 | 16dp
11 | 28dp
12 | 32dp
13 | 48dp
14 | 80dp
15 |
16 | 56dp
17 |
18 | 24sp
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/resources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Magisk
6 | Zygisk
7 |
8 |
9 | \@topjohnwu
10 | \@diareuse
11 | PayPal
12 | Patreon
13 | Twitter
14 | GitHub
15 |
16 | @drawable/ic_logo
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles_md2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
26 |
27 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/values/theme_overlay.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("MagiskPlugin")
3 | }
4 |
5 | tasks.register("clean", Delete::class) {
6 | delete(rootProject.buildDir)
7 | }
8 |
--------------------------------------------------------------------------------
/buildSrc/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | }
4 | repositories {
5 | google()
6 | mavenCentral()
7 | }
8 |
9 | gradlePlugin {
10 | plugins {
11 | register("MagiskPlugin") {
12 | id = "MagiskPlugin"
13 | implementationClass = "MagiskPlugin"
14 | }
15 | }
16 | }
17 |
18 | dependencies {
19 | implementation(kotlin("gradle-plugin", "1.8.10"))
20 | implementation("com.android.tools.build:gradle:8.0.0-beta05")
21 | implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3")
22 | implementation("org.lsposed.lsparanoid:gradle-plugin:0.5.0")
23 | implementation("org.eclipse.jgit:org.eclipse.jgit:6.4.0.202211300538-r")
24 | }
25 |
--------------------------------------------------------------------------------
/config.prop.sample:
--------------------------------------------------------------------------------
1 | ##########################################################
2 | # All variables in config.prop are optional
3 | # Removing or leaving them blank will keep default values
4 | ##########################################################
5 |
6 | # The version name of Magisk. Default: git HEAD short SHA1
7 | version=string
8 |
9 | # Output path. Default: out
10 | outdir=string
11 |
12 | #####################################################
13 | # Signing configs for signing zips and APKs
14 | # These 4 variables has to be either all set or not
15 | #####################################################
16 |
17 | # Path to keystore file
18 | keyStore=string
19 | # Keystore password
20 | keyStorePass=string
21 | # The desired key alias in the keystore
22 | keyAlias=string
23 | # Password of specified key alias
24 | keyPass=string
25 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Magisk Documentation
2 |
3 | - [Installation Instructions](install.md)
4 | - [Frequently Asked Questions](faq.md)
5 | - [Release Notes](releases/index.md)
6 | - [Magisk Changelog](changes.md)
7 |
8 | The following sections are for developers
9 |
10 | - [Developer Guides](guides.md)
11 | - [Magisk Tools](tools.md)
12 | - [Internal Details](details.md)
13 | - [Android Booting Shenanigans](boot.md)
14 |
--------------------------------------------------------------------------------
/docs/images/device_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/device_info.png
--------------------------------------------------------------------------------
/docs/images/disable_auto_ota.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/disable_auto_ota.png
--------------------------------------------------------------------------------
/docs/images/install_inactive_slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/install_inactive_slot.png
--------------------------------------------------------------------------------
/docs/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/logo.png
--------------------------------------------------------------------------------
/docs/images/manager_reboot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/manager_reboot.png
--------------------------------------------------------------------------------
/docs/images/ota_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/ota_done.png
--------------------------------------------------------------------------------
/docs/images/restore_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/docs/images/restore_img.png
--------------------------------------------------------------------------------
/docs/releases/19100.md:
--------------------------------------------------------------------------------
1 | # 2019.5.1 Magisk v19.1
2 | Finally, a lovely stable release!
3 |
4 | For those that were using v18.1, here are some quick highlights of v19.0
5 |
6 | - Imageless Magisk: Although module migration was tested, there are still chances that your modules will get lost in the process. Be prepared to reinstall your existing modules in that case.
7 | - Native 64-bit support
8 | - Zygote Ptrace Based MagiskHide
9 |
10 | Other than adding support for Samsung system-as-root devices, this release is mostly bug fixes from v19.0. Enjoy :)
11 |
12 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
13 |
--------------------------------------------------------------------------------
/docs/releases/19200.md:
--------------------------------------------------------------------------------
1 | # TODO
2 |
--------------------------------------------------------------------------------
/docs/releases/19300.md:
--------------------------------------------------------------------------------
1 | # TODO
2 |
--------------------------------------------------------------------------------
/docs/releases/20300.md:
--------------------------------------------------------------------------------
1 | # 2020.1.10 Magisk v20.3
2 |
3 | ### Magisk
4 | - Fix `magiskboot` crashing when dealing with `lz4_legacy` format
5 |
6 | ### Magisk Manager
7 | - Fix MagiskHide app component toggles
8 |
9 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
10 |
--------------------------------------------------------------------------------
/docs/releases/21100.md:
--------------------------------------------------------------------------------
1 | ## 2020.11.13 Magisk v21.1
2 |
3 | v21.1 is a maintenance update from v21.0, mostly addressing bugs, refining some details, and adding new boot image format support (for Pixel 5 and 4a 5G). Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
4 |
5 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
6 |
--------------------------------------------------------------------------------
/docs/releases/21200.md:
--------------------------------------------------------------------------------
1 | ## 2020.12.28 Magisk v21.2
2 |
3 | v21.2 is a maintenance update, mostly addressing bugs, and expanding device compatibility. Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
4 |
5 | ### v21.2
6 |
7 | - [MagiskInit] Detect 2SI after mounting `system_root` on legacy SAR devices
8 | - [General] Make sure `post-fs-data` scripts cannot block more than 35 seconds
9 | - [General] Fix the `magisk --install-module` command
10 | - [General] Trim Windows newline when reading files
11 | - [General] Directly log to file to prevent `logcat` weirdness
12 | - [MagiskBoot] Fix header dump/load for header v3 images
13 |
14 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
15 |
--------------------------------------------------------------------------------
/docs/releases/21400.md:
--------------------------------------------------------------------------------
1 | ## 2021.1.17 Magisk v21.4
2 |
3 | **Update**: v21.4 adds more regression hot fixes.
4 |
5 | Happy 2021! v21.3 adds a workaround for devices with buggy F2FS Linux kernel drivers. This F2FS bug may cause bootloops on many devices. Checkout the full [v21.0 release notes](https://topjohnwu.github.io/Magisk/releases/21000.html) if coming from older releases.
6 |
7 | ### v21.4
8 |
9 | - [MagiskSU] Fix `su -c` behavior that broke many root apps
10 | - [General] Properly handle read/write over sockets (the `broken pipe` issue)
11 |
12 | ### v21.3
13 |
14 | - [MagiskInit] Avoid mounting `f2fs` userdata as it may result in kernel crashes. This shall fix a lot of bootloops
15 | - [MagiskBoot] Fix a minor header checksum bug for `DHTB` header and ASUS `blob` image formats
16 | - [MagiskHide] Allowing hiding isolated processes if the mount namespace is separated
17 |
18 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
19 |
--------------------------------------------------------------------------------
/docs/releases/22100.md:
--------------------------------------------------------------------------------
1 | ## 2021.4.9 Magisk v22.1
2 |
3 | This release is focused on fixing regressions and bugs. Check the [v22.0 release notes](https://topjohnwu.github.io/Magisk/releases/22000.html) if coming from older releases.
4 |
5 | Note: Magisk v22 is the last major version to support Jellybean and Kitkat. Magisk v23 will only support Android 5.0 and higher.
6 |
7 | ### Bug Fixes
8 |
9 | - [App] Prevent multiple installation sessions running in parallel
10 | - [App] Prevent OutOfMemory crashes when checking boot signature on PXA boot images
11 | - [General] Proper cgroup migration implementation
12 | - [General] Rewrite log writer from scratch, should resolve any crashes and deadlocks
13 | - [General] Many scripts updates fixing regressions
14 | - [MagiskHide] Prevent possible deadlock when signal arrives
15 | - [MagiskHide] Partial match process names if necessary
16 | - [MagiskBoot] Preserve and patch AVB 2.0 structures/headers in boot images
17 | - [MagiskBoot] Properly strip out data encryption flags
18 | - [MagiskBoot] Prevent possible integer overflow
19 | - [MagiskInit] Fix `sepolicy.rule` mounting strategy
20 | - [resetprop] Always delete existing `ro.` props before updating. This will fix bootloops that could be caused by modifying device fingerprint properties.
21 |
22 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
23 |
--------------------------------------------------------------------------------
/docs/releases/23000.md:
--------------------------------------------------------------------------------
1 | ## 2021.5.12 Magisk v23.0
2 |
3 | This release is focused on fixing regressions and bugs.
4 |
5 | Note: Magisk v22 is the last major version to support Jellybean and Kitkat. Magisk v23 only supports Android 5.0 and higher.
6 |
7 | ### Bug Fixes
8 |
9 | - [App] Update snet extension. This fixes SafetyNet API errors.
10 | - [App] Fix a bug in the stub app that causes APK installation to fail
11 | - [App] Hide annoying errors in logs when hidden as stub
12 | - [App] Fix issues when patching ODIN tar files when the app is hidden
13 | - [General] Remove all pre Android 5.0 support
14 | - [General] Update BusyBox to use proper libc
15 | - [General] Fix C++ undefined behaviors
16 | - [General] Several `sepolicy.rule` copy/installation fixes
17 | - [MagiskPolicy] Remove unnecessary sepolicy rules
18 | - [MagiskHide] Update package and process name validation logic
19 | - [MagiskHide] Some changes that prevents zygote deadlock
20 |
21 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
22 |
--------------------------------------------------------------------------------
/docs/releases/24200.md:
--------------------------------------------------------------------------------
1 | ## 2022.3.1 Magisk v24.2
2 |
3 | Maintenance release fixing various issues.
4 |
5 | - [MagiskSU] Fix buffer overflow
6 | - [MagiskSU] Fix owner managed multiuser superuser settings
7 | - [MagiskSU] Fix command logging when using `su -c `
8 | - [MagiskSU] Prevent su request indefinite blocking
9 | - [MagiskBoot] Support `lz4_legacy` archive with multiple magic
10 | - [MagiskBoot] Fix `lz4_lg` compression
11 | - [DenyList] Allow targeting processes running as system UID
12 | - [Zygisk] Workaround Samsung's "early zygote"
13 | - [Zygisk] Improved Zygisk loading mechanism
14 | - [Zygisk] Fix application UID tracking
15 | - [Zygisk] Fix improper `umask` being set in zygote
16 | - [App] Fix BusyBox execution test
17 | - [App] Improve stub loading mechanism
18 | - [App] Major app upgrade flow improvements
19 | - [General] Improve commandline error handling and messaging
20 |
21 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
22 |
--------------------------------------------------------------------------------
/docs/releases/24300.md:
--------------------------------------------------------------------------------
1 | ## 2022.3.10 Magisk v24.3
2 |
3 | For those coming from v24.1, check the full changelog for changes introduced in v24.2.
4 |
5 | - [General] Stop using `getrandom` syscall
6 | - [Zygisk] Update API to v3, adding new fields to `AppSpecializeArgs`
7 | - [App] Improve app repackaging installation workflow
8 |
9 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
10 |
--------------------------------------------------------------------------------
/docs/releases/25200.md:
--------------------------------------------------------------------------------
1 | ## 2022.7.20 Magisk v25.2
2 |
3 | Maintenance release fixing various issues.
4 |
5 | - [MagiskInit] Fix a potential issue when stub cpio is used
6 | - [MagiskInit] Fix reboot to recovery when stub cpio is used
7 | - [MagiskInit] Fix sepolicy.rules symlink for rootfs devices
8 | - [General] Better data encryption detection
9 | - [General] Move the whole logging infrastructure into Rust
10 |
11 | ### Full Changelog: [here](https://topjohnwu.github.io/Magisk/changes.html)
12 |
--------------------------------------------------------------------------------
/docs/releases/index.md:
--------------------------------------------------------------------------------
1 | # Release Notes
2 |
3 | - [v25.2](25200.md)
4 | - [v25.1](25100.md)
5 | - [v25.0](25000.md)
6 | - [v24.3](24300.md)
7 | - [v24.2](24200.md)
8 | - [v24.1](24100.md)
9 | - [v24.0](24000.md)
10 | - [v23.0](23000.md)
11 | - [v22.1](22100.md)
12 | - [v22.0](22000.md)
13 | - [v21.4](21400.md)
14 | - [v21.2](21200.md)
15 | - [v21.1](21100.md)
16 | - [v21.0](21000.md)
17 | - [v20.4](20400.md)
18 | - [v20.3](20300.md)
19 | - [v20.2](20200.md)
20 | - [v20.1](20100.md)
21 | - [v20.0](20000.md)
22 | - [v19.4](19400.md)
23 | - [v19.3](19300.md)
24 | - [v19.2](19200.md)
25 | - [v19.1](19100.md)
26 | - [v19.0](19000.md)
27 | - [v18.1](18100.md)
28 | - [v18.0](18000.md)
29 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | org.gradle.jvmargs=-Xmx2560m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | org.gradle.parallel=true
19 |
20 | # Enable build cache
21 | org.gradle.caching=true
22 |
23 | # Android
24 | android.useAndroidX=true
25 | android.databinding.incremental=true
26 | android.injected.testOnly=false
27 | android.nonTransitiveRClass=true
28 |
29 | # Magisk
30 | magisk.stubVersion=35
31 | magisk.versionCode=25210
32 | magisk.ondkVersion=r25.2
33 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pranshoe/Magisk-Monet/45c552d74885f7e81825f2d745674d3bb2dd5c2f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/native/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | obj
3 | libs
4 | /.externalNativeBuild
5 | /.cxx
6 |
--------------------------------------------------------------------------------
/native/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | }
4 |
5 | setupCommon()
6 |
7 | android {
8 | namespace = "com.topjohnwu.magisk.native"
9 |
10 | externalNativeBuild {
11 | ndkBuild {
12 | path("src/Android.mk")
13 | }
14 | }
15 |
16 | sourceSets.getByName("main") {
17 | manifest.srcFile("src/AndroidManifest.xml")
18 | }
19 |
20 | defaultConfig {
21 | externalNativeBuild {
22 | ndkBuild {
23 | // Pass arguments to ndk-build.
24 | arguments(
25 | "B_MAGISK=1", "B_INIT=1", "B_BOOT=1", "B_TEST=1", "B_POLICY=1", "B_PRELOAD=1", "B_PROP=1"
26 | )
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/native/src/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | # This is only used to make the IDE happy, the actual compilation will
3 | # have the target overriden by command-line
4 | target = "aarch64-linux-android"
5 |
--------------------------------------------------------------------------------
/native/src/.gitignore:
--------------------------------------------------------------------------------
1 | test.cpp
2 | target/
3 |
--------------------------------------------------------------------------------
/native/src/Android-rs.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | ###########################
4 | # Rust compilation outputs
5 | ###########################
6 |
7 | LIBRARY_PATH = ../out/$(TARGET_ARCH_ABI)/libmagisk-rs.a
8 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LIBRARY_PATH)))
9 | include $(CLEAR_VARS)
10 | LOCAL_MODULE := magisk-rs
11 | LOCAL_SRC_FILES := $(LIBRARY_PATH)
12 | include $(PREBUILT_STATIC_LIBRARY)
13 | endif
14 |
15 | LIBRARY_PATH = ../out/$(TARGET_ARCH_ABI)/libmagiskboot-rs.a
16 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LIBRARY_PATH)))
17 | include $(CLEAR_VARS)
18 | LOCAL_MODULE := boot-rs
19 | LOCAL_SRC_FILES := $(LIBRARY_PATH)
20 | include $(PREBUILT_STATIC_LIBRARY)
21 | endif
22 |
23 | LIBRARY_PATH = ../out/$(TARGET_ARCH_ABI)/libmagiskinit-rs.a
24 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LIBRARY_PATH)))
25 | include $(CLEAR_VARS)
26 | LOCAL_MODULE := init-rs
27 | LOCAL_SRC_FILES := $(LIBRARY_PATH)
28 | include $(PREBUILT_STATIC_LIBRARY)
29 | endif
30 |
31 | LIBRARY_PATH = ../out/$(TARGET_ARCH_ABI)/libmagiskpolicy-rs.a
32 | ifneq (,$(wildcard $(LOCAL_PATH)/$(LIBRARY_PATH)))
33 | include $(CLEAR_VARS)
34 | LOCAL_MODULE := policy-rs
35 | LOCAL_SRC_FILES := $(LIBRARY_PATH)
36 | include $(PREBUILT_STATIC_LIBRARY)
37 | endif
38 |
--------------------------------------------------------------------------------
/native/src/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/native/src/Application.mk:
--------------------------------------------------------------------------------
1 | APP_BUILD_SCRIPT := src/Android.mk
2 | APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
3 | APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto
4 | APP_LDFLAGS := -flto
5 | APP_CPPFLAGS := -std=c++20
6 | APP_STL := none
7 | APP_PLATFORM := android-21
8 | APP_THIN_ARCHIVE := true
9 | APP_STRIP_MODE := --strip-all
10 |
11 | # Busybox should use stock libc.a
12 | ifdef B_BB
13 | APP_PLATFORM := android-26
14 | APP_LDFLAGS += -T src/lto_fix.lds
15 | ifeq ($(OS),Windows_NT)
16 | APP_SHORT_COMMANDS := true
17 | endif
18 | endif
19 |
--------------------------------------------------------------------------------
/native/src/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | exclude = ["external"]
3 | members = ["base", "boot", "core", "init", "sepolicy"]
4 |
5 | [profile.dev]
6 | opt-level = "z"
7 | lto = true
8 | codegen-units = 1
9 | panic = "abort"
10 | strip = true
11 |
12 | [profile.release]
13 | opt-level = "z"
14 | lto = true
15 | codegen-units = 1
16 | panic = "abort"
17 | strip = true
18 |
19 | [patch.crates-io]
20 | cxx = { path = "external/cxx-rs" }
21 |
--------------------------------------------------------------------------------
/native/src/base/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | # Magisk project-wide common code
4 |
5 | include $(CLEAR_VARS)
6 | LOCAL_MODULE := libbase
7 | LOCAL_C_INCLUDES := src/include $(LOCAL_PATH)/include out/generated
8 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
9 | LOCAL_EXPORT_STATIC_LIBRARIES := libcxx
10 | LOCAL_STATIC_LIBRARIES := libcxx
11 | LOCAL_SRC_FILES := \
12 | new.cpp \
13 | files.cpp \
14 | misc.cpp \
15 | selinux.cpp \
16 | logging.cpp \
17 | stream.cpp \
18 | ../external/cxx-rs/src/cxx.cc
19 | include $(BUILD_STATIC_LIBRARY)
20 |
21 | # All static executables should link with libcompat
22 |
23 | include $(CLEAR_VARS)
24 | LOCAL_MODULE := libcompat
25 | # Workaround "hacky" libc.a missing symbols
26 | # To build Magisk with vanilla NDK, comment out the next line
27 | LOCAL_SRC_FILES := compat/compat.cpp
28 | # Fix static variables' ctor/dtor when using LTO
29 | # See: https://github.com/android/ndk/issues/1461
30 | LOCAL_EXPORT_LDFLAGS := -static -T src/lto_fix.lds
31 | include $(BUILD_STATIC_LIBRARY)
32 |
--------------------------------------------------------------------------------
/native/src/base/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "base"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | path = "lib.rs"
8 |
9 | [dependencies]
10 | cxx = { path = "../external/cxx-rs" }
11 | libc = "0.2"
12 | cfg-if = "1.0"
13 |
--------------------------------------------------------------------------------
/native/src/base/include/base.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../missing.hpp"
4 | #include "../xwrap.hpp"
5 | #include "../files.hpp"
6 | #include "../misc.hpp"
7 | #include "../logging.hpp"
8 | #include
9 |
--------------------------------------------------------------------------------
/native/src/base/include/embed.hpp:
--------------------------------------------------------------------------------
1 | #if defined(__arm__)
2 | #include
3 | #elif defined(__aarch64__)
4 | #include
5 | #elif defined(__i386__)
6 | #include
7 | #elif defined(__x86_64__)
8 | #include
9 | #else
10 | #error Unsupported ABI
11 | #endif
12 |
--------------------------------------------------------------------------------
/native/src/base/lib.rs:
--------------------------------------------------------------------------------
1 | #![feature(format_args_nl)]
2 |
3 | pub use libc;
4 |
5 | pub use files::*;
6 | pub use logging::*;
7 | pub use misc::*;
8 | pub use xwrap::*;
9 |
10 | mod files;
11 | mod logging;
12 | mod misc;
13 | mod xwrap;
14 |
15 | #[cxx::bridge]
16 | pub mod ffi {
17 | #[derive(Copy, Clone)]
18 | pub enum LogLevel {
19 | Error,
20 | Warn,
21 | Info,
22 | Debug,
23 | }
24 |
25 | extern "Rust" {
26 | fn log_with_rs(level: LogLevel, msg: &str);
27 | fn exit_on_error(b: bool);
28 | fn set_log_level_state(level: LogLevel, enabled: bool);
29 | fn cmdline_logging();
30 | }
31 | }
32 |
33 | #[cxx::bridge(namespace = "rust")]
34 | pub mod ffi2 {
35 | extern "Rust" {
36 | fn xpipe2(fds: &mut [i32; 2], flags: i32) -> i32;
37 | fn fd_path(fd: i32, buf: &mut [u8]) -> isize;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/native/src/base/logging.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | extern int (*cpp_logger)(LogLevel level, const char *fmt, va_list ap);
9 |
10 | void LOGD(const char *fmt, ...) __printflike(1, 2);
11 | void LOGI(const char *fmt, ...) __printflike(1, 2);
12 | void LOGW(const char *fmt, ...) __printflike(1, 2);
13 | void LOGE(const char *fmt, ...) __printflike(1, 2);
14 | #define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s\n", ##args, errno, std::strerror(errno))
15 |
--------------------------------------------------------------------------------
/native/src/base/missing.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | static inline int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
10 | union {
11 | sigset_t set;
12 | sigset64_t set64;
13 | } s{};
14 | s.set = *set;
15 | return syscall(__NR_rt_sigtimedwait, &s.set64, info, timeout, sizeof(s.set64));
16 | }
17 |
18 | static inline int fexecve(int fd, char* const* argv, char* const* envp) {
19 | syscall(__NR_execveat, fd, "", argv, envp, AT_EMPTY_PATH);
20 | if (errno == ENOSYS) {
21 | char buf[256];
22 | std::snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
23 | execve(buf, argv, envp);
24 | }
25 | return -1;
26 | }
27 |
--------------------------------------------------------------------------------
/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 malloc(s); }
8 | void* operator new[](std::size_t s) { return malloc(s); }
9 | void operator delete(void *p) { free(p); }
10 | void operator delete[](void *p) { free(p); }
11 | void* operator new(std::size_t s, const std::nothrow_t&) noexcept { return malloc(s); }
12 | void* operator new[](std::size_t s, const std::nothrow_t&) noexcept { return malloc(s); }
13 | void operator delete(void *p, const std::nothrow_t&) noexcept { free(p); }
14 | void operator delete[](void *p, const std::nothrow_t&) noexcept { free(p); }
15 |
--------------------------------------------------------------------------------
/native/src/boot/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "magiskboot"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | crate-type = ["staticlib"]
8 | path = "lib.rs"
9 |
10 | [dependencies]
11 | base = { path = "../base" }
12 |
--------------------------------------------------------------------------------
/native/src/boot/compress.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "format.hpp"
6 |
7 | filter_strm_ptr get_encoder(format_t type, stream_ptr &&base);
8 |
9 | filter_strm_ptr get_decoder(format_t type, stream_ptr &&base);
10 |
11 | void compress(const char *method, const char *infile, const char *outfile);
12 |
13 | void decompress(char *infile, const char *outfile);
14 |
--------------------------------------------------------------------------------
/native/src/boot/hexpatch.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include "magiskboot.hpp"
6 |
7 | using namespace std;
8 |
9 | static void hex2byte(const char *hex, uint8_t *buf) {
10 | char high, low;
11 | for (int i = 0, length = strlen(hex); i < length; i += 2) {
12 | high = toupper(hex[i]) - '0';
13 | low = toupper(hex[i + 1]) - '0';
14 | buf[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
15 | }
16 | }
17 |
18 | int hexpatch(const char *file, const char *from, const char *to) {
19 | int patched = 1;
20 |
21 | auto m = mmap_data(file, true);
22 |
23 | vector pattern(strlen(from) / 2);
24 | vector patch(strlen(to) / 2);
25 |
26 | hex2byte(from, pattern.data());
27 | hex2byte(to, patch.data());
28 |
29 | uint8_t * const end = m.buf + m.sz;
30 | for (uint8_t *curr = m.buf; curr < end; curr += pattern.size()) {
31 | curr = static_cast(memmem(curr, end - curr, pattern.data(), pattern.size()));
32 | if (curr == nullptr)
33 | return patched;
34 | fprintf(stderr, "Patch @ %08X [%s] -> [%s]\n", (unsigned)(curr - m.buf), from, to);
35 | memset(curr, 0, pattern.size());
36 | memcpy(curr, patch.data(), patch.size());
37 | patched = 0;
38 | }
39 |
40 | return patched;
41 | }
42 |
--------------------------------------------------------------------------------
/native/src/boot/lib.rs:
--------------------------------------------------------------------------------
1 | pub use base;
2 |
--------------------------------------------------------------------------------
/native/src/boot/magiskboot.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #define HEADER_FILE "header"
6 | #define KERNEL_FILE "kernel"
7 | #define RAMDISK_FILE "ramdisk.cpio"
8 | #define SECOND_FILE "second"
9 | #define EXTRA_FILE "extra"
10 | #define KER_DTB_FILE "kernel_dtb"
11 | #define RECV_DTBO_FILE "recovery_dtbo"
12 | #define DTB_FILE "dtb"
13 | #define NEW_BOOT "new-boot.img"
14 |
15 | int unpack(const char *image, bool skip_decomp = false, bool hdr = false);
16 | void repack(const char *src_img, const char *out_img, bool skip_comp = false);
17 | int split_image_dtb(const char *filename);
18 | int hexpatch(const char *file, const char *from, const char *to);
19 | int cpio_commands(int argc, char *argv[]);
20 | int dtb_commands(int argc, char *argv[]);
21 |
22 | uint32_t patch_verity(void *buf, uint32_t size);
23 | uint32_t patch_encryption(void *buf, uint32_t size);
24 | bool check_env(const char *name);
25 |
--------------------------------------------------------------------------------
/native/src/core/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "magisk"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | crate-type = ["staticlib"]
8 | path = "lib.rs"
9 |
10 | [dependencies]
11 | base = { path = "../base" }
12 | cxx = { path = "../external/cxx-rs" }
13 |
--------------------------------------------------------------------------------
/native/src/core/applet_stub.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | int main(int argc, char *argv[]) {
8 | if (argc < 1)
9 | return 1;
10 | enable_selinux();
11 | cmdline_logging();
12 | init_argv0(argc, argv);
13 | umask(0);
14 | return APPLET_STUB_MAIN(argc, argv);
15 | }
16 |
--------------------------------------------------------------------------------
/native/src/core/core.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | extern bool RECOVERY_MODE;
7 | extern std::atomic pkg_xml_ino;
8 |
9 | std::string find_preinit_device();
10 | void unlock_blocks();
11 | void reboot();
12 | void start_log_daemon();
13 | void setup_logfile(bool reset);
14 | std::string read_certificate(int fd, int version = -1);
15 |
16 | // Module stuffs
17 | void handle_modules();
18 | void load_modules();
19 | void disable_modules();
20 | void remove_modules();
21 | void exec_module_scripts(const char *stage);
22 |
23 | // Scripting
24 | void exec_script(const char *script);
25 | void exec_common_scripts(const char *stage);
26 | void exec_module_scripts(const char *stage, const std::vector &modules);
27 | void install_apk(const char *apk);
28 | void uninstall_pkg(const char *pkg);
29 | void clear_pkg(const char *pkg, int user_id);
30 | [[noreturn]] void install_module(const char *file);
31 |
--------------------------------------------------------------------------------
/native/src/core/lib.rs:
--------------------------------------------------------------------------------
1 | pub use base;
2 | use logging::*;
3 |
4 | mod logging;
5 |
6 | #[cxx::bridge]
7 | pub mod ffi {
8 | extern "Rust" {
9 | fn rust_test_entry();
10 | fn android_logging();
11 | fn magisk_logging();
12 | fn zygisk_logging();
13 | }
14 | }
15 |
16 | fn rust_test_entry() {}
17 |
--------------------------------------------------------------------------------
/native/src/exported_sym.txt:
--------------------------------------------------------------------------------
1 | {
2 | zygisk_inject_entry;
3 | };
4 |
--------------------------------------------------------------------------------
/native/src/external/pcre2_workaround.c:
--------------------------------------------------------------------------------
1 | // Workaround pcre2_chartables.c symlink to pcre2_chartables.c.dist failing on Windows NDK if Cygwin git used,
2 | // and NDK not directly accepting a .c.dist file in LOCAL_SRC_FILES list.
3 |
4 | #include "pcre/src/pcre2_chartables.c.dist"
5 |
--------------------------------------------------------------------------------
/native/src/external/systemproperties/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 | LOCAL_MODULE:= libsystemproperties
5 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
6 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
7 | LOCAL_STATIC_LIBRARIES := libcxx
8 | LOCAL_CFLAGS := -Wno-deprecated-declarations
9 | LOCAL_SRC_FILES := \
10 | context_node.cpp \
11 | contexts_serialized.cpp \
12 | contexts_split.cpp \
13 | prop_area.cpp \
14 | prop_info.cpp \
15 | system_properties.cpp \
16 | system_property_api.cpp \
17 | system_property_set.cpp \
18 | property_info_parser.cpp
19 |
20 | include $(BUILD_STATIC_LIBRARY)
21 |
--------------------------------------------------------------------------------
/native/src/external/systemproperties/include/async_safe/log.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define async_safe_format_buffer snprintf
4 | #define async_safe_format_log(...) /* NOP */
5 |
--------------------------------------------------------------------------------
/native/src/external/systemproperties/include/private/ErrnoRestorer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #include "bionic_macros.h"
22 |
23 | class ErrnoRestorer {
24 | public:
25 | explicit ErrnoRestorer() : saved_errno_(errno) {
26 | }
27 |
28 | ~ErrnoRestorer() {
29 | errno = saved_errno_;
30 | }
31 |
32 | void override(int new_errno) {
33 | saved_errno_ = new_errno;
34 | }
35 |
36 | private:
37 | int saved_errno_;
38 |
39 | BIONIC_DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
40 | };
41 |
--------------------------------------------------------------------------------
/native/src/include/resetprop.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | int setprop(const char *name, const char *value, bool prop_svc = true);
7 | std::string getprop(const char *name, bool persist = false);
8 | void getprops(void (*callback)(const char *, const char *, void *),
9 | void *cookie = nullptr, bool persist = false);
10 | int delprop(const char *name, bool persist = false);
11 | void load_prop_file(const char *filename, bool prop_svc = true);
12 |
--------------------------------------------------------------------------------
/native/src/include/socket.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | struct sock_cred : public ucred {
10 | std::string context;
11 | };
12 |
13 | socklen_t setup_sockaddr(sockaddr_un *sun, const char *name);
14 | bool get_client_cred(int fd, sock_cred *cred);
15 | std::vector recv_fds(int sockfd);
16 | int recv_fd(int sockfd);
17 | int send_fds(int sockfd, const int *fds, int cnt);
18 | int send_fd(int sockfd, int fd);
19 | int read_int(int fd);
20 | int read_int_be(int fd);
21 | void write_int(int fd, int val);
22 | void write_int_be(int fd, int val);
23 | std::string read_string(int fd);
24 | bool read_string(int fd, std::string &str);
25 | void write_string(int fd, std::string_view str);
26 |
--------------------------------------------------------------------------------
/native/src/init/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "magiskinit"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | crate-type = ["staticlib"]
8 | path = "lib.rs"
9 |
10 | [dependencies]
11 | base = { path = "../base" }
12 | cxx = "1.0.69"
13 |
--------------------------------------------------------------------------------
/native/src/init/lib.rs:
--------------------------------------------------------------------------------
1 | pub use logging::*;
2 |
3 | mod logging;
4 |
5 | #[cxx::bridge(namespace = "rust")]
6 | pub mod ffi2 {
7 | extern "Rust" {
8 | fn setup_klog();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/native/src/init/logging.rs:
--------------------------------------------------------------------------------
1 | use base::ffi::LogLevel;
2 | use base::*;
3 | use std::fmt::Arguments;
4 |
5 | extern "C" {
6 | fn klog_write(msg: *const u8, len: i32);
7 | }
8 |
9 | pub fn setup_klog() {
10 | const PREFIX: &[u8; 12] = b"magiskinit: ";
11 | const PFX_LEN: usize = PREFIX.len();
12 |
13 | fn klog_fmt(_: LogLevel, args: Arguments) {
14 | let mut buf: [u8; 4096] = [0; 4096];
15 | buf[..PFX_LEN].copy_from_slice(PREFIX);
16 | let len = fmt_to_buf(&mut buf[PFX_LEN..], args) + PFX_LEN;
17 | unsafe {
18 | klog_write(buf.as_ptr(), len as i32);
19 | }
20 | }
21 |
22 | fn klog_write_impl(_: LogLevel, msg: &[u8]) {
23 | unsafe {
24 | klog_write(msg.as_ptr(), msg.len() as i32);
25 | }
26 | }
27 |
28 | let logger = Logger {
29 | fmt: klog_fmt,
30 | write: klog_write_impl,
31 | flags: 0,
32 | };
33 | exit_on_error(false);
34 | unsafe {
35 | LOGGER = logger;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/native/src/init/preload.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | __attribute__((constructor))
7 | static void preload_init() {
8 | // Make sure our next exec won't get bugged
9 | unsetenv("LD_PRELOAD");
10 | unlink("/dev/preload.so");
11 | }
12 |
13 | int security_load_policy(void *data, size_t len) {
14 | int (*load_policy)(void *, size_t) = dlsym(RTLD_NEXT, "security_load_policy");
15 | // Skip checking errors, because if we cannot find the symbol, there
16 | // isn't much we can do other than crashing anyways.
17 | int result = load_policy(data, len);
18 |
19 | // Wait for ack
20 | int fd = open("/sys/fs/selinux/enforce", O_RDONLY);
21 | char c;
22 | read(fd, &c, 1);
23 | close(fd);
24 |
25 | return result;
26 | }
27 |
--------------------------------------------------------------------------------
/native/src/lto_fix.lds:
--------------------------------------------------------------------------------
1 | SECTIONS {
2 | .init_array : {
3 | *(SORT_BY_INIT_PRIORITY(.init_array.*))
4 | *(EXCLUDE_FILE(*crtend_android.o) .init_array)
5 | }
6 | } INSERT AFTER .fini_array;
7 | SECTIONS {
8 | .fini_array : {
9 | *(SORT_BY_INIT_PRIORITY(.fini_array.*))
10 | *(EXCLUDE_FILE(*crtend_android.o) .fini_array)
11 | }
12 | } INSERT BEFORE .init_array;
13 |
--------------------------------------------------------------------------------
/native/src/resetprop/prop.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include