Compare commits

...

339 Commits

Author SHA1 Message Date
LoveSy c6f0762510 Use pidfd_open for setns
which is more efficient on newer kernel
2024-05-20 03:26:55 +08:00
LoveSy 941a363c5a
Support waiting on non-exist prop 2024-05-18 13:55:33 +08:00
Arbri çoçka 2afcdc64a0 Update strings.xml sq 2024-05-18 13:52:31 +08:00
VD $ VD171 @ Priv8 3c66c4bbc5 Update PORTUGUESE translation 2024-05-18 13:52:14 +08:00
VD $ VD171 @ Priv8 9f5cd5e1cc Update PORTUGUESE translation 2024-05-18 13:52:14 +08:00
kubalav a35f2bb73b Update Slovak translation 2024-05-18 13:51:59 +08:00
topjohnwu 6cf00130f4 Check Magisk version instead of app version 2024-05-15 12:42:55 +08:00
topjohnwu 6c27ba6b88 Rename db entry name 2024-05-15 12:42:55 +08:00
vvb2060 dd3b9980e7 app: add safe mode config to menu 2024-05-15 12:42:55 +08:00
vvb2060 02e189a029 core: add safe mode config to db 2024-05-15 12:42:55 +08:00
topjohnwu 72b8d12ee4 Update development guide 2024-05-11 20:40:33 -07:00
topjohnwu eed03080c1 Update to ONDK r27.1 2024-05-09 09:42:40 -07:00
LoveSy 090cb4b0f9 Upgrade AGP to 8.4.0 2024-05-09 09:42:27 -07:00
topjohnwu 6f2c76b898 Fix build script 2024-05-09 02:19:24 -07:00
topjohnwu f61827cbec Switch rustup_wrapper to Rust implementation
For better Windows portability
2024-05-09 02:19:07 -07:00
topjohnwu 3f2264f2c7 Support rustup wrapper 2024-05-09 00:34:12 -07:00
topjohnwu c1cadf4bdc Update build.py to use pathlib 2024-05-09 00:31:41 -07:00
Rodrigo Martínez 0e56991369 Improve and add missing strings for Spanish 2024-04-29 22:23:02 -07:00
LoveSy 4dc1c59040 add missing `xz_dec_end` 2024-04-29 22:22:47 -07:00
topjohnwu 33b7b8b297 Update resetprop 2024-04-26 16:42:24 -07:00
topjohnwu e6af5ed460 Address Rust warnings 2024-04-26 16:28:46 -07:00
topjohnwu b678afa4b6 Update to ONDK r27.0
Co-authored-by: LoveSy <shana@zju.edu.cn>
2024-04-26 03:09:44 -07:00
WINZORT 4bac2df4e7
Improve turkish locales and add the missing strings 2024-04-18 02:14:21 -07:00
igor 50416eee09 Improve Portuguese translation 2024-04-18 02:13:50 -07:00
igor 73cf501d33 Improve Brazilian Portuguese translation 2024-04-18 02:13:50 -07:00
Hen_Ry d2b7907bed
Update german strings.xml 2024-04-18 02:13:28 -07:00
topjohnwu 99d5dd5ea8 Update crt0 2024-04-17 10:12:27 -07:00
cloudchamb3r 5fdb841fa8 Fix typo
Fix typo in values-ko/strings.xml
2024-04-17 09:18:14 -07:00
topjohnwu 7c88484d64 Fix #7988 2024-04-16 19:45:01 -07:00
topjohnwu b22b6a4204 Refactor cpio 2024-04-10 22:46:21 -07:00
topjohnwu 2a3d34c812 Fix mkdirs 2024-04-10 22:36:47 -07:00
topjohnwu c50ee722a1 Use memmem for finding needle in haystack 2024-04-10 14:57:44 -07:00
topjohnwu ffc1e38e48 Add 32 bit CI 2024-04-10 02:56:23 -07:00
topjohnwu 6219d5fcbf Update crt0 for 32 bit 2024-04-10 02:43:37 -07:00
topjohnwu 2e4440b702 Support 32-bit magiskboot 2024-04-09 19:34:14 -07:00
topjohnwu 0d9ec0931b Code cleanup 2024-04-08 23:00:59 -07:00
vvb2060 60e8415369 Make denylist work when zygisk is disabled
Co-authored-by: topjohnwu <topjohnwu@gmail.com>
2024-04-08 23:00:50 -07:00
LoveSy 652a26d5d9 Fix comment of sepolicy 2024-04-03 21:03:41 -07:00
topjohnwu f57839379a Update RustCrypto dependencies 2024-04-03 21:03:05 -07:00
LoveSy 36bd00a046 Add p521 to magiskboot 2024-04-03 21:03:05 -07:00
topjohnwu fb5ee86615 Install one single ABI in ramdisk 2024-03-31 22:01:22 -07:00
topjohnwu 30bf5c8448 Fix typos 2024-03-31 14:17:25 -07:00
topjohnwu 2051836a73 Remove unused code 2024-03-30 21:03:51 -07:00
topjohnwu 2cb0af1ff3 Move revert_unmount into Rust 2024-03-30 02:51:39 -07:00
topjohnwu a1b6568226 Implement preinit related features in Rust 2024-03-28 14:11:03 -07:00
topjohnwu 1eddbfd72c Use const_format for const strings 2024-03-26 18:03:40 -07:00
topjohnwu 21ed095601 Update crt0 2024-03-25 16:11:02 -07:00
Js0n 000a2e4d59 Upgrade AGP to 8.3.1 2024-03-22 17:02:18 -07:00
Js0n 7abe635de9 fix: AGP 8.3.X 2024-03-22 17:02:18 -07:00
topjohnwu 9a008c17ba Optimize for binary size 2024-03-22 16:53:44 -07:00
topjohnwu 08dbf728a4 Allow platform_app to access MagiskSU 2024-03-22 16:53:44 -07:00
topjohnwu 4670f762d3 Disable debug only features 2024-03-22 16:53:44 -07:00
topjohnwu efa49567fa Fix parsing logic for term and sterm 2024-03-21 18:17:28 -07:00
topjohnwu 0ffc4527a7 Better error reporting 2024-03-21 15:10:34 -07:00
topjohnwu dd9d43be96 Move sepolicy parsing error message into Rust 2024-03-21 14:07:28 -07:00
topjohnwu 865fca71a5 Optimize sepolicy rules
Close #7916

Co-authored-by: vvb2060 <vvb2060@gmail.com>
2024-03-21 01:51:35 -07:00
topjohnwu 6b4baa3bcd Change a little parsing handling 2024-03-21 00:04:09 -07:00
topjohnwu a9ee2d7d18 Fix xperm parsing logic 2024-03-20 23:13:54 -07:00
topjohnwu d654b9cb97 Several code cleanups in sepolicy 2024-03-20 23:09:22 -07:00
LoveSy 4d2921e742 Rewrite sepolicy statement parsing in Rust 2024-03-20 10:12:23 -07:00
vvb2060 ecc74d45d1 Let magic mount optional 2024-03-19 23:21:41 -07:00
vvb2060 5de597f079 No need to unshare 2024-03-19 23:21:41 -07:00
LoveSy 156b0e67ca No need extra tmpfs for worker 2024-03-19 23:21:41 -07:00
vvb2060 10069215f4 Rename dir name 2024-03-19 23:21:41 -07:00
LoveSy 92b305a389 Remove unnecessary mirror for magic mount
Mirror was previously used for accessing the original file during
magic mount when we are using a tmpfs to cover the target. However,
since we introduce atomic mount, we switch all tmpfs mount in
worker and then move to the target at once. It means that we can
still access the original file when we are constructing the tmpfs
mount point. Thus we no longer need mirror.
2024-03-19 23:21:41 -07:00
topjohnwu d20b30c771 Update libsepol
Close #7915
2024-03-19 02:54:01 -07:00
topjohnwu 83209b21ff Release new canary build 2024-03-19 00:51:07 -07:00
topjohnwu 81658d45f7 Support tar with files larger than 8GiB
Fix #7838
2024-03-14 16:54:46 -07:00
topjohnwu c951b208a1 Always update stub APK when upgrade 2024-03-14 14:31:02 -07:00
topjohnwu 050a073771 Make all I/O suspendable 2024-03-12 03:24:42 -07:00
topjohnwu 21d374214f Minor cleanup of DownloadEngine 2024-03-12 03:14:06 -07:00
LoveSy 19ea25a9d0
Upgrade AGP 2024-03-08 17:12:46 -08:00
topjohnwu dbf6e40dfe Ensure stub APK is expected
Fix #7884
2024-03-08 17:09:54 -08:00
topjohnwu d56f4fbc90 Fix stub on API 34 2024-03-08 15:57:49 -08:00
topjohnwu 73c3d741a7 Reorganize some code 2024-03-06 18:07:01 -08:00
pndwal 2b5fc75127
Update faq.md
Since system Safe Mode may activate without Magisk 'Safe Mode', this clarification will prevent users from erroneously concluding either that Safe Mode doesn't work or that modules are not the issue since 'Safe Mode' was apparently triggered...

Fixes this: #4624
2024-03-06 17:48:54 -08:00
osm0sis 991802ab82 Add no decompression flag to magiskboot split 2024-03-06 16:15:30 -08:00
WindowsFan9600 7f6b5305ba Improve Turkish language translation
Updated "reboot_download" string
2024-03-06 02:37:58 -08:00
canyie 825c6c4316 Reverse format template argument order 2024-03-06 01:39:16 -08:00
canyie f00408c793 Fix zygote restart monitor 2024-03-06 01:39:16 -08:00
topjohnwu a6ff3672af Update crt0 2024-03-04 16:42:25 -08:00
LoveSy 2290ddeb89 Fix segfault when sepolicy.rule has empty line 2024-03-02 06:15:45 -08:00
topjohnwu 74af79ad03 Update crt0 2024-03-02 05:57:48 -08:00
LoveSy b6c24a3a8a No more sony `init.real` tricks
Co-authored-by: canyie <a1364259@163.com>
Co-authored-by: vvb2060 <vvb2060@gmail.com>
2024-02-29 23:40:00 -08:00
LoveSy a8c2ae223a Avoid hexpatch /init for 2SI when possible
Previous we hexpatch /init from /system/bin/init to /data/magiskinit
to redirect the second stage init. However, some devices like sony
has /init that does not directly invoke /system/bin/init, and thus
the hexpatch fails.

In this patch, we further make use of AOSP `SwitchRoot` to help us
bind mount /data/magisk to /system/bin/init after `SwitchRoot`.

Two important assumption about 2SI are i) that the second stage init
is always /system/bin/init and ii) that the /sdcard (path after
`SwitchRoot`) is always a symlink to `/storage/self/primary`. When
these assumptions hold, during first stage init (before `SwitchRoot`)
we can bind mount magiskinit to /sdcard, and create a symlink
/storage/self/primary to /system/system/bin/init. By these steps,
during `SwitchRoot`, AOSP init will try to mount move /sdcard to
/system/sdcard. And /system/sdcard is symlink to /storage/self/primary,
it will try to mount move /sdcard to /storage/self/primary. And
/storage/self/primary in ramfs is now a symlink that points to
/system/system/bin/init, thus AOSP will try to mount move /sdcard
(which is a bind mount to magiskinit) to /system/system/bin/init.
After chroot done by AOSP init, we then have a magiskinit bind mount
on /system/bin/init, which is the second stage init.

An edge case is that some devices (like meizu) use 2SI but
does not switch root. In this case, they must already have a /sdcard
in the ramfs, thus we can check if /sdcard exists and fallback to
hexpatch.
2024-02-29 23:40:00 -08:00
topjohnwu 953d44302c Remove ancient NDK binaries 2024-02-29 23:26:58 -08:00
topjohnwu 24e46a5971 Build magiskboot with crt0 2024-02-29 02:36:05 -08:00
topjohnwu b1297c4192 Less usage of C stdio 2024-02-28 15:52:03 -08:00
topjohnwu 9ae328fd84 Further reduce code size 2024-02-28 11:19:56 -08:00
topjohnwu 625a1d6f44 Remove seek support from streams 2024-02-28 11:07:53 -08:00
topjohnwu 987e5f5413 Address clippy warnings 2024-02-27 21:03:34 -08:00
topjohnwu 715284b70d Reorganize code 2024-02-27 18:14:30 -08:00
LoveSy 62fc7868ac Use self implemented parse_mount_info 2024-02-27 17:03:22 -08:00
topjohnwu 1a70796339 Replace all parse_mount_info usage with Rust 2024-02-27 03:49:17 -08:00
topjohnwu af6965eefa Update init logging implementation
Use less std::fs
2024-02-26 17:49:11 -08:00
topjohnwu 8f7d2e38f7 Make crt0 an external submodule 2024-02-26 17:34:17 -08:00
topjohnwu be433fa667 Use Rust for formatting
The fprintf implementation included in crt0 is too rudimental
2024-02-26 00:26:23 -08:00
topjohnwu 0ccd6e7381 Fix fread and fwrite implementation 2024-02-25 23:20:30 -08:00
topjohnwu 907bbbda41 Remove usage of patched static lib 2024-02-25 22:11:34 -08:00
topjohnwu 4393bc077d Implement string routines 2024-02-25 21:12:19 -08:00
topjohnwu 365b373480 Make it easy to build without crt0 2024-02-24 22:32:22 -08:00
topjohnwu 47e6dd286d Minor fixes 2024-02-24 22:00:09 -08:00
topjohnwu 0dbaf52566 Make all platforms build properly 2024-02-24 05:10:54 -08:00
topjohnwu 66f49dfab5 Remove unnecessary lock usage 2024-02-24 04:20:28 -08:00
topjohnwu f8967e9274 Implement strerror 2024-02-24 04:02:46 -08:00
topjohnwu a4f008fde5 Reorganize files 2024-02-24 03:41:22 -08:00
topjohnwu e9980c778b Implement stub functions 2024-02-24 03:41:03 -08:00
topjohnwu 06b6fb0c33 Add setenv 2024-02-24 03:27:09 -08:00
topjohnwu 38cb3d4105 Add dirent implementation 2024-02-24 03:26:53 -08:00
topjohnwu db99caf258 Use execve directly 2024-02-24 01:47:11 -08:00
topjohnwu 39dbffadfe Complete stdio 2024-02-24 01:28:58 -08:00
topjohnwu b7505c3c9c Remove fopen usage in magiskinit 2024-02-24 00:45:07 -08:00
topjohnwu 3185e5a7ca Introduce string/mem functions 2024-02-23 23:56:31 -08:00
topjohnwu e0cbe28711 Add the generic syscall function 2024-02-23 18:41:39 -08:00
topjohnwu 66cee19cea Add printf and sscanf family 2024-02-23 17:44:12 -08:00
topjohnwu 2ec29ade79 Add all missing syscalls 2024-02-23 14:35:12 -08:00
topjohnwu c865d4e187 Add memory allocator 2024-02-22 21:22:27 -08:00
topjohnwu a42a0a53ce Declare more symbols 2024-02-22 21:22:27 -08:00
topjohnwu 6d79de7d71 Initial crt0 implementation
Builds but cannot link, missing a lot of symbols
2024-02-22 21:22:27 -08:00
topjohnwu 7e9abe6e90 Update ONDK 2024-02-22 20:58:40 -08:00
残页 4d5510be4f Prompt users to use reboot button in System Updates
So the update engine can write verify info of partitions which fixes bootloop on newer Pixel devices
2024-02-19 02:14:12 -08:00
topjohnwu b04e1394c0 Update README 2024-02-07 14:39:53 -08:00
topjohnwu 2aa923191e Rename DownloadManager to DownloadEngine
Also add some documentation
2024-02-06 17:54:15 -08:00
topjohnwu 4bf1c74164 Disable foreground service on API 34+ 2024-02-06 17:29:42 -08:00
topjohnwu 472c7878b2 Update AGP 2024-02-06 17:04:48 -08:00
topjohnwu 38ad871e33 Use user-initiated jobs for download tasks on API 34+ 2024-02-06 17:04:39 -08:00
topjohnwu c5d34670c4 Isolate download logic from service lifecycle 2024-02-06 00:56:14 -08:00
topjohnwu 154121f3dd Release new canary build 2024-02-02 23:51:35 -08:00
topjohnwu 3d91a561fe Update README 2024-02-02 23:35:14 -08:00
topjohnwu 2c6adbc69b Release Magisk v27.0 2024-02-02 22:54:41 -08:00
topjohnwu 5280982363 Add v27.0 changelog 2024-02-02 22:47:35 -08:00
topjohnwu 18c45ae289 Update cxx and Rust dependencies 2024-02-02 14:35:30 -08:00
LoveSy 41fbd2a7be Upgrade gradle 2024-02-02 10:55:11 -08:00
LoveSy 5e45884af4 Use Apple Silicon for CI
https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
2024-02-01 15:09:42 -08:00
topjohnwu d78ee171bc Release new canary build 2024-01-30 15:59:02 -08:00
LoveSy 356ee1febd Code clean up 2024-01-30 11:07:37 -08:00
LoveSy cc044ccc4c Fix zygisk unload 2024-01-30 11:07:37 -08:00
LoveSy 9c638cc463 Remove rust workaround 2024-01-29 15:07:21 -08:00
topjohnwu df786eb2b6 Separate Linux and other jobs 2024-01-29 01:53:09 -08:00
topjohnwu 8e7186eebb Try out composite actions 2024-01-29 01:36:51 -08:00
topjohnwu 74b7b84561 Test all APIs on Linux 2024-01-28 00:46:03 -08:00
topjohnwu 308c9999fa Properly detect package changes 2024-01-28 00:42:43 -08:00
topjohnwu 930bb8687f Minor zygisk refactoring 2024-01-25 00:17:47 -08:00
topjohnwu f2c4288d2d Run pthread_atfork only once
Close #7704
2024-01-25 00:17:05 -08:00
topjohnwu b44141ae39 Run tests on Linux 2024-01-22 18:10:26 -08:00
kam821 86e0020964 Update Polish translation
- Added missing strings, fixed translation, escaped quotas.
- Some context dependent values (like target_pid) may require better translation in the future.
- Also, 'DenyList' translation, although correct, could be replaced in the future by better fitting polish equivalent of 'block list' / 'rejection list'.
2024-01-17 16:13:20 -08:00
残页 94d3daeadf Fix Sony init.real check 2024-01-17 16:09:50 -08:00
LoveSy 79334b7702 One stage zygisk loading 2024-01-11 16:19:39 -08:00
LoveSy df66458db6 Check full path of init.rc instead of its dir
Some devices has `/system/etc/init/hw` but has no init.rc in it.
2024-01-11 16:18:57 -08:00
LoveSy 97705704e2 install or uninstall apk asynchronously 2024-01-11 16:16:36 -08:00
topjohnwu 1206179580 Update dependencies 2024-01-10 15:46:30 -08:00
topjohnwu a0b8aa4da6 Release new canary build 2023-12-27 01:42:42 +08:00
topjohnwu 65207f96c8 Create custom cxx binding to Utf8CStr 2023-12-26 23:10:55 +08:00
Abhishek Girish 062e498bdd
Update Malayalam translations 2023-12-25 18:46:08 +08:00
topjohnwu 1057cb3e3c Set serial on Rust binding 2023-12-24 04:36:58 +08:00
topjohnwu 2dd23b2518 Update system_properties 2023-12-24 04:36:58 +08:00
RafaeloxMC 8cab12998c Update strings.xml / German translation 2023-12-23 16:49:47 +08:00
topjohnwu 48b1c26dc8 Prevent race condition in wait 2023-12-23 06:33:12 +08:00
topjohnwu f1e0bc3e4a Use platform implementation if possible 2023-12-23 06:24:20 +08:00
topjohnwu 38527cd58f Slightly change wait usage and API 2023-12-23 06:23:29 +08:00
LoveSy e94d65b4b2 Add `resetprop -w` for waiting property change
It's very easy to wait for property change both in Java and C++,
but it's not the case in shell script. With this patch, developers
can now easily to wait for property change, just like what we have
in `.rc` files, and to wait for boot complete.
2023-12-23 00:12:42 +08:00
LoveSy 27ece3c7df Keep mirror shared before magic mount
This allows mounting during post-fs-data be kept after magic mount
2023-12-22 21:39:03 +08:00
LoveSy 06687abffc Fix magisk --stop by making mirror shared
Previously mirror is private and then unshared to zygote, which
makes magisk --stop cannot propagate umount mirror to zygote.
2023-12-22 21:39:03 +08:00
vvb2060 deedb462a0 Hide magisk internal mount point 2023-12-22 21:38:15 +08:00
igor c48962bdf7
Update Portuguese translation 2023-12-22 01:31:55 +08:00
Wang Han 1ef3f6e13b Remove useless rule for prctl PR_SET_MM
* There is no use-case for it now.
2023-12-22 00:36:06 +08:00
topjohnwu 83a34a9004 Update emulator 2023-12-21 21:30:35 +08:00
topjohnwu e30bda6c8d Rebase libsepol to AOSP main 2023-12-21 19:23:02 +08:00
vvb2060 00e9d76a5a Revert "Avoid doing any unmounts for SysUI" 2023-12-20 17:23:17 +08:00
LoveSy 6cda6c2fae Upgrade github action deps 2023-12-18 16:25:56 +08:00
VD $ VD171 @ Priv8 6dfda6dc39
Update Portuguese Translation 2023-12-18 16:24:14 +08:00
LoveSy f41994cb52 Skip svc for ro properties
ro properties' triggers should only be triggered once, otherwise it
may undefined behaviour.
This patch avoids triggering ro properties' actions again when using
resetprop to modify them.

Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
2023-12-18 16:21:08 +08:00
topjohnwu a003336497 Update system_properties for pre Android 10 2023-12-18 16:21:08 +08:00
LoveSy 401090d6fe Avoid zygiskd restarts when boot-complete 2023-12-18 16:21:08 +08:00
LoveSy 90dcc1cd30 Do not always zero initialize for rust resize vec 2023-12-18 16:21:08 +08:00
LoveSy 2ac464b186 Only compress regular file 2023-12-18 16:21:08 +08:00
LoveSy 8b7fae278b Support compressing during cpio backup 2023-12-18 16:21:08 +08:00
topjohnwu d73c2daf6d Use special emulator to make tests less flaky 2023-12-16 15:50:53 +08:00
topjohnwu ca25935de3 Release new canary build 2023-12-14 03:21:22 +08:00
LoveSy d7750b7220 uiautomator dump to /data/local/tmp 2023-12-13 03:28:30 +08:00
LoveSy 98861f0b5a Clone dir attr for tmpfs in advance 2023-12-13 03:28:30 +08:00
topjohnwu e35925d520 Properly version zygisk APIs 2023-12-13 03:27:38 +08:00
Kieron Quinn 685a2d2101 Fixes for Android 14 QPR2 B2
Added new method signatures and arguments
2023-12-13 00:16:54 +08:00
LoveSy f7e471616d Fix clone_attr for newly created dirs 2023-12-10 23:37:47 +08:00
残页 c013a349af Update install guide
- Remove boot vbmeta patching because the checkbox is removed in b1363ee
- Remove meaningless slot argument from `fastboot flash` as it will automatically flash the active slot. Fix #7571
2023-12-10 23:37:02 +08:00
topjohnwu 61ea59a27b API 34 AOSP ATD image is released 2023-12-08 17:59:24 +08:00
VD $ VD171 @ Priv8 e55f338367 Update Portuguese Translation 2023-12-08 17:03:48 +08:00
VD $ VD171 @ Priv8 1425cf4105 Update Portuguese Translation 2023-12-08 17:03:48 +08:00
topjohnwu b493a985b0 Update dependencies 2023-12-08 17:03:18 +08:00
canyie 1fe9ede940 Update selinux to disable validation for policydb 2023-12-08 16:50:45 +08:00
LoveSy 1fd49e4987 Make tmpfs mount of magic mount atomic
This avoid system libraries disappear temporarily during magic mount,
which causes some dynamic executables fails to run during post-fs-data.
2023-12-08 13:59:02 +08:00
LoveSy d49b02b274 Fix zygiskd not restart when zygote restarts 2023-12-07 20:44:44 +08:00
LoveSy d47e70cfaa Fix native symbol strips
`ndkVersion` is also needed by app for striping native symbols.
Set it in `setupCommon` instead.
2023-12-04 00:37:09 +08:00
topjohnwu 40cb031af5 Release new canary build 2023-12-04 00:30:46 +08:00
topjohnwu 1dcf325547 Minor cleanup 2023-12-03 19:32:58 +08:00
LoveSy 4e99997013 Upgrade AGP 2023-12-02 15:25:58 +08:00
LoveSy 334554697d Enable rust parallel front-end
See https://blog.rust-lang.org/2023/11/09/parallel-rustc.html
2023-12-02 15:25:41 +08:00
LoveSy e77cbd0c15 Upgrade gradle 2023-11-30 11:49:40 +08:00
topjohnwu 46ba008b9d Disable SCCACHE_DIRECT 2023-11-30 01:55:38 +08:00
LoveSy 58aded31c2 Enable iter_intersperse 2023-11-29 23:47:51 +08:00
LoveSy 6f6b0ade06 Correct cpio's norm_path 2023-11-29 23:47:51 +08:00
topjohnwu d9b67a207b Update ONDK 2023-11-27 17:41:11 +08:00
topjohnwu c7083659aa Directly guard boot state with mutex 2023-11-27 17:40:58 +08:00
topjohnwu a6d1803105 Update dependencies 2023-11-26 23:09:20 +08:00
Re*Index. (ot_inc) 66eef75673 Update strings.xml 2023-11-26 22:54:53 +08:00
Alessandro Sangiorgi 367f5f7b44
Update italian translation
Co-authored-by: Francesco Saltori <francescosaltori@gmail.com>
2023-11-26 22:54:33 +08:00
topjohnwu 0edcb03c45 Update test API levels 2023-11-26 21:41:43 +08:00
canyie 63eef153de Warn about unsupported installation methods 2023-11-17 13:58:41 -08:00
canyie 68442f38ac Misc changes
- actions: Update all actions/checkout references to v4
- magiskboot: Add missing new line to dtb help message
- docs: Update documents, fix some errors and remove outdated info
2023-11-17 13:58:41 -08:00
topjohnwu 8d5b9e5329 C++/Rust 2 way binding for MagiskD 2023-11-17 13:35:50 -08:00
topjohnwu 6c0966b795 Move some global state into Rust 2023-11-16 15:38:38 -08:00
topjohnwu 7c2e93d266 Introduce owned_fd 2023-11-16 15:38:38 -08:00
topjohnwu 1ff7b9055f Add LSPosed launch test 2023-11-16 15:38:38 -08:00
topjohnwu 49f241b77c Allow running scripts with incomplete env 2023-11-10 00:55:05 -08:00
topjohnwu cfb20b0f86 Zygisk refactoring part 2 2023-11-09 20:55:58 -08:00
topjohnwu 6d6f14fcb3 Use bitflags 2023-11-09 14:35:49 -08:00
topjohnwu 977c981265 Make sure native bridge is restored on daemon restart 2023-11-08 17:55:25 -08:00
topjohnwu ef48abf19d Reorganize zygisk code 2023-11-08 17:46:39 -08:00
topjohnwu 65c18f9c09 Restructure project files 2023-11-08 01:46:02 -08:00
残页 ecb31eed40
Prevent Zygisk from closing new fds created by Zygote itself 2023-11-08 00:34:38 -08:00
topjohnwu a80cadf587 Refactor hookJniNativeMethods
Utilize NativeBridgeRuntimeCallbacks we obtained from native bridge
to directly fetch and modify registered native JNI methods.
By doing so, we do not need to keep a copy of every single
JNINativeMethod registered in order to provide JNI hooking
functionality.

Co-authored-by: LoveSy <shana@zju.edu.cn>
2023-11-07 23:57:55 -08:00
LoveSy fce1bf2365 Obtain NativeBridgeRuntimeCallbacks for future use
NativeBridgeRuntimeCallbacks can be used for better JNI method hooking

Co-authored-by: topjohnwu <topjohnwu@gmail.com>
2023-11-07 16:56:40 -08:00
LoveSy cbc6d40b2c Clean up codes 2023-11-07 14:25:57 -08:00
LoveSy 9fbd079560 Refactor zygisk to use native bridge to inject
Co-authored-by: vvb2060 <vvb2060@gmail.com>
Co-authored-by: topjohnwu <topjohnwu@gmail.com>
2023-11-07 14:25:57 -08:00
LoveSy 42eb928054 Inject zygisk.rc for sync `--zygisk-restart` 2023-11-06 15:39:48 -08:00
topjohnwu 577483fde1 Release new canary build 2023-11-05 23:49:35 -08:00
topjohnwu aa6c7c15cc Update README 2023-11-05 23:44:07 -08:00
topjohnwu 6c807d35b2 Release Magisk v26.4 2023-11-05 23:31:15 -08:00
topjohnwu 8ca8cdae97 Add v26.4 release notes 2023-11-05 23:07:53 -08:00
topjohnwu 75e37be6f3 Do not need to check pkg in magisk_env 2023-11-05 23:02:40 -08:00
WindowsFan9600 4985314ca6 Update language "tr" on main application 2023-11-05 22:37:39 -08:00
topjohnwu ac5ceb18c8 Guard log FIFO with SELinux 2023-11-04 23:59:11 -07:00
topjohnwu 72b39594d3 Always close logd_fd during fork 2023-11-04 02:36:14 -07:00
topjohnwu 16ae4aedf1 Remove usage of MAGISKTMP 2023-11-02 15:50:36 -07:00
topjohnwu 3ba00858e6 Allow avd_magisk on API 28 2023-11-01 09:15:17 -07:00
topjohnwu 489100c755 Fix fd sanitization 2023-11-01 02:01:29 -07:00
topjohnwu da766f2a4e Do not go through magiskd for getting the log pipe 2023-11-01 02:01:18 -07:00
topjohnwu c81d7ff76c Remove unnecessary RefCell usage 2023-10-31 18:22:48 -07:00
topjohnwu a6e50d3648 Make log pipe a FIFO instead of anonymous pipe 2023-10-31 18:05:22 -07:00
topjohnwu a177846044 Better logging in recv_fds 2023-10-31 17:40:59 -07:00
topjohnwu 19a4e11645 Make tmpfs path static strings 2023-10-29 00:47:28 -07:00
topjohnwu 67cc36268e Simplify zygisk log pipe 2023-10-26 18:13:56 -07:00
topjohnwu 28770b9a32 Support baseline profiles 2023-10-26 15:56:51 -07:00
WindowsFan9600 9f92e1bf15 [STRINGS] Improve Turkish (tr) language 2023-10-26 15:23:35 -07:00
topjohnwu 23fe5d5a19 Update build.yml 2023-10-26 14:50:42 -07:00
LoveSy 9088b584f6 Use official argh 2023-10-25 15:14:16 -07:00
vvb2060 beaf636415 Use ccache for C code 2023-10-25 15:05:41 -07:00
vvb2060 09bb2fe8dc Update dependencies 2023-10-25 14:58:02 -07:00
tzagim 1d6747d90e
Update Hebrew translation 2023-10-24 21:06:15 -07:00
南宫雪珊 efadd94de3 Update strings.xml 2023-10-24 21:02:32 -07:00
vvb2060 8c0b4e444a Update zh-rCN translation 2023-10-24 21:02:32 -07:00
Rom 32c7106e40 Update French translation 2023-10-24 21:01:53 -07:00
topjohnwu d2f2a9e4c8 Make avd_test less flaky 2023-10-24 16:45:24 -07:00
topjohnwu 985454afd4 Better logging 2023-10-24 16:41:49 -07:00
topjohnwu 9e1322de25 Make sure the shared preference is committed 2023-10-24 16:41:38 -07:00
topjohnwu 4e4ec73d94 Make gradle.properties optional 2023-10-19 15:44:34 -07:00
topjohnwu bb39a524d0 Switch to default images for faster boot time 2023-10-19 05:31:03 -07:00
topjohnwu 196d9af099 Add application and Zygisk tests to avd_test.sh 2023-10-19 05:15:53 -07:00
topjohnwu 1eeb2a34a1 Don't support alternative binary paths
The Magisk app will guide users through repair setup
2023-10-19 05:11:43 -07:00
Arbri çoçka cf43c56218 Update strings.xml sq 2023-10-18 14:29:55 -07:00
kubalav e6c1aec443 Update Slovak translation 2023-10-18 14:29:38 -07:00
topjohnwu 43fd1c4c1b Update stub version 2023-10-17 19:22:53 -07:00
topjohnwu 022caca979 Release new canary build 2023-10-17 19:13:16 -07:00
topjohnwu 0352ea2cca Rename biometrics to user authentication 2023-10-17 18:43:27 -07:00
topjohnwu e483d6befe Do not go through a fragment for auth 2023-10-17 17:39:31 -07:00
vvb2060 678c07fff5 suBiometric: remove biometric
use device credential to support more devices and second user
2023-10-17 17:39:05 -07:00
topjohnwu 91c92051f1 Simplify C++ SELinux routines 2023-10-17 16:04:59 -07:00
topjohnwu 4b8a0388e7 Make SELinux support a feature 2023-10-17 13:29:15 -07:00
topjohnwu 66788dc58c Cleanup SELinux support 2023-10-16 17:38:44 -07:00
topjohnwu dd8c28b1cb Upgrade AGP 2023-10-16 17:25:57 -07:00
残页 32c5153e8e Increase boot timeout to 600s 2023-10-16 01:20:25 -07:00
topjohnwu 36de62873a Fix error logging on the C++ side 2023-10-13 16:59:54 -07:00
topjohnwu 51e37880c6 Add repr(transparent) to guarantee soundness 2023-10-12 18:59:16 -07:00
topjohnwu 4b83c1e76c Cleanup messy error messages 2023-10-12 18:54:09 -07:00
topjohnwu b0b04690d5 Use newer bash version for avd_test.sh 2023-10-12 00:45:53 -07:00
topjohnwu 6d1e8d86cb Cleaner cstr code 2023-10-11 23:53:55 -07:00
topjohnwu eda8c70a80 Borrow value instead of moving in FsPath::from()
When accepting a value of AsRef<Utf8CStr> in FsPath::from(), the
existing code will move a value of Utf8CStrBufArr, creating a reference
that lives longer than the borrowing value, causing undefined behavior.

The issue is only visible on release builds, as more advanced
optimizations will be more aggressive re-using the stack of variables
that no longer lives.

Fix #7408
2023-10-11 23:48:54 -07:00
topjohnwu 587b6cfd41 Update avd_test.sh 2023-10-11 22:42:45 -07:00
topjohnwu e774408782 Allow AVD hacks on release builds 2023-10-11 14:17:31 -07:00
canyie 187f583c95 Fix $RECOVERYMODE from config being incorrectly overridden
Move legacy SAR checking logic into mount_partitions, and avoid calling get_flags before check_boot_ramdisk
Fix #7346
2023-10-10 15:53:18 -07:00
topjohnwu f5d3a71478 Update ONDK to r26.1 2023-10-10 15:52:59 -07:00
残页 d868ff3080 AVD test release builds as well 2023-10-10 15:52:41 -07:00
nkh0472 f80198a669
typo fix 2023-10-09 17:22:48 -07:00
topjohnwu 6076b52c48 Update libcxx 2023-10-03 17:22:25 -07:00
topjohnwu 79a1c39b30 Simplify fd sanitization 2023-09-28 20:38:16 -07:00
topjohnwu 5c92d39498 Enable Zygisk by default in emulators
Make sure CI tests Zygisk
2023-09-28 20:25:26 -07:00
topjohnwu 6e7a995716 Introduce UtfCString 2023-09-27 15:21:24 -07:00
topjohnwu a55d570213 Move more I/O operations into Rust 2023-09-27 02:28:43 -07:00
topjohnwu 5d07d0b964 Do not support systems without SELinux 2023-09-27 02:28:43 -07:00
Wang Han ec115cd7e3 Don't skip fd sanitization if fds_to_ignore does not exist 2023-09-25 09:45:03 -07:00
osm0sis 9b3896fd3d Retain PREINITDEVICE during A-only addon.d 2023-09-23 23:51:36 -07:00
topjohnwu a3f5918d25 Fix bug in libsepol
Fix #7308
2023-09-23 22:34:51 -07:00
topjohnwu b28326198c Use crates for cpio code 2023-09-22 01:39:21 -07:00
topjohnwu 46275b90c2 Generalize unxz 2023-09-21 05:47:21 -07:00
topjohnwu 15e13a8d8b Organize logging code 2023-09-19 03:02:30 -07:00
topjohnwu b750c89c87 Address clippy warnings 2023-09-19 01:11:50 -07:00
LoveSy 8d7c7c3dfb Refactor dtb in rust 2023-09-19 00:41:42 -07:00
topjohnwu 8e1a91509c Remove readlink_unsafe 2023-09-19 00:06:21 -07:00
LoveSy 927cd571f8 Fix `read_cert` crash when receive fd = -1 2023-09-18 22:32:32 -07:00
LoveSy 5fbd3e5c65 Fix buf len update of read_link to Utf8CStrBuf 2023-09-18 22:31:12 -07:00
LoveSy 877aeb66cb Upgrade to Gradle 8.3 2023-09-14 13:16:59 -07:00
topjohnwu 8a88d8465a Prevent OOM
Fix #7341
2023-09-14 13:14:30 -07:00
topjohnwu dda8cc85c9 Use bytemuck 2023-09-14 13:10:09 -07:00
topjohnwu 6a59939d9a Remove for_all_file 2023-09-13 18:09:16 -07:00
topjohnwu 4745e86c1b Fix #7301 2023-09-13 14:44:20 -07:00
topjohnwu 9aa466c773 Fix genfscon and filename_trans
Fix #7329
2023-09-12 21:31:31 -07:00
LoveSy 0243610c09 No trailing zeros if the signed boot img is larger 2023-09-12 18:09:20 -07:00
topjohnwu 0a2a590ab7 Use Utf8CStr for logging 2023-09-12 17:35:20 -07:00
topjohnwu 89aee6ffa7 Add more to the Utf8CStr family
Better C strings with path operations
2023-09-12 17:35:01 -07:00
topjohnwu 4eaf701cb7 Address clippy warnings 2023-09-06 21:45:12 -07:00
topjohnwu 4fff2aa7d8 Fix proto read and write 2023-09-06 20:45:59 -07:00
topjohnwu 35b3c8ba5c Cleanup persist props code 2023-09-06 15:52:14 -07:00
topjohnwu 1d7cff7703 Update Cargo dependencies 2023-09-06 13:57:43 -07:00
LoveSy 8d81bd0e33 resetprop: replace nanopb with quick-protobuf for persist 2023-09-05 22:20:57 -07:00
topjohnwu 7826d7527f Release new canary build 2023-09-04 00:35:17 -07:00
topjohnwu d4e552d08b Update README 2023-09-04 00:26:48 -07:00
topjohnwu 5a16418543 Release Magisk v26.3 2023-09-04 00:01:46 -07:00
topjohnwu 7297aba15a Add v26.3 release notes 2023-09-03 23:54:45 -07:00
Ylarod bc5d5f9502 Update details.md
The `MAGISKTMP` changed to `/debug_ramdisk` since https://github.com/topjohnwu/Magisk/pull/6931
2023-09-03 23:46:25 -07:00
vvb2060 1761986c1b Update zh-rCN translation 2023-09-03 23:43:07 -07:00
topjohnwu 1e034e3e0e Update libsu 2023-09-03 23:41:17 -07:00
topjohnwu bbf9756bfa Release new canary build 2023-09-02 06:20:10 -07:00
topjohnwu 96e559fb0e Skip cargo build if possible 2023-09-02 06:03:39 -07:00
topjohnwu 4c45775131 Update BusyBox 2023-09-02 05:45:18 -07:00
LoveSy c072b4254d Wrap rename and renameat 2023-09-02 04:24:24 -07:00
topjohnwu 2dbb812126 Disable stack protector on x86 static executables
Close #7274
2023-09-01 23:04:19 -07:00
topjohnwu be50f17f55 Update to ONDK r26.0
Close #7264
2023-09-01 23:01:49 -07:00
残页 6f77f190f2 Fix processPayload 2023-08-31 20:30:10 -07:00
topjohnwu 6bdc57cbe4 Release new canary build 2023-08-30 01:22:02 -07:00
残页 de00f1d5a9 Always check mounts to detect legacy SAR on bootmode 2023-08-30 01:02:19 -07:00
残页 e9b9bf987b Fix syntax error in util_functions.sh 2023-08-29 15:33:03 -07:00
topjohnwu f4b6385f9f Disable boot vbmeta patch when found vbmeta.img 2023-08-28 22:54:55 -07:00
topjohnwu 75d905a56d Fix device detection scripts and logic 2023-08-28 22:13:36 -07:00
topjohnwu b1363ee479 Do not allow user to configure boot vbmeta patching 2023-08-28 22:13:36 -07:00
topjohnwu 51afe43a30 Cleanup util_functions 2023-08-28 22:13:36 -07:00
残页 189c03c047 Add canyie to developer list 2023-08-28 13:21:58 -07:00
topjohnwu ae9d270a32 Release new canary build 2023-08-28 01:25:07 -07:00
topjohnwu e47e869f6b Update full changelog 2023-08-28 01:15:14 -07:00
topjohnwu c39038a439 Update README 2023-08-28 01:13:25 -07:00
308 changed files with 10515 additions and 8958 deletions

44
.github/actions/setup/action.yml vendored Normal file
View File

@ -0,0 +1,44 @@
name: Magisk Setup
runs:
using: "composite"
steps:
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Set up sccache
uses: hendrikmuhs/ccache-action@v1.2
with:
variant: sccache
key: ${{ runner.os }}-${{ github.sha }}
restore-keys: ${{ runner.os }}
max-size: 10000M
- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Cache build cache
uses: actions/cache@v4
with:
path: |
~/.gradle/caches/build-cache-*
key: ${{ runner.os }}-build-cache-${{ github.sha }}
restore-keys: ${{ runner.os }}-build-cache-
- name: Set up NDK
run: python build.py -v ndk
shell: bash

View File

@ -17,118 +17,138 @@ on:
jobs:
build:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
name: Build Magisk artifacts
runs-on: ubuntu-latest
env:
SCCACHE_DIRECT: false
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Check out
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "17"
- name: Set up Python 3
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Set up sccache
uses: hendrikmuhs/ccache-action@v1.2
with:
variant: sccache
key: ${{ runner.os }}-${{ github.sha }}
restore-keys: ${{ runner.os }}
max-size: 10000M
- name: Cache Gradle dependencies
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Cache build cache
uses: actions/cache@v3
with:
path: |
~/.gradle/caches/build-cache-*
key: ${{ runner.os }}-build-cache-${{ github.sha }}
restore-keys: ${{ runner.os }}-build-cache-
- name: Set up NDK
run: python build.py -v ndk
- name: Setup environment
uses: ./.github/actions/setup
- name: Build release
run: |
python build.py -vr all
run: ./build.py -vr all
- name: Build debug
run: |
python build.py -v all
run: ./build.py -v all
- name: Stop gradle daemon
run: ./gradlew --stop
# Only upload artifacts built on Linux
- name: Upload build artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ github.sha }}
path: out
compression-level: 9
- name: Upload mapping and native debug symbols
if: runner.os == 'Linux'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ github.sha }}-symbols
path: app/build/outputs
compression-level: 9
test-build:
name: Test building on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
SCCACHE_DIRECT: false
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-14]
steps:
- name: Check out
uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0
- name: Setup environment
uses: ./.github/actions/setup
- name: Build debug
run: python build.py -v all
- name: Stop gradle daemon
run: ./gradlew --stop
test:
name: Test on ${{ matrix.api }}
runs-on: macos-latest
name: Test x86_64 on API ${{ matrix.api }}
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
api: [23, 26, 28, 29, 34]
api: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
steps:
- name: Check out
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "17"
- name: Set up Python 3
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Download build artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ github.sha }}
path: out
- name: AVD test
- name: Enable KVM group perms
run: |
brew install coreutils
scripts/avd_test.sh ${{ matrix.api }}
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD test
run: scripts/avd_test.sh ${{ matrix.api }}
test-32:
name: Test x86 on API ${{ matrix.api }}
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
api: [23, 24, 25, 26, 27, 28, 29, 30]
steps:
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: ${{ github.sha }}
path: out
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD test
env:
FORCE_32_BIT: 1
run: scripts/avd_test.sh ${{ matrix.api }}

12
.gitmodules vendored
View File

@ -4,9 +4,6 @@
[submodule "busybox"]
path = native/src/external/busybox
url = https://github.com/topjohnwu/ndk-busybox.git
[submodule "dtc"]
path = native/src/external/dtc
url = https://github.com/dgibson/dtc.git
[submodule "lz4"]
path = native/src/external/lz4
url = https://github.com/lz4/lz4.git
@ -16,9 +13,6 @@
[submodule "xz"]
path = native/src/external/xz
url = https://github.com/xz-mirror/xz.git
[submodule "nanopb"]
path = native/src/external/nanopb
url = https://github.com/nanopb/nanopb.git
[submodule "pcre"]
path = native/src/external/pcre
url = https://android.googlesource.com/platform/external/pcre
@ -28,9 +22,6 @@
[submodule "zlib"]
path = native/src/external/zlib
url = https://android.googlesource.com/platform/external/zlib
[submodule "parallel-hashmap"]
path = native/src/external/parallel-hashmap
url = https://github.com/greg7mdp/parallel-hashmap.git
[submodule "zopfli"]
path = native/src/external/zopfli
url = https://github.com/google/zopfli.git
@ -43,6 +34,9 @@
[submodule "system_properties"]
path = native/src/external/system_properties
url = https://github.com/topjohnwu/system_properties.git
[submodule "crt0"]
path = native/src/external/crt0
url = https://github.com/topjohnwu/crt0.git
[submodule "termux-elf-cleaner"]
path = tools/termux-elf-cleaner
url = https://github.com/termux/termux-elf-cleaner.git

View File

@ -18,8 +18,8 @@ Some highlight features:
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
[![](https://img.shields.io/badge/Magisk-v26.1-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v26.1)
[![](https://img.shields.io/badge/Magisk%20Beta-v26.1-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v26.1)
[![](https://img.shields.io/badge/Magisk-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
[![](https://img.shields.io/badge/Magisk%20Beta-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
[![](https://img.shields.io/badge/Magisk-Canary-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-release.apk)
[![](https://img.shields.io/badge/Magisk-Debug-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)

View File

@ -70,17 +70,17 @@ configurations.all {
dependencies {
implementation(project(":app:shared"))
implementation("com.github.topjohnwu:jtar:1.0.0")
implementation("com.github.topjohnwu:jtar:1.1.0")
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
implementation("com.github.topjohnwu:lz4-java:1.7.1")
implementation("com.jakewharton.timber:timber:5.0.1")
implementation("org.bouncycastle:bcpkix-jdk18on:1.76")
implementation("org.bouncycastle:bcpkix-jdk18on:1.77")
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0")
implementation("dev.rikka.rikkax.insets:insets:1.3.0")
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.2")
implementation("io.noties.markwon:core:4.6.2")
val vLibsu = "5.2.0"
val vLibsu = "5.2.2"
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
implementation("com.github.topjohnwu.libsu:service:${vLibsu}")
implementation("com.github.topjohnwu.libsu:nio:${vLibsu}")
@ -90,7 +90,7 @@ dependencies {
implementation("com.squareup.retrofit2:converter-moshi:${vRetrofit}")
implementation("com.squareup.retrofit2:converter-scalars:${vRetrofit}")
val vOkHttp = "4.11.0"
val vOkHttp = "4.12.0"
implementation("com.squareup.okhttp3:okhttp:${vOkHttp}")
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}")
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
@ -99,23 +99,23 @@ dependencies {
implementation("com.squareup.moshi:moshi:${vMoshi}")
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
val vRoom = "2.6.0-beta01"
val vRoom = "2.6.1"
implementation("androidx.room:room-runtime:${vRoom}")
implementation("androidx.room:room-ktx:${vRoom}")
kapt("androidx.room:room-compiler:${vRoom}")
val vNav = "2.7.1"
val vNav = "2.7.7"
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
implementation("androidx.biometric:biometric:1.1.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.recyclerview:recyclerview:1.3.1")
implementation("androidx.fragment:fragment-ktx:1.6.1")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.fragment:fragment-ktx:1.6.2")
implementation("androidx.transition:transition:1.4.1")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
implementation("com.google.android.material:material:1.11.0")
}

View File

@ -4,12 +4,14 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RUN_USER_INITIATED_JOBS" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE"
android:maxSdkVersion="33" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />

View File

@ -67,8 +67,6 @@ public final class APKInstall {
public interface Session {
// @WorkerThread
OutputStream openStream(Context context) throws IOException;
// @WorkerThread
void install(Context context, File apk) throws IOException;
// @WorkerThread @Nullable
Intent waitIntent();
}
@ -167,13 +165,5 @@ public final class APKInstall {
}
};
}
@Override
public void install(Context context, File apk) throws IOException {
try (var src = new FileInputStream(apk);
var out = openStream(context)) {
transfer(src, out);
}
}
}
}

View File

@ -61,8 +61,9 @@
</receiver>
<service
android:name=".core.download.DownloadService"
android:name=".core.Service"
android:exported="false"
android:enabled="@bool/enable_fg_service"
android:foregroundServiceType="dataSync" />
<service
@ -82,11 +83,15 @@
android:name="androidx.room.MultiInstanceInvalidationService"
tools:node="remove" />
<!-- We don't need emoji compat -->
<!-- We handle initialization ourselves -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="remove" />
<!-- We handle profile installation ourselves -->
<receiver
android:name="androidx.profileinstaller.ProfileInstallReceiver"
tools:node="remove" />
</application>

View File

@ -1,6 +1,8 @@
package com.topjohnwu.magisk.arch
import android.Manifest.permission.*
import android.Manifest.permission.POST_NOTIFICATIONS
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.annotation.SuppressLint
import android.os.Bundle
import androidx.databinding.PropertyChangeRegistry

View File

@ -5,9 +5,13 @@ import android.app.Application
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.system.Os
import androidx.profileinstaller.ProfileInstaller
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.utils.DispatcherExecutor
import com.topjohnwu.magisk.core.utils.NetworkObserver
import com.topjohnwu.magisk.core.utils.ProcessLifecycle
import com.topjohnwu.magisk.core.utils.RootUtils
import com.topjohnwu.magisk.core.utils.ShellInit
@ -19,6 +23,8 @@ import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.UiThreadHandler
import com.topjohnwu.superuser.ipc.RootService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import timber.log.Timber
import java.lang.ref.WeakReference
import kotlin.system.exitProcess
@ -41,6 +47,8 @@ open class App() : Application() {
Timber.e(e)
exitProcess(1)
}
Os.setenv("PATH", "${Os.getenv("PATH")}:/debug_ramdisk:/sbin", true)
}
override fun attachBaseContext(context: Context) {
@ -82,6 +90,12 @@ open class App() : Application() {
override fun onCreate() {
super.onCreate()
ProcessLifecycle.init(this)
NetworkObserver.init(this)
if (!BuildConfig.DEBUG && !isRunningAsStub) {
GlobalScope.launch(Dispatchers.IO) {
ProfileInstaller.writeProfile(this@App)
}
}
}
override fun onConfigurationChanged(newConfig: Configuration) {

View File

@ -12,8 +12,11 @@ import com.topjohnwu.magisk.core.repository.DBConfig
import com.topjohnwu.magisk.core.repository.PreferenceConfig
import com.topjohnwu.magisk.core.utils.refreshLocale
import com.topjohnwu.magisk.ui.theme.Theme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
import java.io.File
import java.io.IOException
object Config : PreferenceConfig, DBConfig {
@ -37,6 +40,7 @@ object Config : PreferenceConfig, DBConfig {
const val SU_MNT_NS = "mnt_ns"
const val SU_BIOMETRIC = "su_biometric"
const val ZYGISK = "zygisk"
const val BOOTLOOP = "bootloop"
const val DENYLIST = "denylist"
const val SU_MANAGER = "requester"
const val KEYSTORE = "keystore"
@ -114,7 +118,6 @@ object Config : PreferenceConfig, DBConfig {
@JvmField var keepVerity = false
@JvmField var keepEnc = false
@JvmField var patchVbmeta = false
@JvmField var recovery = false
var bootId by preference(Key.BOOT_ID, "")
@ -157,8 +160,14 @@ object Config : PreferenceConfig, DBConfig {
var rootMode by dbSettings(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB)
var suMntNamespaceMode by dbSettings(Key.SU_MNT_NS, Value.NAMESPACE_MODE_REQUESTER)
var suMultiuserMode by dbSettings(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY)
var suBiometric by dbSettings(Key.SU_BIOMETRIC, false)
private var suBiometric by dbSettings(Key.SU_BIOMETRIC, false)
var userAuth
get() = Info.isDeviceSecure && suBiometric
set(value) {
suBiometric = value
}
var zygisk by dbSettings(Key.ZYGISK, false)
var bootloop by dbSettings(Key.BOOTLOOP, 0)
var denyList by BoolDBPropertyNoWrite(Key.DENYLIST, false)
var suManager by dbStrings(Key.SU_MANAGER, "", true)
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
@ -167,8 +176,14 @@ object Config : PreferenceConfig, DBConfig {
fun load(pkg: String?) {
// Only try to load prefs when fresh install and a previous package name is set
if (pkg != null && prefs.all.isEmpty()) runCatching {
context.contentResolver.openInputStream(Provider.preferencesUri(pkg))?.writeTo(prefsFile)
if (pkg != null && prefs.all.isEmpty()) {
runBlocking {
try {
context.contentResolver
.openInputStream(Provider.preferencesUri(pkg))
?.writeTo(prefsFile, dispatcher = Dispatchers.Unconfined)
} catch (ignored: IOException) {}
}
return
}

View File

@ -35,7 +35,8 @@ object Const {
}
object ID {
const val JOB_SERVICE_ID = 7
const val DOWNLOAD_JOB_ID = 6
const val CHECK_UPDATE_JOB_ID = 7
}
object Url {

View File

@ -1,14 +1,12 @@
package com.topjohnwu.magisk.core
import android.os.Build
import androidx.lifecycle.LiveData
import android.app.KeyguardManager
import androidx.lifecycle.MutableLiveData
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.ktx.getProperty
import com.topjohnwu.magisk.core.model.UpdateInfo
import com.topjohnwu.magisk.core.repository.NetworkService
import com.topjohnwu.magisk.core.utils.NetworkObserver
import com.topjohnwu.superuser.ShellUtils.fastCmd
val isRunningAsStub get() = Info.stub != null
@ -33,31 +31,26 @@ object Info {
@JvmField val isZygiskEnabled = System.getenv("ZYGISK_ENABLED") == "1"
@JvmStatic val isFDE get() = crypto == "block"
@JvmField var ramdisk = false
@JvmField var vbmeta = false
var patchBootVbmeta = false
var crypto = ""
var noDataExec = false
var isRooted = false
@JvmField var hasGMS = true
val isSamsung = Build.MANUFACTURER.equals("samsung", ignoreCase = true)
@JvmField val isEmulator =
getProperty("ro.kernel.qemu", "0") == "1" ||
getProperty("ro.boot.qemu", "0") == "1"
val isConnected: LiveData<Boolean> by lazy {
MutableLiveData(false).also { field ->
NetworkObserver.observe(AppContext) {
remote = EMPTY_REMOTE
field.postValue(it)
}
}
}
val isConnected = MutableLiveData(false)
val showSuperUser: Boolean get() {
return env.isActive && (Const.USER_ID == 0
|| Config.suMultiuserMode == Config.Value.MULTIUSER_MODE_USER)
}
val isDeviceSecure get() =
AppContext.getSystemService(KeyguardManager::class.java).isDeviceSecure
private fun loadState(): Env {
val v = fastCmd("magisk -v").split(":".toRegex())
return Env(

View File

@ -1,5 +1,8 @@
package com.topjohnwu.magisk.core
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Notification
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
@ -8,38 +11,78 @@ import androidx.core.content.getSystemService
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.core.base.BaseJobService
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.view.Notifications
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit
class JobService : BaseJobService() {
private val job = Job()
private val svc get() = ServiceLocator.networkService
private var mSession: Session? = null
override fun onStartJob(params: JobParameters): Boolean {
val coroutineScope = CoroutineScope(Dispatchers.IO + job)
coroutineScope.launch {
doWork()
@TargetApi(value = 34)
inner class Session(
private var params: JobParameters
) : DownloadEngine.Session {
override val context get() = this@JobService
val engine = DownloadEngine(this)
fun updateParams(params: JobParameters) {
this.params = params
engine.reattach()
}
override fun attachNotification(id: Int, builder: Notification.Builder) {
setNotification(params, id, builder.build(), JOB_END_NOTIFICATION_POLICY_REMOVE)
}
override fun onDownloadComplete() {
jobFinished(params, false)
}
return false
}
private suspend fun doWork() {
svc.fetchUpdate()?.let {
Info.remote = it
if (Info.env.isActive && BuildConfig.VERSION_CODE < it.magisk.versionCode)
Notifications.updateAvailable()
@SuppressLint("NewApi")
override fun onStartJob(params: JobParameters): Boolean {
return when (params.jobId) {
Const.ID.CHECK_UPDATE_JOB_ID -> checkUpdate(params)
Const.ID.DOWNLOAD_JOB_ID -> downloadFile(params)
else -> false
}
}
override fun onStopJob(params: JobParameters): Boolean {
job.cancel()
return false
override fun onStopJob(params: JobParameters?) = false
@TargetApi(value = 34)
private fun downloadFile(params: JobParameters): Boolean {
params.transientExtras.classLoader = Subject::class.java.classLoader
val subject = params.transientExtras
.getParcelable(DownloadEngine.SUBJECT_KEY, Subject::class.java) ?:
return false
val session = mSession?.also {
it.updateParams(params)
} ?: run {
Session(params).also { mSession = it }
}
session.engine.download(subject)
return true
}
private fun checkUpdate(params: JobParameters): Boolean {
GlobalScope.launch(Dispatchers.IO) {
ServiceLocator.networkService.fetchUpdate()?.let {
Info.remote = it
if (Info.env.isActive && BuildConfig.VERSION_CODE < it.magisk.versionCode)
Notifications.updateAvailable()
jobFinished(params, false)
}
}
return true
}
companion object {
@ -47,14 +90,14 @@ class JobService : BaseJobService() {
val scheduler = context.getSystemService<JobScheduler>() ?: return
if (Config.checkUpdate) {
val cmp = JobService::class.java.cmp(context.packageName)
val info = JobInfo.Builder(Const.ID.JOB_SERVICE_ID, cmp)
val info = JobInfo.Builder(Const.ID.CHECK_UPDATE_JOB_ID, cmp)
.setPeriodic(TimeUnit.HOURS.toMillis(12))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setRequiresDeviceIdle(true)
.build()
scheduler.schedule(info)
} else {
scheduler.cancel(Const.ID.JOB_SERVICE_ID)
scheduler.cancel(Const.ID.CHECK_UPDATE_JOB_ID)
}
}
}

View File

@ -6,12 +6,18 @@ import android.os.ParcelFileDescriptor
import android.os.ParcelFileDescriptor.MODE_READ_ONLY
import com.topjohnwu.magisk.core.base.BaseProvider
import com.topjohnwu.magisk.core.su.SuCallbackHandler
import com.topjohnwu.magisk.core.su.TestHandler
class Provider : BaseProvider() {
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
SuCallbackHandler.run(context!!, method, extras)
return Bundle.EMPTY
return when (method) {
SuCallbackHandler.LOG, SuCallbackHandler.NOTIFY -> {
SuCallbackHandler.run(context!!, method, extras)
Bundle.EMPTY
}
else -> TestHandler.run(method)
}
}
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {

View File

@ -3,8 +3,11 @@ package com.topjohnwu.magisk.core
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import androidx.core.content.IntentCompat
import com.topjohnwu.magisk.core.base.BaseReceiver
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
@ -35,6 +38,12 @@ open class Receiver : BaseReceiver() {
}
when (intent.action ?: return) {
DownloadEngine.ACTION -> {
IntentCompat.getParcelableExtra(
intent, DownloadEngine.SUBJECT_KEY, Subject::class.java)?.let {
DownloadEngine.start(context, it)
}
}
Intent.ACTION_PACKAGE_REPLACED -> {
// This will only work pre-O
if (Config.suReAuth)

View File

@ -0,0 +1,38 @@
package com.topjohnwu.magisk.core
import android.app.Notification
import android.content.Intent
import android.os.Build
import androidx.core.app.ServiceCompat
import androidx.core.content.IntentCompat
import com.topjohnwu.magisk.core.base.BaseService
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
class Service : BaseService(), DownloadEngine.Session {
private var mEngine: DownloadEngine? = null
override val context get() = this
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
if (intent.action == DownloadEngine.ACTION) {
IntentCompat
.getParcelableExtra(intent, DownloadEngine.SUBJECT_KEY, Subject::class.java)
?.let { subject ->
val engine = mEngine ?: DownloadEngine(this).also { mEngine = it }
engine.download(subject)
}
}
return START_NOT_STICKY
}
override fun attachNotification(id: Int, builder: Notification.Builder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
builder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
startForeground(id, builder.build())
}
override fun onDownloadComplete() {
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
}
}

View File

@ -20,6 +20,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.reflectField
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.utils.RequestAuthentication
import com.topjohnwu.magisk.core.utils.RequestInstall
import com.topjohnwu.magisk.core.wrap
@ -43,6 +44,12 @@ abstract class BaseActivity : AppCompatActivity() {
installCallback = null
}
var authenticateCallback: ((Boolean) -> Unit)? = null
val requestAuthenticate = registerForActivityResult(RequestAuthentication()) {
authenticateCallback?.invoke(it)
authenticateCallback = null
}
private var contentCallback: ContentResultCallback? = null
private val getContent = registerForActivityResult(GetContent()) {
if (it != null) contentCallback?.onActivityResult(it)

View File

@ -4,7 +4,11 @@ import com.topjohnwu.magisk.core.model.BranchInfo
import com.topjohnwu.magisk.core.model.ModuleJson
import com.topjohnwu.magisk.core.model.UpdateInfo
import okhttp3.ResponseBody
import retrofit2.http.*
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Path
import retrofit2.http.Streaming
import retrofit2.http.Url
private const val BRANCH = "branch"
private const val REPO = "repo"

View File

@ -1,12 +1,16 @@
package com.topjohnwu.magisk.core.data
import androidx.room.*
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Insert
import androidx.room.Query
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.topjohnwu.magisk.core.model.su.SuLog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.*
import java.util.Calendar
@Database(version = 2, entities = [SuLog::class], exportSchema = false)
abstract class SuLogDatabase : RoomDatabase() {

View File

@ -12,7 +12,6 @@ import com.topjohnwu.magisk.core.data.magiskdb.StringDao
import com.topjohnwu.magisk.core.ktx.deviceProtectedContext
import com.topjohnwu.magisk.core.repository.LogRepository
import com.topjohnwu.magisk.core.repository.NetworkService
import com.topjohnwu.magisk.core.utils.BiometricHelper
import io.noties.markwon.Markwon
import io.noties.markwon.utils.NoCopySpannableFactory
@ -24,7 +23,6 @@ object ServiceLocator {
lateinit var context: Context
val deContext by lazy { context.deviceProtectedContext }
val timeoutPrefs by lazy { deContext.getSharedPreferences("su_timeout", 0) }
val biometrics by lazy { BiometricHelper(context) }
// Database
val policyDB = PolicyDao()

View File

@ -0,0 +1,373 @@
package com.topjohnwu.magisk.core.download
import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.PendingIntent
import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Bundle
import androidx.collection.SparseArrayCompat
import androidx.collection.isNotEmpty
import androidx.core.content.getSystemService
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.ActivityTracker
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.cmp
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.intent
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.cachedFile
import com.topjohnwu.magisk.core.ktx.copyAll
import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.forEach
import com.topjohnwu.magisk.core.ktx.set
import com.topjohnwu.magisk.core.ktx.withStreams
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.core.utils.ProgressInputStream
import com.topjohnwu.magisk.utils.APKInstall
import com.topjohnwu.magisk.view.Notifications
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import okhttp3.ResponseBody
import timber.log.Timber
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
/**
* This class drives the execution of file downloads and notification management.
*
* Each download engine instance has to be paired with a "session" that is managed by the operating
* system. A session is an Android component that allows executing long lasting operations and
* have its state tied to a notification to show progress.
*
* A session can only have one single notification representing its state, and the operating system
* also uses the notification to manage the lifecycle of a session. One goal of this class is
* to support concurrent download tasks using only one single session, so internally it manages
* all active tasks and notifications and properly re-assign notifications to be attached to
* the session to make sure all download operations can be completed without the operating system
* killing the session.
*
* For API 23 - 33, we use a foreground service as a session.
* For API 34 and higher, we use user-initiated job services as a session.
*/
class DownloadEngine(
private val session: Session
) {
interface Session {
val context: Context
fun attachNotification(id: Int, builder: Notification.Builder)
fun onDownloadComplete()
}
companion object {
const val ACTION = "com.topjohnwu.magisk.DOWNLOAD"
const val SUBJECT_KEY = "subject"
private const val REQUEST_CODE = 1
private val progressBroadcast = MutableLiveData<Pair<Float, Subject>?>()
private fun broadcast(progress: Float, subject: Subject) {
progressBroadcast.postValue(progress to subject)
}
fun observeProgress(owner: LifecycleOwner, callback: (Float, Subject) -> Unit) {
progressBroadcast.value = null
progressBroadcast.observe(owner) {
val (progress, subject) = it ?: return@observe
callback(progress, subject)
}
}
private fun createIntent(context: Context, subject: Subject) =
if (Build.VERSION.SDK_INT >= 34) {
context.intent<com.topjohnwu.magisk.core.Receiver>()
.setAction(ACTION)
.putExtra(SUBJECT_KEY, subject)
} else {
context.intent<com.topjohnwu.magisk.core.Service>()
.setAction(ACTION)
.putExtra(SUBJECT_KEY, subject)
}
@SuppressLint("InlinedApi")
fun getPendingIntent(context: Context, subject: Subject): PendingIntent {
val flag = PendingIntent.FLAG_IMMUTABLE or
PendingIntent.FLAG_UPDATE_CURRENT or
PendingIntent.FLAG_ONE_SHOT
val intent = createIntent(context, subject)
return if (Build.VERSION.SDK_INT >= 34) {
// On API 34+, download tasks are handled with a user-initiated job.
// However, there is no way to schedule a new job directly with a pending intent.
// As a workaround, we send the subject to a broadcast receiver and have it
// schedule the job for us.
PendingIntent.getBroadcast(context, REQUEST_CODE, intent, flag)
} else if (Build.VERSION.SDK_INT >= 26) {
PendingIntent.getForegroundService(context, REQUEST_CODE, intent, flag)
} else {
PendingIntent.getService(context, REQUEST_CODE, intent, flag)
}
}
@SuppressLint("InlinedApi")
fun startWithActivity(activity: BaseActivity, subject: Subject) {
activity.withPermission(Manifest.permission.POST_NOTIFICATIONS) {
// Always download regardless of notification permission status
start(activity.applicationContext, subject)
}
}
fun start(context: Context, subject: Subject) {
if (Build.VERSION.SDK_INT >= 34) {
val scheduler = context.getSystemService<JobScheduler>()!!
val cmp = JobService::class.java.cmp(context.packageName)
val extras = Bundle()
extras.putParcelable(SUBJECT_KEY, subject)
val info = JobInfo.Builder(Const.ID.DOWNLOAD_JOB_ID, cmp)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setUserInitiated(true)
.setTransientExtras(extras)
.build()
scheduler.schedule(info)
} else if (Build.VERSION.SDK_INT >= 26) {
context.startForegroundService(createIntent(context, subject))
} else {
context.startService(createIntent(context, subject))
}
}
}
fun download(subject: Subject) {
notifyUpdate(subject.notifyId)
CoroutineScope(job + Dispatchers.IO).launch {
try {
val stream = network.fetchFile(subject.url).toProgressStream(subject)
when (subject) {
is Subject.App -> handleApp(stream, subject)
is Subject.Module -> handleModule(stream, subject.file)
else -> stream.copyAndClose(subject.file.outputStream())
}
val activity = ActivityTracker.foreground
if (activity != null && subject.autoLaunch) {
notifyRemove(subject.notifyId)
subject.pendingIntent(activity)?.send()
} else {
notifyFinish(subject)
}
} catch (e: IOException) {
Timber.e(e)
notifyFail(subject)
}
}
}
@Synchronized
fun reattach() {
val builder = notifications[attachedId] ?: return
session.attachNotification(attachedId, builder)
}
private val notifications = SparseArrayCompat<Notification.Builder>()
private var attachedId = -1
private val job = Job()
private val context get() = session.context
private val network get() = ServiceLocator.networkService
private fun finalNotify(id: Int, editor: (Notification.Builder) -> Unit): Int {
val notification = notifyRemove(id)?.also(editor) ?: return -1
val newId = Notifications.nextId()
Notifications.mgr.notify(newId, notification.build())
return newId
}
private fun notifyFail(subject: Subject) = finalNotify(subject.notifyId) {
broadcast(-2f, subject)
it.setContentText(context.getString(R.string.download_file_error))
.setSmallIcon(android.R.drawable.stat_notify_error)
.setOngoing(false)
}
private fun notifyFinish(subject: Subject) = finalNotify(subject.notifyId) {
broadcast(1f, subject)
it.setContentTitle(subject.title)
.setContentText(context.getString(R.string.download_complete))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setProgress(0, 0, false)
.setOngoing(false)
.setAutoCancel(true)
subject.pendingIntent(context)?.let { intent -> it.setContentIntent(intent) }
}
private fun attachNotification(id: Int, notification: Notification.Builder) {
attachedId = id
session.attachNotification(id, notification)
}
@Synchronized
private fun notifyUpdate(id: Int, editor: (Notification.Builder) -> Unit = {}) {
val notification = (notifications[id] ?: Notifications.startProgress("").also {
notifications[id] = it
}).apply(editor)
if (attachedId < 0)
attachNotification(id, notification)
else
Notifications.mgr.notify(id, notification.build())
}
@Synchronized
private fun notifyRemove(id: Int): Notification.Builder? {
val idx = notifications.indexOfKey(id)
var n: Notification.Builder? = null
if (idx >= 0) {
n = notifications.valueAt(idx)
notifications.removeAt(idx)
// The cancelled notification is the one attached to the session, need special handling
if (attachedId == id) {
if (notifications.isNotEmpty()) {
// There are still remaining notifications, pick one and attach to the session
val anotherId = notifications.keyAt(0)
val notification = notifications.valueAt(0)
attachNotification(anotherId, notification)
} else {
// No more notifications left, terminate the session
attachedId = -1
session.onDownloadComplete()
}
}
}
Notifications.mgr.cancel(id)
return n
}
private suspend fun handleApp(stream: InputStream, subject: Subject.App) {
val external = subject.file.outputStream()
if (isRunningAsStub) {
val updateApk = StubApk.update(context)
try {
// Download full APK to stub update path
stream.copyAndClose(TeeOutputStream(external, updateApk.outputStream()))
// Also upgrade stub
notifyUpdate(subject.notifyId) {
it.setProgress(0, 0, true)
.setContentTitle(context.getString(R.string.hide_app_title))
.setContentText("")
}
// Extract stub
val zf = ZipFile(updateApk)
val apk = context.cachedFile("stub.apk")
apk.delete()
zf.getInputStream(zf.getEntry("assets/stub.apk")).writeTo(apk)
zf.close()
// Patch and install
subject.intent = HideAPK.upgrade(context, apk)
?: throw IOException("HideAPK patch error")
apk.delete()
} catch (e: Exception) {
// If any error occurred, do not let stub load the new APK
updateApk.delete()
throw e
}
} else {
val session = APKInstall.startSession(context)
stream.copyAndClose(TeeOutputStream(external, session.openStream(context)))
subject.intent = session.waitIntent()
}
}
private suspend fun handleModule(src: InputStream, file: Uri) {
val input = ZipInputStream(src)
val output = ZipOutputStream(file.outputStream())
withStreams(input, output) { zin, zout ->
zout.putNextEntry(ZipEntry("META-INF/"))
zout.putNextEntry(ZipEntry("META-INF/com/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/android/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/android/update-binary"))
context.assets.open("module_installer.sh").use { it.copyAll(zout) }
zout.putNextEntry(ZipEntry("META-INF/com/google/android/updater-script"))
zout.write("#MAGISK\n".toByteArray())
zin.forEach { entry ->
val path = entry.name
if (path.isNotEmpty() && !path.startsWith("META-INF")) {
zout.putNextEntry(ZipEntry(path))
if (!entry.isDirectory) {
zin.copyAll(zout)
}
}
}
}
}
private class TeeOutputStream(
private val o1: OutputStream,
private val o2: OutputStream
) : OutputStream() {
override fun write(b: Int) {
o1.write(b)
o2.write(b)
}
override fun write(b: ByteArray?, off: Int, len: Int) {
o1.write(b, off, len)
o2.write(b, off, len)
}
override fun close() {
o1.close()
o2.close()
}
}
private fun ResponseBody.toProgressStream(subject: Subject): InputStream {
val max = contentLength()
val total = max.toFloat() / 1048576
val id = subject.notifyId
notifyUpdate(id) { it.setContentTitle(subject.title) }
return ProgressInputStream(byteStream()) {
val progress = it.toFloat() / 1048576
notifyUpdate(id) { notification ->
if (max > 0) {
broadcast(progress / total, subject)
notification
.setProgress(max.toInt(), it.toInt(), false)
.setContentText("%.2f / %.2f MB".format(progress, total))
} else {
broadcast(-1f, subject)
notification.setContentText("%.2f MB / ??".format(progress))
}
}
}
}
}

View File

@ -1,220 +0,0 @@
package com.topjohnwu.magisk.core.download
import android.Manifest
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.PendingIntent.*
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.core.net.toFile
import androidx.lifecycle.LifecycleOwner
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.ActivityTracker
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.intent
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.*
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.utils.APKInstall
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.Properties
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
class DownloadService : NotificationService() {
private val job = Job()
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
intent.getParcelableExtra<Subject>(SUBJECT_KEY)?.let { download(it) }
return START_NOT_STICKY
}
override fun onDestroy() {
job.cancel()
}
private fun download(subject: Subject) {
notifyUpdate(subject.notifyId)
CoroutineScope(job + Dispatchers.IO).launch {
try {
val stream = service.fetchFile(subject.url).toProgressStream(subject)
when (subject) {
is Subject.App -> handleApp(stream, subject)
is Subject.Module -> handleModule(stream, subject.file)
}
val activity = ActivityTracker.foreground
if (activity != null && subject.autoLaunch) {
notifyRemove(subject.notifyId)
subject.pendingIntent(activity)?.send()
} else {
notifyFinish(subject)
}
subject.postDownload?.invoke()
if (!hasNotifications)
stopSelf()
} catch (e: Exception) {
Timber.e(e)
notifyFail(subject)
}
}
}
private fun handleApp(stream: InputStream, subject: Subject.App) {
fun writeTee(output: OutputStream) {
val uri = MediaStoreUtils.getFile("${subject.title}.apk").uri
val external = uri.outputStream()
stream.copyAndClose(TeeOutputStream(external, output))
}
if (isRunningAsStub) {
val updateApk = StubApk.update(this)
try {
// Download full APK to stub update path
writeTee(updateApk.outputStream())
val zf = ZipFile(updateApk)
val prop = Properties()
prop.load(ByteArrayInputStream(zf.comment.toByteArray()))
val stubVersion = prop.getProperty("stubVersion").toIntOrNull() ?: -1
if (Info.stub!!.version < stubVersion) {
// Also upgrade stub
notifyUpdate(subject.notifyId) {
it.setProgress(0, 0, true)
.setContentTitle(getString(R.string.hide_app_title))
.setContentText("")
}
// Extract stub
val apk = subject.file.toFile()
zf.getInputStream(zf.getEntry("assets/stub.apk")).writeTo(apk)
zf.close()
// Patch and install
subject.intent = HideAPK.upgrade(this, apk)
?: throw IOException("HideAPK patch error")
apk.delete()
} else {
ActivityTracker.foreground?.let {
// Relaunch the process if we are foreground
StubApk.restartProcess(it)
} ?: run {
// Or else kill the current process after posting notification
subject.intent = selfLaunchIntent()
subject.postDownload = { Runtime.getRuntime().exit(0) }
}
return
}
} catch (e: Exception) {
// If any error occurred, do not let stub load the new APK
updateApk.delete()
throw e
}
} else {
val session = APKInstall.startSession(this)
writeTee(session.openStream(this))
subject.intent = session.waitIntent()
}
}
private fun handleModule(src: InputStream, file: Uri) {
val input = ZipInputStream(src.buffered())
val output = ZipOutputStream(file.outputStream().buffered())
withStreams(input, output) { zin, zout ->
zout.putNextEntry(ZipEntry("META-INF/"))
zout.putNextEntry(ZipEntry("META-INF/com/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/android/"))
zout.putNextEntry(ZipEntry("META-INF/com/google/android/update-binary"))
assets.open("module_installer.sh").copyTo(zout)
zout.putNextEntry(ZipEntry("META-INF/com/google/android/updater-script"))
zout.write("#MAGISK\n".toByteArray())
zin.forEach { entry ->
val path = entry.name
if (path.isNotEmpty() && !path.startsWith("META-INF")) {
zout.putNextEntry(ZipEntry(path))
if (!entry.isDirectory) {
zin.copyTo(zout)
}
}
}
}
}
private class TeeOutputStream(
private val o1: OutputStream,
private val o2: OutputStream
) : OutputStream() {
override fun write(b: Int) {
o1.write(b)
o2.write(b)
}
override fun write(b: ByteArray?, off: Int, len: Int) {
o1.write(b, off, len)
o2.write(b, off, len)
}
override fun close() {
o1.close()
o2.close()
}
}
companion object {
private const val SUBJECT_KEY = "subject"
private const val REQUEST_CODE = 1
fun observeProgress(owner: LifecycleOwner, callback: (Float, Subject) -> Unit) {
progressBroadcast.value = null
progressBroadcast.observe(owner) {
val (progress, subject) = it ?: return@observe
callback(progress, subject)
}
}
private fun intent(context: Context, subject: Subject) =
context.intent<DownloadService>().putExtra(SUBJECT_KEY, subject)
@SuppressLint("InlinedApi")
fun getPendingIntent(context: Context, subject: Subject): PendingIntent {
val flag = FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT or FLAG_ONE_SHOT
val intent = intent(context, subject)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
getForegroundService(context, REQUEST_CODE, intent, flag)
} else {
getService(context, REQUEST_CODE, intent, flag)
}
}
@SuppressLint("InlinedApi")
fun start(activity: BaseActivity, subject: Subject) {
activity.withPermission(Manifest.permission.POST_NOTIFICATIONS) {
// Always download regardless of notification permission status
val app = activity.applicationContext
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
app.startForegroundService(intent(app, subject))
} else {
app.startService(intent(app, subject))
}
}
}
}
}

View File

@ -1,128 +0,0 @@
package com.topjohnwu.magisk.core.download
import android.app.Notification
import android.content.Intent
import android.os.Build
import androidx.lifecycle.MutableLiveData
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.base.BaseService
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.synchronized
import com.topjohnwu.magisk.core.utils.ProgressInputStream
import com.topjohnwu.magisk.view.Notifications
import okhttp3.ResponseBody
import java.io.InputStream
open class NotificationService : BaseService() {
private val notifications = HashMap<Int, Notification.Builder>().synchronized()
protected val hasNotifications get() = notifications.isNotEmpty()
protected val service get() = ServiceLocator.networkService
private var attachedNotificationId = 0
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
notifications.forEach { Notifications.mgr.cancel(it.key) }
notifications.clear()
}
protected fun ResponseBody.toProgressStream(subject: Subject): InputStream {
val max = contentLength()
val total = max.toFloat() / 1048576
val id = subject.notifyId
notifyUpdate(id) { it.setContentTitle(subject.title) }
return ProgressInputStream(byteStream()) {
val progress = it.toFloat() / 1048576
notifyUpdate(id) { notification ->
if (max > 0) {
broadcast(progress / total, subject)
notification
.setProgress(max.toInt(), it.toInt(), false)
.setContentText("%.2f / %.2f MB".format(progress, total))
} else {
broadcast(-1f, subject)
notification.setContentText("%.2f MB / ??".format(progress))
}
}
}
}
private fun finalNotify(id: Int, editor: (Notification.Builder) -> Unit): Int {
val notification = notifyRemove(id)?.also(editor) ?: return -1
val newId = Notifications.nextId()
Notifications.mgr.notify(newId, notification.build())
return newId
}
protected fun notifyFail(subject: Subject) = finalNotify(subject.notifyId) {
broadcast(-2f, subject)
it.setContentText(getString(R.string.download_file_error))
.setSmallIcon(android.R.drawable.stat_notify_error)
.setOngoing(false)
}
protected fun notifyFinish(subject: Subject) = finalNotify(subject.notifyId) {
broadcast(1f, subject)
it.setContentTitle(subject.title)
.setContentText(getString(R.string.download_complete))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setProgress(0, 0, false)
.setOngoing(false)
.setAutoCancel(true)
subject.pendingIntent(this)?.let { intent -> it.setContentIntent(intent) }
}
private fun attachNotification(id: Int, notification: Notification) {
attachedNotificationId = id
startForeground(id, notification)
}
private fun maybeDetachNotification(id: Int) : Boolean {
if (attachedNotificationId != id) return false
if (hasNotifications) {
val (anotherId, notification) = notifications.entries.first()
// Attaching a new notification will remove the current showing one
attachNotification(anotherId, notification.build())
return true
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE)
} else {
@Suppress("DEPRECATION")
stopForeground(true)
}
attachedNotificationId = 0
return true
}
protected fun notifyUpdate(id: Int, editor: (Notification.Builder) -> Unit = {}) {
fun create() = Notifications.startProgress("")
val wasEmpty = !hasNotifications
val notification = notifications.getOrPut(id, ::create).also(editor).build()
if (wasEmpty)
attachNotification(id, notification)
else
Notifications.mgr.notify(id, notification)
}
protected fun notifyRemove(id: Int): Notification.Builder? {
val n = notifications.remove(id)
if (n == null || !maybeDetachNotification(id))
Notifications.mgr.cancel(id)
return n
}
companion object {
@JvmStatic
protected val progressBroadcast = MutableLiveData<Pair<Float, Subject>?>()
private fun broadcast(progress: Float, subject: Subject) {
progressBroadcast.postValue(progress to subject)
}
}
}

View File

@ -17,13 +17,8 @@ import com.topjohnwu.magisk.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.Notifications
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
private fun cachedFile(name: String) = AppContext.cachedFile(name).apply { delete() }.toUri()
enum class Action {
Flash,
Download
}
import java.io.File
import java.util.UUID
sealed class Subject : Parcelable {
@ -32,19 +27,17 @@ sealed class Subject : Parcelable {
abstract val title: String
abstract val notifyId: Int
open val autoLaunch: Boolean get() = true
open val postDownload: (() -> Unit)? get() = null
abstract fun pendingIntent(context: Context): PendingIntent?
open fun pendingIntent(context: Context): PendingIntent? = null
@Parcelize
class Module(
val module: OnlineModule,
val action: Action,
private val module: OnlineModule,
override val autoLaunch: Boolean,
override val notifyId: Int = Notifications.nextId()
) : Subject() {
override val url: String get() = module.zipUrl
override val title: String get() = module.downloadFilename
override val autoLaunch: Boolean get() = action == Action.Flash
@IgnoredOnParcel
override val file by lazy {
@ -65,17 +58,24 @@ sealed class Subject : Parcelable {
@IgnoredOnParcel
override val file by lazy {
cachedFile("manager.apk")
MediaStoreUtils.getFile("${title}.apk").uri
}
@IgnoredOnParcel
override var postDownload: (() -> Unit)? = null
@IgnoredOnParcel
var intent: Intent? = null
override fun pendingIntent(context: Context) = intent?.toPending(context)
}
@Parcelize
class Test(
override val notifyId: Int = Notifications.nextId(),
override val title: String = UUID.randomUUID().toString().substring(0, 6)
) : Subject() {
override val url get() = "https://link.testfile.org/250MB"
override val file get() = File("/dev/null").toUri()
override val autoLaunch get() = false
}
@SuppressLint("InlinedApi")
protected fun Intent.toPending(context: Context): PendingIntent {
return PendingIntent.getActivity(context, notifyId, this,

View File

@ -2,10 +2,15 @@ package com.topjohnwu.magisk.core.ktx
import androidx.collection.SparseArrayCompat
import com.topjohnwu.magisk.core.utils.currentLocale
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.lang.reflect.Field
@ -35,9 +40,38 @@ inline fun <In : InputStream, Out : OutputStream> withStreams(
}
}
fun InputStream.copyAndClose(out: OutputStream) = withStreams(this, out) { i, o -> i.copyTo(o) }
@Throws(IOException::class)
suspend fun InputStream.copyAll(
out: OutputStream,
bufferSize: Int = DEFAULT_BUFFER_SIZE,
dispatcher: CoroutineDispatcher = Dispatchers.IO
): Long {
return withContext(dispatcher) {
var bytesCopied: Long = 0
val buffer = ByteArray(bufferSize)
var bytes = read(buffer)
while (isActive && bytes >= 0) {
out.write(buffer, 0, bytes)
bytesCopied += bytes
bytes = read(buffer)
}
bytesCopied
}
}
fun InputStream.writeTo(file: File) = copyAndClose(file.outputStream())
@Throws(IOException::class)
suspend inline fun InputStream.copyAndClose(
out: OutputStream,
bufferSize: Int = DEFAULT_BUFFER_SIZE,
dispatcher: CoroutineDispatcher = Dispatchers.IO
) = withStreams(this, out) { i, o -> i.copyAll(o, bufferSize, dispatcher) }
@Throws(IOException::class)
suspend inline fun InputStream.writeTo(
file: File,
bufferSize: Int = DEFAULT_BUFFER_SIZE,
dispatcher: CoroutineDispatcher = Dispatchers.IO
) = copyAndClose(file.outputStream(), bufferSize, dispatcher)
operator fun <E> SparseArrayCompat<E>.set(key: Int, value: E) {
put(key, value)

View File

@ -58,6 +58,7 @@ class SuRequestHandler(
val pid = intent.getIntExtra("pid", -1)
val fifo = intent.getStringExtra("fifo")
if (uid <= 0 || pid <= 0 || fifo == null) {
Timber.e("Unexpected extras: uid=[${uid}], pid=[${pid}], fifo=[${fifo}]")
return false
}
output = File(fifo)
@ -73,7 +74,11 @@ class SuRequestHandler(
respond(SuPolicy.DENY, -1)
return false
}
return output.canWrite()
if (!output.canWrite()) {
Timber.e("Cannot write to $output")
return false
}
return true
}
suspend fun respond(action: Int, time: Int) {

View File

@ -0,0 +1,68 @@
package com.topjohnwu.magisk.core.su
import android.os.Bundle
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.core.utils.RootUtils
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.internal.NOPList
import kotlinx.coroutines.runBlocking
object TestHandler {
fun run(method: String): Bundle {
val r = Bundle()
fun setup(): Boolean {
val nop = NOPList.getInstance()
return runBlocking {
MagiskInstaller.Emulator(nop, nop).exec()
}
}
fun test(): Boolean {
// Make sure Zygisk works correctly
if (!Info.isZygiskEnabled) {
r.putString("reason", "zygisk not enabled")
return false
}
// Make sure the Magisk app can get root
val shell = Shell.getShell()
if (!shell.isRoot) {
r.putString("reason", "shell not root")
return false
}
// Make sure the root service is running
RootUtils.Connection.await()
// Clear existing grant for ADB shell
runBlocking {
ServiceLocator.policyDB.delete(2000)
Config.suAutoResponse = Config.Value.SU_AUTO_ALLOW
Config.prefs.edit().commit()
}
return true
}
val b = runCatching {
when (method) {
"setup" -> setup()
"test" -> test()
else -> {
r.putString("reason", "unknown method")
false
}
}
}.getOrElse {
r.putString("reason", it.stackTraceToString())
false
}
r.putBoolean("result", b)
return r
}
}

View File

@ -26,7 +26,7 @@ open class FlashZip(
private lateinit var zipFile: File
@Throws(IOException::class)
private fun flash(): Boolean {
private suspend fun flash(): Boolean {
installDir.deleteRecursively()
installDir.mkdirs()
@ -47,13 +47,13 @@ open class FlashZip(
}
}
val isValid = runCatching {
val isValid = try {
zipFile.unzip(installDir, "META-INF/com/google/android", true)
val script = File(installDir, "updater-script")
script.readText().contains("#MAGISK")
}.getOrElse {
} catch (e: IOException) {
console.add("! Unzip error")
throw it
throw e
}
if (!isValid) {

View File

@ -12,6 +12,7 @@ import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Provider
import com.topjohnwu.magisk.core.ktx.await
import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.utils.AXML
@ -168,7 +169,7 @@ object HideAPK {
activity.finish()
}
private fun patchAndHide(activity: Activity, label: String, onFailure: Runnable): Boolean {
private suspend fun patchAndHide(activity: Activity, label: String, onFailure: Runnable): Boolean {
val stub = File(activity.cacheDir, "stub.apk")
try {
activity.assets.open("stub.apk").writeTo(stub)
@ -195,7 +196,7 @@ object HideAPK {
if (Shell.cmd(cmd).exec().isSuccess) return true
try {
session.install(activity, repack)
repack.inputStream().copyAndClose(session.openStream(activity))
} catch (e: IOException) {
Timber.e(e)
return false
@ -244,7 +245,7 @@ object HideAPK {
if (Shell.cmd(cmd).await().isSuccess) return
val success = withContext(Dispatchers.IO) {
try {
session.install(activity, apk)
apk.inputStream().copyAndClose(session.openStream(activity))
} catch (e: IOException) {
Timber.e(e)
return@withContext false

View File

@ -1,6 +1,7 @@
package com.topjohnwu.magisk.core.tasks
import android.net.Uri
import android.os.Process
import android.system.ErrnoException
import android.system.Os
import android.system.OsConstants
@ -17,6 +18,7 @@ import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.copyAll
import com.topjohnwu.magisk.core.ktx.copyAndClose
import com.topjohnwu.magisk.core.ktx.reboot
import com.topjohnwu.magisk.core.ktx.toast
@ -93,7 +95,7 @@ abstract class MagiskInstallImpl protected constructor(
return true
}
private fun extractFiles(): Boolean {
private suspend fun extractFiles(): Boolean {
console.add("- Device platform: ${Const.CPU_ABI}")
console.add("- Installing: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
@ -104,40 +106,41 @@ abstract class MagiskInstallImpl protected constructor(
try {
// Extract binaries
if (isRunningAsStub) {
val zf = ZipFile(StubApk.current(context))
ZipFile(StubApk.current(context)).use { zf ->
zf.entries().asSequence().filter {
!it.isDirectory && it.name.startsWith("/lib/${Const.CPU_ABI}/")
}.forEach {
val n = it.name.substring(it.name.lastIndexOf('/') + 1)
val name = n.substring(3, n.length - 3)
val dest = File(installDir, name)
zf.getInputStream(it).writeTo(dest)
dest.setExecutable(true)
}
// Also extract magisk32 on non 64-bit only 64-bit devices
val is32lib = Const.CPU_ABI_32?.let {
{ entry: ZipEntry -> entry.name == "lib/$it/libmagisk32.so" }
} ?: { false }
zf.entries().asSequence().filter {
!it.isDirectory && (it.name.startsWith("lib/${Const.CPU_ABI}/") || is32lib(it))
}.forEach {
val n = it.name.substring(it.name.lastIndexOf('/') + 1)
val name = n.substring(3, n.length - 3)
val dest = File(installDir, name)
zf.getInputStream(it).writeTo(dest)
dest.setExecutable(true)
val abi32 = Const.CPU_ABI_32
if (Process.is64Bit() && abi32 != null) {
val magisk32 = File(installDir, "magisk32")
zf.getInputStream(ZipEntry("lib/$abi32/libmagisk.so")).writeTo(magisk32)
magisk32.setExecutable(true)
}
}
zf.close()
} else {
val info = context.applicationInfo
var libs = File(info.nativeLibraryDir).listFiles { _, name ->
name.startsWith("lib") && name.endsWith(".so")
} ?: emptyArray()
// Also symlink magisk32 on non 64-bit only 64-bit devices
val lib32 = info.javaClass.getDeclaredField("secondaryNativeLibraryDir")
.get(info) as String?
if (lib32 != null) {
libs += File(lib32, "libmagisk32.so")
}
for (lib in libs) {
val name = lib.name.substring(3, lib.name.length - 3)
Os.symlink(lib.path, "$installDir/$name")
}
// Also symlink magisk32 on 64-bit devices that supports 32-bit
val lib32 = info.javaClass.getDeclaredField("secondaryNativeLibraryDir")
.get(info) as String?
if (lib32 != null) {
Os.symlink("$lib32/libmagisk.so", "$installDir/magisk32");
}
}
// Extract scripts
@ -174,27 +177,30 @@ abstract class MagiskInstallImpl protected constructor(
return true
}
private fun InputStream.copyAndCloseOut(out: OutputStream) = out.use { copyTo(it) }
private suspend fun InputStream.copyAndCloseOut(out: OutputStream) = out.use { copyAll(it) }
private fun newTarEntry(name: String, size: Long): TarEntry {
console.add("-- Writing: $name")
return TarEntry(TarHeader.createHeader(name, size, 0, false, 420 /* 0644 */))
}
private class LZ4InputStream(s: InputStream) : LZ4FrameInputStream(s) {
// Workaround bug in LZ4FrameInputStream
private class NoAvailableStream(s: InputStream) : FilterInputStream(s) {
// Make sure available is never called on the actual stream and always return 0
// 1. Workaround bug in LZ4FrameInputStream
// 2. Reduce max buffer size to prevent OOM
override fun available() = 0
}
private class NoBootException : IOException()
@Throws(IOException::class)
private fun processTar(tarIn: TarInputStream, tarOut: TarOutputStream): ExtendedFile {
private suspend fun processTar(tarIn: TarInputStream, tarOut: TarOutputStream): ExtendedFile {
console.add("- Processing tar file")
lateinit var entry: TarEntry
fun decompressedStream(): InputStream {
return if (entry.name.endsWith(".lz4")) LZ4InputStream(tarIn) else tarIn
val stream = if (entry.name.endsWith(".lz4")) LZ4FrameInputStream(tarIn) else tarIn
return NoAvailableStream(stream)
}
while (tarIn.nextEntry?.let { entry = it } != null) {
@ -218,12 +224,14 @@ abstract class MagiskInstallImpl protected constructor(
ByteBuffer.wrap(rawData).putInt(120, 3)
tarOut.putNextEntry(newTarEntry("vbmeta.img", rawData.size.toLong()))
tarOut.write(rawData)
// vbmeta partition exist, disable boot vbmeta patch
Info.patchBootVbmeta = false
} else if (entry.name.contains("userdata.img")) {
continue
} else {
console.add("-- Copying: ${entry.name}")
tarOut.putNextEntry(entry)
tarIn.copyTo(tarOut, bufferSize = 1024 * 1024)
tarIn.copyAll(tarOut, bufferSize = 1024 * 1024)
}
}
@ -231,10 +239,10 @@ abstract class MagiskInstallImpl protected constructor(
val initBoot = installDir.getChildFile("init_boot.img")
val recovery = installDir.getChildFile("recovery.img")
fun ExtendedFile.copyToTar() {
suspend fun ExtendedFile.copyToTar() {
newInputStream().use {
tarOut.putNextEntry(newTarEntry(name, length()))
it.copyTo(tarOut)
it.copyAll(tarOut)
}
delete()
}
@ -268,7 +276,7 @@ abstract class MagiskInstallImpl protected constructor(
}
@Throws(IOException::class)
private fun processZip(zipIn: ZipInputStream): ExtendedFile {
private suspend fun processZip(zipIn: ZipInputStream): ExtendedFile {
console.add("- Processing zip file")
val boot = installDir.getChildFile("boot.img")
val initBoot = installDir.getChildFile("init_boot.img")
@ -320,7 +328,8 @@ abstract class MagiskInstallImpl protected constructor(
val fd = Os.open(fifo.path, O_WRONLY, 0)
try {
val buf = ByteBuffer.allocate(1024 * 1024)
val bufSize = 1024 * 1024
val buf = ByteBuffer.allocate(bufSize)
buf.position(input.read(buf.array()).coerceAtLeast(0)).flip()
while (buf.hasRemaining()) {
try {
@ -332,6 +341,7 @@ abstract class MagiskInstallImpl protected constructor(
break
}
if (!buf.hasRemaining()) {
buf.limit(bufSize)
buf.position(input.read(buf.array()).coerceAtLeast(0)).flip()
}
}
@ -366,23 +376,22 @@ abstract class MagiskInstallImpl protected constructor(
}
}
private fun handleFile(uri: Uri): Boolean {
private suspend fun handleFile(uri: Uri): Boolean {
val outStream: OutputStream
val outFile: MediaStoreUtils.UriFile
// Process input file
try {
uri.inputStream().buffered().use { src ->
src.mark(500)
val magic = ByteArray(4)
val tarMagic = ByteArray(5)
if (src.read(magic) != magic.size || src.skip(253) != 253L ||
src.read(tarMagic) != tarMagic.size
) {
PushbackInputStream(uri.inputStream(), 512).use { src ->
val head = ByteArray(512)
if (src.read(head) != head.size) {
console.add("! Invalid input file")
return false
}
src.reset()
src.unread(head)
val magic = head.copyOf(4)
val tarMagic = Arrays.copyOfRange(head, 257, 262)
val alpha = "abcdefghijklmnopqrstuvwxyz"
val alphaNum = "$alpha${alpha.uppercase(Locale.ROOT)}0123456789"
@ -490,7 +499,7 @@ abstract class MagiskInstallImpl protected constructor(
"cd $installDir",
"KEEPFORCEENCRYPT=${Config.keepEnc} " +
"KEEPVERITY=${Config.keepVerity} " +
"PATCHVBMETAFLAG=${Config.patchVbmeta} " +
"PATCHVBMETAFLAG=${Info.patchBootVbmeta} " +
"RECOVERYMODE=${Config.recovery} " +
"LEGACYSAR=${Info.legacySAR} " +
"sh boot_patch.sh $srcBoot")
@ -503,7 +512,7 @@ abstract class MagiskInstallImpl protected constructor(
private fun flashBoot() = "direct_install $installDir $srcBoot".sh().isSuccess
private fun postOTA(): Boolean {
private suspend fun postOTA(): Boolean {
try {
val bootctl = File.createTempFile("bootctl", null, context.cacheDir)
context.assets.open("bootctl").writeTo(bootctl)
@ -514,9 +523,10 @@ abstract class MagiskInstallImpl protected constructor(
return false
}
console.add("***************************************")
console.add("*************************************************************")
console.add(" Next reboot will boot to second slot!")
console.add("***************************************")
console.add(" Go back to System Updates and press Restart to complete OTA")
console.add("*************************************************************")
return true
}
@ -526,14 +536,14 @@ abstract class MagiskInstallImpl protected constructor(
private fun String.fsh() = ShellUtils.fastCmd(shell, this)
private fun Array<String>.fsh() = ShellUtils.fastCmd(shell, *this)
protected fun patchFile(file: Uri) = extractFiles() && handleFile(file)
protected suspend fun patchFile(file: Uri) = extractFiles() && handleFile(file)
protected fun direct() = findImage() && extractFiles() && patchBoot() && flashBoot()
protected suspend fun direct() = findImage() && extractFiles() && patchBoot() && flashBoot()
protected fun secondSlot() =
protected suspend fun secondSlot() =
findSecondary() && extractFiles() && patchBoot() && flashBoot() && postOTA()
protected fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
protected suspend fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
protected fun uninstall() = "run_uninstaller $AppApkPath".sh().isSuccess

View File

@ -1,53 +0,0 @@
package com.topjohnwu.magisk.core.utils
import android.content.Context
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
class BiometricHelper(context: Context) {
private val mgr = BiometricManager.from(context)
val isSupported get() = when (mgr.canAuthenticate(Authenticators.BIOMETRIC_WEAK)) {
BiometricManager.BIOMETRIC_SUCCESS -> true
else -> false
}
val isEnabled get() = isSupported && Config.suBiometric
fun authenticate(
activity: FragmentActivity,
onError: () -> Unit = {},
onSuccess: () -> Unit): BiometricPrompt {
val prompt = BiometricPrompt(activity,
ContextCompat.getMainExecutor(activity),
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
onError()
}
override fun onAuthenticationFailed() {
onError()
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
onSuccess()
}
}
)
val info = BiometricPrompt.PromptInfo.Builder()
.setConfirmationRequired(true)
.setAllowedAuthenticators(Authenticators.BIOMETRIC_WEAK)
.setTitle(activity.getString(R.string.authenticate))
.setNegativeButtonText(activity.getString(android.R.string.cancel))
.build()
prompt.authenticate(info)
return prompt
}
}

View File

@ -12,7 +12,7 @@ import com.topjohnwu.magisk.core.createNewResources
import com.topjohnwu.magisk.core.di.AppContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.*
import java.util.Locale
var currentLocale: Locale = Locale.getDefault()

View File

@ -15,9 +15,6 @@ import com.topjohnwu.magisk.core.di.AppContext
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.io.OutputStream
import java.security.MessageDigest
import kotlin.experimental.and
@Suppress("DEPRECATION")
object MediaStoreUtils {
@ -120,24 +117,6 @@ object MediaStoreUtils {
return this.toString()
}
fun Uri.checkSum(alg: String, reference: String) = runCatching {
this.inputStream().use {
val digest = MessageDigest.getInstance(alg)
it.copyTo(object : OutputStream() {
override fun write(b: Int) {
digest.update(b.toByte())
}
override fun write(b: ByteArray, off: Int, len: Int) {
digest.update(b, off, len)
}
})
val sb = StringBuilder()
digest.digest().forEach { b -> sb.append("%02x".format(b and 0xff.toByte())) }
sb.toString() == reference
}
}.getOrElse { false }
interface UriFile {
val uri: Uri
fun delete(): Boolean

View File

@ -14,14 +14,10 @@ import androidx.core.content.getSystemService
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.ktx.registerRuntimeReceiver
typealias ConnectionCallback = (Boolean) -> Unit
class NetworkObserver(
context: Context,
private val callback: ConnectionCallback
): DefaultLifecycleObserver {
class NetworkObserver(context: Context): DefaultLifecycleObserver {
private val manager = context.getSystemService<ConnectivityManager>()!!
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
@ -29,11 +25,11 @@ class NetworkObserver(
override fun onAvailable(network: Network) {
activeList.add(network)
callback(true)
postValue(true)
}
override fun onLost(network: Network) {
activeList.remove(network)
callback(!activeList.isEmpty())
postValue(!activeList.isEmpty())
}
}
@ -45,7 +41,7 @@ class NetworkObserver(
}
override fun onReceive(context: Context, intent: Intent) {
if (context.isIdleMode()) {
callback(false)
postValue(false)
} else {
postCurrentState()
}
@ -67,13 +63,18 @@ class NetworkObserver(
}
private fun postCurrentState() {
callback(manager.getNetworkCapabilities(manager.activeNetwork)
postValue(manager.getNetworkCapabilities(manager.activeNetwork)
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false)
}
private fun postValue(b: Boolean) {
Info.remote = Info.EMPTY_REMOTE
Info.isConnected.postValue(b)
}
companion object {
fun observe(context: Context, callback: ConnectionCallback): NetworkObserver {
return NetworkObserver(context, callback).apply { postCurrentState() }
fun init(context: Context): NetworkObserver {
return NetworkObserver(context).apply { postCurrentState() }
}
}
}

View File

@ -0,0 +1,17 @@
package com.topjohnwu.magisk.core.utils
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract
class RequestAuthentication: ActivityResultContract<Unit, Boolean>() {
override fun createIntent(context: Context, input: Unit) =
context.getSystemService(KeyguardManager::class.java)
.createConfirmDeviceCredentialIntent(null, null)
override fun parseResult(resultCode: Int, intent: Intent?) =
resultCode == Activity.RESULT_OK
}

View File

@ -13,6 +13,8 @@ import com.topjohnwu.magisk.core.ktx.rawResource
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import java.io.File
import java.util.jar.JarFile
@ -34,7 +36,9 @@ class ShellInit : Shell.Initializer() {
val bb = jar.getJarEntry("lib/${Const.CPU_ABI}/libbusybox.so")
localBB = context.deviceProtectedContext.cachedFile("busybox")
localBB.delete()
jar.getInputStream(bb).writeTo(localBB)
runBlocking {
jar.getInputStream(bb).writeTo(localBB, dispatcher = Dispatchers.Unconfined)
}
localBB.setExecutable(true)
} else {
localBB = File(context.applicationInfo.nativeLibraryDir, "libbusybox.so")
@ -73,18 +77,17 @@ class ShellInit : Shell.Initializer() {
fun getVar(name: String) = fastCmd("echo \$$name")
fun getBool(name: String) = getVar(name).toBoolean()
Info.isSAR = getBool("SYSTEM_ROOT")
Info.isSAR = getBool("SYSTEM_AS_ROOT")
Info.ramdisk = getBool("RAMDISKEXIST")
Info.vbmeta = getBool("VBMETAEXIST")
Info.isAB = getBool("ISAB")
Info.crypto = getVar("CRYPTOTYPE")
Info.patchBootVbmeta = getBool("PATCHVBMETAFLAG")
Info.legacySAR = getBool("LEGACYSAR")
// Default presets
Config.recovery = getBool("RECOVERYMODE")
Config.keepVerity = getBool("KEEPVERITY")
Config.keepEnc = getBool("KEEPFORCEENCRYPT")
Config.patchVbmeta = getBool("PATCHVBMETAFLAG")
return true
}

View File

@ -1,5 +1,6 @@
package com.topjohnwu.magisk.core.utils
import com.topjohnwu.magisk.core.ktx.copyAll
import java.io.File
import java.io.IOException
import java.io.InputStream
@ -7,14 +8,14 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@Throws(IOException::class)
fun File.unzip(folder: File, path: String = "", junkPath: Boolean = false) {
suspend fun File.unzip(folder: File, path: String = "", junkPath: Boolean = false) {
inputStream().buffered().use {
it.unzip(folder, path, junkPath)
}
}
@Throws(IOException::class)
fun InputStream.unzip(folder: File, path: String, junkPath: Boolean) {
suspend fun InputStream.unzip(folder: File, path: String, junkPath: Boolean) {
try {
val zin = ZipInputStream(this)
var entry: ZipEntry
@ -34,7 +35,7 @@ fun InputStream.unzip(folder: File, path: String, junkPath: Boolean) {
if (!it.exists())
it.mkdirs()
}
dest.outputStream().use { out -> zin.copyTo(out) }
dest.outputStream().use { out -> zin.copyAll(out) }
}
} catch (e: IllegalArgumentException) {
throw IOException(e)

View File

@ -8,7 +8,12 @@ import android.text.Spanned
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.*
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.Spinner
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.Toolbar
import androidx.cardview.widget.CardView
@ -20,7 +25,11 @@ import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter
import androidx.databinding.InverseBindingListener
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.*
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip

View File

@ -3,7 +3,7 @@ package com.topjohnwu.magisk.databinding
import androidx.databinding.ListChangeRegistry
import androidx.databinding.ObservableList
import androidx.databinding.ObservableList.OnListChangedCallback
import java.util.*
import java.util.AbstractList
@Suppress("UNCHECKED_CAST")
class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {

View File

@ -4,7 +4,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.view.MagiskDialog
import java.io.File
@ -29,7 +29,7 @@ class ManagerInstallDialog : MarkDownDialog() {
setCancelable(true)
setButton(MagiskDialog.ButtonType.POSITIVE) {
text = R.string.install
onClick { DownloadService.start(activity, Subject.App()) }
onClick { DownloadEngine.startWithActivity(activity, Subject.App()) }
}
setButton(MagiskDialog.ButtonType.NEGATIVE) {
text = android.R.string.cancel

View File

@ -2,8 +2,7 @@ package com.topjohnwu.magisk.dialog
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.download.Action
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.view.MagiskDialog
@ -22,9 +21,7 @@ class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog
dialog.apply {
fun download(install: Boolean) {
val action = if (install) Action.Flash else Action.Download
val subject = Subject.Module(item, action)
DownloadService.start(activity, subject)
DownloadEngine.startWithActivity(activity, Subject.Module(item, install))
}
val title = context.getString(R.string.repo_install_title,

View File

@ -1,38 +0,0 @@
package com.topjohnwu.magisk.events
import com.topjohnwu.magisk.arch.ActivityExecutor
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.arch.ViewEvent
import com.topjohnwu.magisk.core.di.ServiceLocator
class BiometricEvent(
builder: Builder.() -> Unit
) : ViewEvent(), ActivityExecutor {
private var listenerOnFailure: () -> Unit = {}
private var listenerOnSuccess: () -> Unit = {}
init {
builder(Builder())
}
override fun invoke(activity: UIActivity<*>) {
ServiceLocator.biometrics.authenticate(
activity,
onError = listenerOnFailure,
onSuccess = listenerOnSuccess
)
}
inner class Builder internal constructor() {
fun onFailure(listener: () -> Unit) {
listenerOnFailure = listener
}
fun onSuccess(listener: () -> Unit) {
listenerOnSuccess = listener
}
}
}

View File

@ -51,6 +51,16 @@ class RecreateEvent : ViewEvent(), ActivityExecutor {
}
}
class AuthEvent(
private val callback: () -> Unit
) : ViewEvent(), ActivityExecutor {
override fun invoke(activity: UIActivity<*>) {
activity.authenticateCallback = { if (it) callback() }
activity.requestAuthenticate.launch(Unit)
}
}
class GetContentEvent(
private val type: String,
private val callback: ContentResultCallback

View File

@ -12,7 +12,6 @@ import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.forEach
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavDirections
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
@ -24,13 +23,10 @@ import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.model.module.LocalModule
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Shortcuts
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
class MainViewModel : BaseViewModel()
@ -62,7 +58,6 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
setContentView()
showUnsupportedMessage()
askForHomeShortcut()
checkStubComponent()
// Ask permission to post notifications for background update check
if (Config.checkUpdate) {
@ -231,22 +226,4 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
}.show()
}
}
@SuppressLint("InlinedApi")
private fun checkStubComponent() {
if (intent.component?.className?.contains(HideAPK.PLACEHOLDER) == true) {
// The stub APK was not properly patched, re-apply our changes
withPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES) { granted ->
if (granted) {
lifecycleScope.launch(Dispatchers.IO) {
val apk = File(applicationInfo.sourceDir)
HideAPK.upgrade(this@MainActivity, apk)?.let {
startActivity(it)
}
}
}
}
}
}
}

View File

@ -8,23 +8,30 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.JobService
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.RootUtils
import com.topjohnwu.magisk.ui.theme.Theme
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.File
import java.io.IOException
@SuppressLint("CustomSplashScreen")
abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Binding>() {
@ -58,7 +65,7 @@ abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Bi
showInvalidStateMessage()
return@getShell
}
preLoad(savedInstanceState)
initialize(savedInstanceState)
}
}
}
@ -102,7 +109,7 @@ abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Bi
}
}
private fun preLoad(savedState: Bundle?) {
private fun initialize(savedState: Bundle?) {
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)?.let {
// Make sure the calling package matches (prevent DoS)
if (it == realCallingPackage)
@ -112,7 +119,21 @@ abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Bi
}
Config.load(prevPkg)
handleRepackage(prevPkg)
if (packageName != APPLICATION_ID) {
runCatching {
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
packageManager.getApplicationInfo(APPLICATION_ID, 0)
Shell.cmd("(pm uninstall $APPLICATION_ID)& >/dev/null 2>&1").exec()
}
} else {
if (Config.suManager.isNotEmpty())
Config.suManager = ""
if (prevPkg != null) {
Shell.cmd("(pm uninstall $prevPkg)& >/dev/null 2>&1").exec()
}
}
if (prevPkg != null) {
runOnUiThread {
// Relaunch the process after package migration
@ -121,6 +142,31 @@ abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Bi
return
}
// Validate stub APK
if (isRunningAsStub && (
// Version mismatch
Info.stub!!.version != BuildConfig.STUB_VERSION ||
// Not properly patched
intent.component!!.className.contains(HideAPK.PLACEHOLDER)
)) {
withPermission(REQUEST_INSTALL_PACKAGES) { granted ->
if (granted) {
lifecycleScope.launch(Dispatchers.IO) {
val apk = File(cacheDir, "stub.apk")
try {
assets.open("stub.apk").writeTo(apk)
HideAPK.upgrade(this@SplashActivity, apk)?.let {
startActivity(it)
}
} catch (e: IOException) {
Timber.e(e)
}
}
}
}
return
}
JobService.schedule(this)
Shortcuts.setupDynamic(this)
@ -144,19 +190,4 @@ abstract class SplashActivity<Binding : ViewDataBinding> : NavigationActivity<Bi
}
}
}
private fun handleRepackage(pkg: String?) {
if (packageName != APPLICATION_ID) {
runCatching {
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
packageManager.getApplicationInfo(APPLICATION_ID, 0)
Shell.cmd("(pm uninstall $APPLICATION_ID)& >/dev/null 2>&1").exec()
}
} else {
if (Config.suManager.isNotEmpty())
Config.suManager = ""
pkg ?: return
Shell.cmd("(pm uninstall $pkg)& >/dev/null 2>&1").exec()
}
}
}

View File

@ -4,7 +4,12 @@ import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
import android.content.pm.ComponentInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.*
import android.content.pm.PackageManager.GET_ACTIVITIES
import android.content.pm.PackageManager.GET_PROVIDERS
import android.content.pm.PackageManager.GET_RECEIVERS
import android.content.pm.PackageManager.GET_SERVICES
import android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import android.content.pm.ServiceInfo
import android.graphics.drawable.Drawable
import android.os.Build
@ -12,7 +17,7 @@ import android.os.Build.VERSION.SDK_INT
import androidx.core.os.ProcessCompat
import com.topjohnwu.magisk.core.ktx.getLabel
import com.topjohnwu.magisk.core.utils.currentLocale
import java.util.*
import java.util.TreeSet
class CmdlineListItem(line: String) {
val packageName: String

View File

@ -5,7 +5,11 @@ import android.content.Context
import android.content.pm.ActivityInfo
import android.net.Uri
import android.os.Bundle
import android.view.*
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.view.MenuProvider
import androidx.core.view.isVisible
import androidx.navigation.NavDeepLinkBuilder

View File

@ -72,6 +72,7 @@ class FlashViewModel : BaseViewModel() {
MagiskInstaller.Direct(outItems, logItems).exec()
}
Const.Value.FLASH_INACTIVE_SLOT -> {
showReboot = false
MagiskInstaller.SecondSlot(outItems, logItems).exec()
}
Const.Value.PATCH_FILE -> {

View File

@ -24,6 +24,10 @@ private interface RikkaImpl : Dev {
override val name get() = "RikkaW"
}
private interface CanyieImpl : Dev {
override val name get() = "canyie"
}
sealed class DeveloperItem : Dev {
abstract val items: List<IconLink>
@ -61,6 +65,14 @@ sealed class DeveloperItem : Dev {
object : IconLink.Github.User(), RikkaImpl {}
)
}
object Canyie : DeveloperItem(), CanyieImpl {
override val items =
listOf<IconLink>(
object : IconLink.Twitter() { override val name = "canyie2977" },
object : IconLink.Github.User(), CanyieImpl {}
)
}
}
sealed class IconLink : RvItem() {

View File

@ -14,7 +14,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
@ -25,7 +25,7 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.section_home)
DownloadService.observeProgress(this, viewModel::onProgressUpdate)
DownloadEngine.observeProgress(this, viewModel::onProgressUpdate)
}
private fun checkTitle(text: TextView, icon: ImageView) {

View File

@ -7,6 +7,8 @@ import android.view.MenuItem
import android.widget.PopupMenu
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.ktx.reboot as systemReboot
@ -20,6 +22,11 @@ object RebootMenu {
R.id.action_reboot_download -> systemReboot("download")
R.id.action_reboot_edl -> systemReboot("edl")
R.id.action_reboot_recovery -> systemReboot("recovery")
R.id.action_reboot_safe_mode -> {
val status = !item.isChecked
item.isChecked = status
Config.bootloop = if (status) 2 else 0
}
else -> Unit
}
return true
@ -29,10 +36,16 @@ object RebootMenu {
val themeWrapper = ContextThemeWrapper(activity, R.style.Foundation_PopupMenu)
val menu = PopupMenu(themeWrapper, activity.findViewById(R.id.action_reboot))
activity.menuInflater.inflate(R.menu.menu_reboot, menu.menu)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true)
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
menu.setOnMenuItemClickListener(RebootMenu::reboot)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
}
if (Const.Version.isCanary()) {
menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
} else {
menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
}
return menu
}

View File

@ -37,8 +37,7 @@ import java.io.IOException
class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() {
val isRooted get() = Info.isRooted
val hideVbmeta = Info.vbmeta || Info.isSamsung || Info.isAB
val skipOptions = Info.isEmulator || (Info.isSAR && !Info.isFDE && hideVbmeta && Info.ramdisk)
val skipOptions = Info.isEmulator || (Info.isSAR && !Info.isFDE && Info.ramdisk)
val noSecondSlot = !isRooted || !Info.isAB || Info.isEmulator
@get:Bindable
@ -105,7 +104,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
step,
Config.keepVerity,
Config.keepEnc,
Config.patchVbmeta,
Config.recovery
))
}
@ -116,7 +114,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
step = it.step
Config.keepVerity = it.keepVerity
Config.keepEnc = it.keepEnc
Config.patchVbmeta = it.patchVbmeta
Config.recovery = it.recovery
}
}
@ -137,7 +134,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
val step: Int,
val keepVerity: Boolean,
val keepEnc: Boolean,
val patchVbmeta: Boolean,
val recovery: Boolean,
) : Parcelable

View File

@ -12,7 +12,6 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.activity
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
@ -228,25 +227,14 @@ object Zygisk : BaseSettingsItem.Toggle() {
get() = Config.zygisk
set(value) {
Config.zygisk = value
DenyList.isEnabled = value
DenyListConfig.isEnabled = value
notifyPropertyChanged(BR.description)
DenyList.notifyPropertyChanged(BR.description)
}
val mismatch get() = value != Info.isZygiskEnabled
}
object DenyList : BaseSettingsItem.Toggle() {
override val title = R.string.settings_denylist_title.asText()
override val description get() =
if (isEnabled) {
if (Zygisk.mismatch)
R.string.reboot_apply_change.asText()
else
R.string.settings_denylist_summary.asText()
} else {
R.string.settings_denylist_error.asText(R.string.zygisk.asText())
}
override val description get() = R.string.settings_denylist_summary.asText()
override var value = Config.denyList
set(value) {
@ -261,18 +249,11 @@ object DenyList : BaseSettingsItem.Toggle() {
}
}
}
override fun refresh() {
isEnabled = Zygisk.value
}
}
object DenyListConfig : BaseSettingsItem.Blank() {
override val title = R.string.settings_denylist_config_title.asText()
override val description = R.string.settings_denylist_config_summary.asText()
override fun refresh() {
isEnabled = Zygisk.value
}
}
// --- Superuser
@ -283,19 +264,15 @@ object Tapjack : BaseSettingsItem.Toggle() {
override var value by Config::suTapjack
}
object Biometrics : BaseSettingsItem.Toggle() {
override val title = R.string.settings_su_biometric_title.asText()
override var description = R.string.settings_su_biometric_summary.asText()
override var value
get() = ServiceLocator.biometrics.isEnabled
set(value) {
Config.suBiometric = value
}
object Authentication : BaseSettingsItem.Toggle() {
override val title = R.string.settings_su_auth_title.asText()
override var description = R.string.settings_su_auth_summary.asText()
override var value by Config::userAuth
override fun refresh() {
isEnabled = ServiceLocator.biometrics.isSupported
isEnabled = Info.isDeviceSecure
if (!isEnabled) {
description = R.string.no_biometric.asText()
description = R.string.settings_su_auth_insecure.asText()
}
}
}

View File

@ -18,7 +18,7 @@ import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.events.AddHomeIconEvent
import com.topjohnwu.magisk.events.BiometricEvent
import com.topjohnwu.magisk.events.AuthEvent
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch
@ -72,7 +72,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
if (Info.showSuperUser) {
list.addAll(listOf(
Superuser,
Tapjack, Biometrics, AccessMode, MultiuserMode, MountNamespaceMode,
Tapjack, Authentication, AccessMode, MultiuserMode, MountNamespaceMode,
AutomaticResponse, RequestTimeout, SUNotification
))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@ -92,7 +92,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
when (item) {
DownloadPath -> withExternalRW(andThen)
UpdateChecker -> withPostNotificationPermission(andThen)
Biometrics -> authenticate(andThen)
Authentication -> AuthEvent(andThen).publish()
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
SystemlessHosts -> createHosts()
@ -119,13 +119,6 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
}
}
private fun authenticate(callback: () -> Unit) {
BiometricEvent {
// allow the change on success
onSuccess { callback() }
}.publish()
}
private fun createHosts() {
Shell.cmd("add_hosts_module").submit {
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)

View File

@ -10,16 +10,20 @@ import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.getLabel
import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.*
import com.topjohnwu.magisk.databinding.MergeObservableList
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.diffList
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.dialog.SuperuserRevokeDialog
import com.topjohnwu.magisk.events.BiometricEvent
import com.topjohnwu.magisk.events.AuthEvent
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.view.TextItem
@ -113,10 +117,8 @@ class SuperuserViewModel(
}
}
if (ServiceLocator.biometrics.isEnabled) {
BiometricEvent {
onSuccess { updateState() }
}.publish()
if (Config.userAuth) {
AuthEvent { updateState() }.publish()
} else {
SuperuserRevokeDialog(item.title) { updateState() }.show()
}
@ -168,10 +170,8 @@ class SuperuserViewModel(
}
}
if (ServiceLocator.biometrics.isEnabled) {
BiometricEvent {
onSuccess { updateState() }
}.publish()
if (Config.userAuth) {
AuthEvent { updateState() }.publish()
} else {
updateState()
}

View File

@ -22,14 +22,13 @@ import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.di.ServiceLocator
import com.topjohnwu.magisk.core.ktx.getLabel
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.DENY
import com.topjohnwu.magisk.core.su.SuRequestHandler
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.events.BiometricEvent
import com.topjohnwu.magisk.events.AuthEvent
import com.topjohnwu.magisk.events.DieEvent
import com.topjohnwu.magisk.events.ShowUIEvent
import com.topjohnwu.magisk.utils.TextHolder
@ -77,12 +76,8 @@ class SuRequestViewModel(
fun grantPressed() {
cancelTimer()
if (ServiceLocator.biometrics.isEnabled) {
BiometricEvent {
onSuccess {
respond(ALLOW)
}
}.publish()
if (Config.userAuth) {
AuthEvent { respond(ALLOW) }.publish()
} else {
respond(ALLOW)
}

View File

@ -11,7 +11,7 @@ import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toIcon
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.core.download.DownloadEngine
import com.topjohnwu.magisk.core.download.Subject
import com.topjohnwu.magisk.core.ktx.getBitmap
import com.topjohnwu.magisk.core.ktx.selfLaunchIntent
@ -67,7 +67,7 @@ object Notifications {
fun updateAvailable() {
AppContext.apply {
val intent = DownloadService.getPendingIntent(this, Subject.App())
val intent = DownloadEngine.getPendingIntent(this, Subject.App())
val bitmap = getBitmap(R.drawable.ic_magisk_outline)
val builder = if (SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder(this, UPDATE_CHANNEL)

View File

@ -242,6 +242,14 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l_50" />
<include
item="@{DeveloperItem.Canyie.INSTANCE}"
layout="@layout/item_developer"
viewModel="@{viewModel}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l_50" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -108,15 +108,6 @@
android:text="@string/keep_force_encryption"
app:tint="?colorPrimary" />
<CheckBox
style="@style/WidgetFoundation.Checkbox"
gone="@{viewModel.hideVbmeta}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="@={Config.patchVbmeta}"
android:text="@string/patch_vbmeta"
app:tint="?colorPrimary" />
<CheckBox
style="@style/WidgetFoundation.Checkbox"
gone="@{Info.ramdisk}"

View File

@ -26,4 +26,9 @@
android:id="@+id/action_reboot_edl"
android:title="@string/reboot_edl" />
</menu>
<item
android:id="@+id/action_reboot_safe_mode"
android:checkable="true"
android:title="@string/reboot_safe_mode" />
</menu>

View File

@ -14,7 +14,7 @@ env_check() {
[ -f "$MAGISKBIN/magiskpolicy" ] || return 1
fi
if [ "$2" -ge 25210 ]; then
[ -b "$MAGISKTMP/.magisk/block/preinit" ] || return 2
[ -b "$MAGISKTMP/.magisk/device/preinit" ] || [ -b "$MAGISKTMP/.magisk/block/preinit" ] || return 2
fi
grep -xqF "MAGISK_VER='$1'" "$MAGISKBIN/util_functions.sh" || return 3
grep -xqF "MAGISK_VER_CODE=$2" "$MAGISKBIN/util_functions.sh" || return 3
@ -193,30 +193,26 @@ check_encryption() {
mount_partitions() {
[ "$(getprop ro.build.ab_update)" = "true" ] && SLOT=$(getprop ro.boot.slot_suffix)
# Check whether non rootfs root dir exists
SYSTEM_ROOT=false
grep ' / ' /proc/mounts | grep -qv 'rootfs' && SYSTEM_ROOT=true
SYSTEM_AS_ROOT=false
grep ' / ' /proc/mounts | grep -qv 'rootfs' && SYSTEM_AS_ROOT=true
LEGACYSAR=false
grep ' / ' /proc/mounts | grep -q '/dev/root' && LEGACYSAR=true
}
get_flags() {
KEEPVERITY=$SYSTEM_ROOT
KEEPVERITY=$SYSTEM_AS_ROOT
ISENCRYPTED=false
[ "$(getprop ro.crypto.state)" = "encrypted" ] && ISENCRYPTED=true
KEEPFORCEENCRYPT=$ISENCRYPTED
VBMETAEXIST=false
if [ -n "$(getprop ro.boot.vbmeta.device)" -o -n "$(getprop ro.boot.vbmeta.size)" ]; then
VBMETAEXIST=true
PATCHVBMETAFLAG=false
elif getprop ro.product.ab_ota_partitions | grep -wq vbmeta; then
VBMETAEXIST=true
fi
# Preset PATCHVBMETAFLAG to false in the non-root case
PATCHVBMETAFLAG=false
# Make sure RECOVERYMODE has value
[ -z $RECOVERYMODE ] && RECOVERYMODE=false
if grep ' / ' /proc/mounts | grep -q '/dev/root'; then
LEGACYSAR=true
PATCHVBMETAFLAG=false
else
LEGACYSAR=false
PATCHVBMETAFLAG=true
fi
[ -z $RECOVERYMODE ] && RECOVERYMODE=false
}
run_migrations() { return; }
@ -229,9 +225,9 @@ grep_prop() { return; }
app_init() {
mount_partitions
get_flags
RAMDISKEXIST=false
check_boot_ramdisk && RAMDISKEXIST=true
get_flags
run_migrations
SHA1=$(grep_prop SHA1 $MAGISKTMP/.magisk/config)
check_encryption

View File

@ -142,9 +142,6 @@
<string name="superuser_notification">إشعارات طلبات الروت</string>
<string name="settings_su_reauth_title">إعادة المصادقة بعد الترقية</string>
<string name="settings_su_reauth_summary">أعد مصادقة صلاحيات الروت بعد إجراء ترقيات للتطبيق</string>
<string name="settings_su_biometric_title">تفعيل التحقق بالبصمة</string>
<string name="settings_su_biometric_summary">تحقق إضافي بالبصمة لطلبات الروت </string>
<string name="no_biometric">جهازك غير مدعوم، أو أنك لم تضبّط البصماتَ بجهازك</string>
<string name="settings_customization">تخصيص</string>
<string name="multiuser_mode">نمط مستخدمين متعددين</string>

View File

@ -155,9 +155,6 @@
<string name="settings_su_reauth_summary">Vuelve pidir los permisos de superusuariu dempués d\'anovar les aplicaciones</string>
<string name="settings_su_tapjack_title">Proteición escontra\'l tapjacking</string>
<string name="settings_su_tapjack_summary">El diálogu de concesión de permisos de superusuariu nun respuende a la entrada mentanto lu torgue otra ventana o superposición</string>
<string name="settings_su_biometric_title">Autenticación biométrica</string>
<string name="settings_su_biometric_summary">Usa l\'autenticación biométrica pa permitir les solicitúes de superusuariu</string>
<string name="no_biometric">El preséu nun ye compatible o nun s\'activaron los axustes biométricos</string>
<string name="settings_customization">Personalización</string>
<string name="setting_add_shortcut_summary">Amiesta un atayu a la pantalla d\'aniciu en casu de que\'l nome y l\'iconu seyan difíciles de reconocer darréu d\'anubrir l\'aplicación</string>
<string name="settings_doh_title">DNS per HTTPS</string>

View File

@ -165,9 +165,6 @@
<string name="settings_su_reauth_summary">Tətbiqləri yüksəltdikdən sonra Superuser icazəsi istə</string>
<string name="settings_su_tapjack_title">Tapjack Qoruması</string>
<string name="settings_su_tapjack_summary">Superuser icazə pəncərəsi digər pəncərələr tərəfindən əngəlləndikdə heçbir girişə cavab verməyəcək</string>
<string name="settings_su_biometric_title">Biometrik İcazə</string>
<string name="settings_su_biometric_summary">Superuser istəkləri üçün biometrik icazədən istifadə et</string>
<string name="no_biometric">Cihaz ya dəstəklənmir ya da biometrik ayarlar yoxdur</string>
<string name="settings_customization">Özəlləşdirmə</string>
<string name="setting_add_shortcut_summary">Tətbiqi gizlətdikdən sonra tapmaq çətin olmasın deyə ana ekrana qısayol əlavə et</string>
<string name="settings_doh_title">HTTPS əvəzinə DNS</string>

View File

@ -142,9 +142,6 @@
<string name="settings_su_reauth_summary">Паўторна запытваць правы суперкарыстальніка пасля абнаўлення праграмы</string>
<string name="settings_su_tapjack_title">Уключыць абарону ад перахоплівання ўводу</string>
<string name="settings_su_tapjack_summary">Дыялог выдачы правоў суперкарыстальніка не будзе адказваць на ўвод, калі па-над ім знаходзяцца іншыя вокны</string>
<string name="settings_su_biometric_title">Уключыць біяметрычную аўтэнтыфікацыю</string>
<string name="settings_su_biometric_summary">Выкарыстанне біяметрычнай аўтэнтыфікацыі для запытаў правоў суперкарыстальніка</string>
<string name="no_biometric">Не падтрымліваецца прыладай альбо не ўключана ў наладах</string>
<string name="settings_customization">Персаналізацыя</string>
<string name="setting_add_shortcut_summary">Дадаць на хатні экран прыгожы цэтлік на той выпадак, калі пасля хавання праграмы будзе цяжка разглядзець значок і назву</string>
<string name="settings_doh_title">DNS паверх HTTPS</string>

View File

@ -167,9 +167,6 @@
<string name="settings_su_reauth_summary">Повторно запитване за достъп до правата на суперпотребителя след обновяване на приложения</string>
<string name="settings_su_tapjack_title">Предпазване от измамно докосване</string>
<string name="settings_su_tapjack_summary">Прозорецът за достъп до суперпотребителя няма да реагира, докато е покрит от друг прозорец или слой</string>
<string name="settings_su_biometric_title">Биометрично удостоверяване</string>
<string name="settings_su_biometric_summary">За получаване на достъп до суперпотребителя е необходимо биометрично удостоверяване</string>
<string name="no_biometric">Устройството не се поддръжа или липсват биометрични настройки</string>
<string name="settings_customization">Приспособяване</string>
<string name="setting_add_shortcut_summary">Добавя красив пряк път на началния екран ако името или текущата икона на скритото приложение са трудни за разпознаване</string>
<string name="settings_doh_title">DNS през HTTPS</string>

View File

@ -164,9 +164,6 @@
<string name="settings_su_reauth_summary">অ্যাপগুলি আপগ্রেড করার পরে আবার সুপার ইউজার অনুমতির জন্য জিজ্ঞাসা করুন</string>
<string name="settings_su_tapjack_title">ট্যাপজ্যাকিং সুরক্ষা</string>
<string name="settings_su_tapjack_summary">সুপার ইউজার প্রম্পট ডায়ালগ অন্য কোনো উইন্ডো বা ওভারলে দ্বারা অস্পষ্ট থাকাকালীন ইনপুটটিতে সাড়া দেবে না</string>
<string name="settings_su_biometric_title">বায়োমেট্রিক প্রমাণীকরণ</string>
<string name="settings_su_biometric_summary">সুপার ইউজার অনুরোধের অনুমতি দিতে বায়োমেট্রিক প্রমাণীকরণ ব্যবহার করুন</string>
<string name="no_biometric">অসমর্থিত ডিভাইস বা কোনো বায়োমেট্রিক সেটিংস সক্ষম করা নেই৷</string>
<string name="settings_customization">কাস্টমাইজেশন</string>
<string name="setting_add_shortcut_summary">অ্যাপটি লুকানোর পরে নাম এবং আইকন সনাক্ত করা কঠিন হলে হোম স্ক্রিনে একটি সুন্দর শর্টকাট যোগ করুন</string>
<string name="settings_doh_title">HTTPS এর উপর ডিএনএস</string>

View File

@ -152,9 +152,6 @@
<string name="settings_su_reauth_summary">Demanar permisos de superusuari novament si una aplicació és actualitzada o reinstal·lada</string>
<string name="settings_su_tapjack_title">Activa la protecció contra \'TapJacking\'</string>
<string name="settings_su_tapjack_summary">El diàleg per donar permisos de superusuari no respondrà mentre estigui ofuscat per alguna altra finestra o superposició</string>
<string name="settings_su_biometric_title">Activar autenticació biomètrica</string>
<string name="settings_su_biometric_summary">Utilitza l\'autenticació biomètrica per permetre sol·licituds de superusuari</string>
<string name="no_biometric">El dispositiu no suporta o no té establerta configuració biomètrica</string>
<string name="settings_customization">Personalització</string>
<string name="setting_add_shortcut_summary">Afegeix una bonica drecera a la pantalla d\'inici en cas que el nom i la icona siguin difícils de reconèixer després d\'amagar l\'aplicació.</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>

View File

@ -170,9 +170,6 @@
<string name="settings_su_reauth_summary">Opětovné ověření oprávnění SuperUser po aktualizaci aplikace.</string>
<string name="settings_su_tapjack_title">Povolit ochranu před TapJack</string>
<string name="settings_su_tapjack_summary">Okno dialogu SuperUser nebude reagovat na kliknutí v případě, že je zavřené nebo překryté jiným oknem</string>
<string name="settings_su_biometric_title">Povolit biometrické ověření</string>
<string name="settings_su_biometric_summary">Použije biometrické ověření pro povolení požadavků SuperUser</string>
<string name="no_biometric">Nepodporované zařízení, nebo není povolené biometrické ověření</string>
<string name="settings_customization">Přizpůsobit</string>
<string name="setting_add_shortcut_summary">Přidá odkaz na domovskou obrazovku v případě, že se po skrytí aplikace její název a ikona těžko rozpoznávají.</string>
<string name="settings_doh_title">DNS přes HTTPS</string>

View File

@ -8,14 +8,14 @@
<string name="install">Installieren</string>
<string name="section_home">Startseite</string>
<string name="section_theme">Themen</string>
<string name="denylist">Verweigerungsliste</string>
<string name="denylist">Ausnahmeliste</string>
<!--Home-->
<string name="no_connection">Keine Verbindung verfügbar</string>
<string name="app_changelog">Änderungen</string>
<string name="loading">Laden …</string>
<string name="update">Aktualisieren</string>
<string name="not_available">N/A</string>
<string name="not_available">Nicht verfügbar</string>
<string name="hide">Verstecken</string>
<string name="home_package">Paket</string>
<string name="home_app_title">App</string>
@ -88,6 +88,9 @@
<string name="logs_cleared">Protokoll erfolgreich gelöscht.</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Ziel-UID: %1$d</string>
<string name="target_pid">NS Target PID einbinden: %s</string>
<string name="selinux_context">SELinux Kontext: %s</string>
<string name="supp_group">Ergänzende Gruppe: %s</string>
<!--SafetyNet-->
@ -138,11 +141,11 @@
<string name="settings_update_custom">Benutzerdefiniert</string>
<string name="settings_update_custom_msg">Benutzerdefinierte URL einfügen</string>
<string name="settings_zygisk_summary">Teile von Magisk im Zygoten-Daemon ausführen</string>
<string name="settings_denylist_title">Verweigerungsliste erzwingen</string>
<string name="settings_denylist_summary">Bei Prozessen, die auf der Verweigerungsliste stehen, werden alle Magisk-Änderungen rückgängig gemacht.</string>
<string name="settings_denylist_title">Ausnahmeliste erzwingen</string>
<string name="settings_denylist_summary">Bei Prozessen, die auf der Ausnahmeliste stehen, werden alle Magisk-Änderungen rückgängig gemacht.</string>
<string name="settings_denylist_error">Für diese Funktion muss %1$s aktiviert sein</string>
<string name="settings_denylist_config_title">Verweigerungsliste konfigurieren</string>
<string name="settings_denylist_config_summary">Auswahl der Prozesse, die in die Verweigerungsliste aufgenommen werden sollen</string>
<string name="settings_denylist_config_title">Ausnahmeliste konfigurieren</string>
<string name="settings_denylist_config_summary">Auswahl der Prozesse, die in die Ausnahmeliste aufgenommen werden sollen</string>
<string name="settings_hosts_title">Systemlose Hosts-Datei</string>
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>
<string name="settings_hosts_toast">Systemloses Hosts-Modul hinzugefügt</string>
@ -167,9 +170,9 @@
<string name="settings_su_reauth_summary">Superuser-Berechtigungen nach App-Aktualisierung erneut authentifizieren</string>
<string name="settings_su_tapjack_title">Tapjacking-Schutz aktivieren</string>
<string name="settings_su_tapjack_summary">Das Dialogfeld der Superuser-Eingabeaufforderung reagiert nicht auf Eingaben, wenn es durch ein anderes Fenster oder Überlagerung verdeckt wird</string>
<string name="settings_su_biometric_title">Biometrische Authentifizierung aktivieren</string>
<string name="settings_su_biometric_summary">Biometrie verwenden, um Superuser-Anfragen zuzulassen</string>
<string name="no_biometric">Gerät unterstützt keine biometrischen Daten oder ist nicht mit diesen konfiguriert</string>
<string name="settings_su_auth_title">Benutzerauthentifizierung</string>
<string name="settings_su_auth_summary">Nachfrage nach Benutzerauthentifizierung bei Superuser-Anfragen</string>
<string name="settings_su_auth_insecure">Auf dem Gerät ist keine Authentifizierungsmethode konfiguriert</string>>
<string name="settings_customization">Personalisierung</string>
<string name="setting_add_shortcut_summary">Hinzufügen einer hübschen Startbildschirm-Verknüpfung, falls der Name und das Symbol nach dem Ausblenden der App schwer zu erkennen sind</string>
<string name="settings_doh_title">DNS über HTTPS</string>

View File

@ -165,9 +165,6 @@
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
<string name="settings_su_tapjack_title">Ενεργοποίηση προστασίας Tapjacking</string>
<string name="settings_su_tapjack_summary">Το παράθυρο διαλόγου προτροπής του υπερχρήστη δεν αποκρίνεται στην είσοδο ενώ κρύβεται από οποιοδήποτε άλλο παράθυρο</string>
<string name="settings_su_biometric_title">Ενεργοποίηση βιομετρικού ελέγχου ταυτότητας</string>
<string name="settings_su_biometric_summary">Χρησιμοποιήστε βιομετρικό έλεγχο ταυτότητας για να επιτρέψετε αιτήματα υπερχρηστών</string>
<string name="no_biometric">Δεν υποστηρίζεται η συσκευή ή δεν υπάρχει καμία βιομετρική ρύθμιση</string>
<string name="settings_customization">Προσαρμογή</string>
<string name="setting_add_shortcut_summary">Προσθέστε μια όμορφη συντόμευση στην αρχική οθόνη σε περίπτωση που το όνομα και το εικονίδιο είναι δύσκολο να αναγνωριστούν αφού κρύψετε την εφαρμογή</string>
<string name="settings_doh_title">DNS μέσω HTTPS</string>

View File

@ -19,7 +19,6 @@
<string name="hide">Ocultar</string>
<string name="home_package">Nombre de paquete:</string>
<string name="home_app_title">App</string>
<string name="home_notice_content">Descarga Magisk únicamente desde la página oficial de GitHub. ¡Las descargas desde fuentes desconocidas pueden ser maliciosas!</string>
<string name="home_support_title">Apóyanos</string>
<string name="home_follow_title">Síguenos</string>
@ -75,7 +74,6 @@
<string name="su_revoke_msg">Confirma para revocarle los privilegios de superusuario a %1$s</string>
<string name="toast">Mensaje emergente</string>
<string name="none">Ninguno</string>
<string name="superuser_toggle_notification">Notificaciones</string>
<string name="superuser_toggle_revoke">Revocar</string>
<string name="superuser_policy_none">Ninguna app ha solicitado privilegios de superusuario aún.</string>
@ -87,7 +85,10 @@
<string name="menuClearLog">Limpiar registro</string>
<string name="logs_cleared">Registros limpiados correctamente</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Target UID: %1$d</string>
<string name="target_uid">Objetivo UID: %1$d</string>
<string name="target_pid">Montar ns objetivo PID: %s</string>
<string name="selinux_context">Contexto SELinux: %s</string>
<string name="supp_group">Grupo suplementario: %s</string>
<!--SafetyNet/PlayIntegrity-->
@ -167,14 +168,13 @@
<string name="settings_su_reauth_summary">Las apps volverán a solicitar privilegios de superusuario tras actualizarse</string>
<string name="settings_su_tapjack_title">Protección contra tapjacking</string>
<string name="settings_su_tapjack_summary">No podrás interactuar con las solicitudes de superusuario mientras estén tapadas por cualquier otra ventana o superposición</string>
<string name="settings_su_biometric_title">Autenticación biométrica</string>
<string name="settings_su_biometric_summary">Usa tu rostro, iris o huella digital para conceder privilegios de superusuario</string>
<string name="no_biometric">El dispositivo no está soportado o no has configurado ningún dato biométrico</string>
<string name="settings_su_auth_title">Autenticación de usuario</string>
<string name="settings_su_auth_summary">Preguntar por la autenticación de usuario durante las peticiones de Superusuario</string>
<string name="settings_su_auth_insecure">No hay método de autenticación configurado en el dispositivo</string>
<string name="settings_customization">Personalización</string>
<string name="setting_add_shortcut_summary">Añade un atajo a la app con el ícono de Magisk a la pantalla de inicio en caso de que te resulte difícil reconocerla tras haberle cambiado el nombre y el ícono</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>
<string name="settings_doh_description">Proporciona una solución alternativa (workaround) contra el envenenamiento de DNS en algunos países</string>
<string name="multiuser_mode">Modo multiusuario</string>
<string name="settings_owner_only">Propietario del dispositivo</string>
<string name="settings_owner_manage">Administrado por el propietario del dispositivo</string>
@ -182,7 +182,6 @@
<string name="owner_only_summary">Solo el administrador tiene acceso root</string>
<string name="owner_manage_summary">Solo el administrador puede manipular y recibir solicitudes de superusuario</string>
<string name="user_independent_summary">Cada usuario tiene sus propias reglas y acceso al root</string>
<string name="mount_namespace_mode">Modo del namespace de montaje</string>
<string name="settings_ns_global">Namespace global</string>
<string name="settings_ns_requester">Namespace heredado</string>
@ -241,4 +240,4 @@
<string name="reboot_apply_change">Reinicia para aplicar los cambios</string>
<string name="restore_app_confirmation">Se restaurará la app oculta de vuelta a la original. ¿Quieres continuar?</string>
</resources>
</resources>

View File

@ -163,9 +163,6 @@
<string name="settings_su_reauth_summary">Pärast rakenduste uuendamist küsi superkasutaja luba uuesti</string>
<string name="settings_su_tapjack_title">Nupu varjamise kaitse</string>
<string name="settings_su_tapjack_summary">Superkasutaja taotluse hüpik ei reageeri vajutusele, kui seda katab mõni teine aken või ülekate</string>
<string name="settings_su_biometric_title">Luba biomeetriaga autentimine</string>
<string name="settings_su_biometric_summary">Kasuta superkasutaja taotluste kinnitamiseks biomeetrilist autentimist</string>
<string name="no_biometric">Mittetoetatud seade või ükski biomeetriaseadistus pole lubatud</string>
<string name="settings_customization">Kohandamine</string>
<string name="setting_add_shortcut_summary">Lisa avakuvale ilus otsetee juhuks, kui nime ja ikooni on pärast rakenduse peitmist raske tuvastada</string>
<string name="settings_doh_title">DNS üle HTTPSi</string>

View File

@ -138,9 +138,6 @@
<string name="superuser_notification">اعلان روت</string>
<string name="settings_su_reauth_title">احراز هویت دوباره پس از بروز رسانی</string>
<string name="settings_su_reauth_summary">تأیید کردندوباره مجوزهای روت پس از ارتقاء برنامه</string>
<string name="settings_su_biometric_title">فعال کردن احراز هویت بیومتریک</string>
<string name="settings_su_biometric_summary">استفاده کردن از احراز هویت بیومتریک برای تأیید درخواست های روت</string>
<string name="no_biometric">دستگاه پشتیبانی نمی شود یا تنظیمات بیومتریک فعال نیست</string>
<string name="settings_customization">سفارشی سازی</string>
<string name="setting_add_shortcut_summary">اضافه کردن یک میانبر زیبا را در صفحه اصلی در صورت شناسایی نام و نماد پس از پنهان کردن برنامه</string>

View File

@ -88,6 +88,9 @@
<string name="logs_cleared">Le journal a été effacé.</string>
<string name="pid">PID : %1$d</string>
<string name="target_uid">UID cible : %1$d</string>
<string name="target_pid">Montage ns PID cible: %s</string>
<string name="selinux_context">Contexte SELinux: %s</string>
<string name="supp_group">Groupe supplémentaire: %s</string>
<!--SafetyNet-->
@ -167,9 +170,9 @@
<string name="settings_su_reauth_summary">Redemander une authentification pour autoriser laccès en superutilisateur après une mise à jour de lapplication</string>
<string name="settings_su_tapjack_title">Activer la protection contre le détournement du tapotement</string>
<string name="settings_su_tapjack_summary">Le dialogue dinvite du superutilisateur ne répondra pas à la saisie lorsquil est masqué par une autre fenêtre ou une surcouche</string>
<string name="settings_su_biometric_title">Activer lauthentification biométrique</string>
<string name="settings_su_biometric_summary">Utiliser lauthentification biométrique pour autoriser les accès en superutilisateur</string>
<string name="no_biometric">Lappareil nest pas pris en charge ou alors aucun paramètre biométrique nest activé</string>
<string name="settings_su_auth_title">Authentification utilisateur</string>
<string name="settings_su_auth_summary">Demander lauthentification utilisateur lors de la requête super-utilisateur</string>
<string name="settings_su_auth_insecure">Aucun méthode dauthentification utilisateur nest configurée sur le périphérique</string>
<string name="settings_customization">Personnalisation</string>
<string name="setting_add_shortcut_summary">Ajouter un joli raccourci dans lécran daccueil au cas où le nom et licône seraient difficiles à reconnaître après avoir masqué lapplication</string>
<string name="settings_doh_title">DNS sur HTTPS</string>

View File

@ -165,9 +165,6 @@
<string name="settings_su_reauth_summary">एक ऐप अपडेट होने के बाद सुपरयूज़र अनुमति प्रमाणित करें</string>
<string name="settings_su_tapjack_title">टैपजैकिंग सुरक्षा</string>
<string name="settings_su_tapjack_summary">सुपरयुसर प्रॉम्प्ट डायलॉग किसी अन्य विंडो या ओवरले द्वारा अस्पष्ट होने पर इनपुट का जवाब नहीं देगा</string>
<string name="settings_su_biometric_title">बायोमेट्रिक प्रमाणीकरण सक्षम करें</string>
<string name="settings_su_biometric_summary">सुपरयूज़र अनुरोधों की अनुमति देने के लिए बायोमेट्रिक प्रमाणीकरण का उपयोग करें</string>
<string name="no_biometric">असमर्थित डिवाइस या कोई बायोमेट्रिक सेटिंग सक्षम नहीं हैं</string>
<string name="settings_customization">कस्टमाईजेशन</string>
<string name="setting_add_shortcut_summary">ऐप को छिपाने के बाद नाम और आइकन को पहचानना मुश्किल है, तो होम स्क्रीन में एक सुंदर शॉर्टकट जोड़ें</string>
<string name="settings_doh_title">HTTPS पर DNS</string>

View File

@ -142,9 +142,6 @@
<string name="superuser_notification">Superuser obavijest</string>
<string name="settings_su_reauth_title">Ponovno provjerite autentičnost nakon ažuriranja</string>
<string name="settings_su_reauth_summary">Ponovno provjerite autentičnost Superuser-a dopuštenja nakon ažuriranja aplikacije</string>
<string name="settings_su_biometric_title">Omogući biometrijsku provjeru autentičnosti</string>
<string name="settings_su_biometric_summary">Koristi biometrijsku provjeru autentičnosti da biste omogućili zahtjeve Superuser-a</string>
<string name="no_biometric">Nepodržani uređaj ili nije omogućena biometrijska provjera autentičnosti</string>
<string name="settings_customization">Prilagodba</string>
<string name="setting_add_shortcut_summary">Dodajte lijepi prečac na početni zaslon u slučaju da je naziv i ikonu teško prepoznati nakon skrivanja aplikacije</string>
<string name="settings_doh_title">DNS preko HTTPS-a</string>

View File

@ -165,9 +165,6 @@
<string name="settings_su_reauth_summary">Az appok frissítés után kérjenek ismét Superuser engedélyeket</string>
<string name="settings_su_tapjack_title">Tapjacking védelem</string>
<string name="settings_su_tapjack_summary">A Superuser kérés párbeszédpanel nem válaszol a bevitelre, ha más ablak vagy átfedés eltakarja</string>
<string name="settings_su_biometric_title">Biometrikus azonosítás</string>
<string name="settings_su_biometric_summary">Használjon biometrikus hitelesítést a Superuser kérések engedélyezéséhez</string>
<string name="no_biometric">Nem támogatott eszköz, vagy nincsenek engedélyezve a biometrikus beállítások</string>
<string name="settings_customization">Testreszabás</string>
<string name="setting_add_shortcut_summary">Adjon hozzá egy szép parancsikont a kezdőképernyőhöz arra az esetre, ha a nevet és az ikont nehéz felismerni az alkalmazás elrejtése után</string>
<string name="settings_doh_title">DNS HTTPS-en keresztül</string>

View File

@ -167,9 +167,6 @@
<string name="settings_su_reauth_summary">Autentikasi ulang izin akses superuser setelah aplikasi ditingkatkan</string>
<string name="settings_su_tapjack_title">Aktifkan perlindungan tapjacking</string>
<string name="settings_su_tapjack_summary">Dialog permintaan superuser tidak akan menanggapi masukan saat terhalangi oleh lapisan atau jendela lainnya</string>
<string name="settings_su_biometric_title">Aktifkan autentikasi biometrik</string>
<string name="settings_su_biometric_summary">Gunakan autentikasi biometrik untuk mengizinkan permintaan superuser</string>
<string name="no_biometric">Perangkat tidak mendukung atau setelan biometrik tidak diaktifkan</string>
<string name="settings_customization">Personalisasi</string>
<string name="setting_add_shortcut_summary">Tambahkan pintasan yang menarik pada layar utama seandainya nama dan ikon sulit untuk dikenali setelah menyembunyikan aplikasi</string>
<string name="settings_doh_title">DNS melalui HTTPS</string>

View File

@ -165,9 +165,9 @@
<string name="settings_su_reauth_summary">Richiedi nuovamente i permessi di root dopo l\'aggiornamento di un\'app</string>
<string name="settings_su_tapjack_title">Protezione anti-tapjacking</string>
<string name="settings_su_tapjack_summary">La schermata di richiesta dei permessi di root non risponderà al tocco mentre è oscurata da altre finestre o elementi in sovraimpressione</string>
<string name="settings_su_biometric_title">Autenticazione biometrica</string>
<string name="settings_su_biometric_summary">Utilizza l\'autenticazione biometrica per accettare le richieste di accesso root</string>
<string name="no_biometric">Il dispositivo non è supportato o le impostazioni biometriche sono disattivate</string>
<string name="settings_su_auth_title">Autenticazione utente</string>
<string name="settings_su_auth_summary">Richiedi l\'autenticazione dell\'utente per le richieste di accesso root</string>
<string name="settings_su_auth_insecure">Sul dispositivo non è configurato alcun metodo di autenticazione</string>
<string name="settings_customization">Personalizzazione</string>
<string name="setting_add_shortcut_summary">Aggiungi un collegamento alla schermata iniziale se il nome e l\'icona sono difficili da riconoscere dopo aver nascosto l\'app</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@ -8,6 +8,8 @@
<string name="install">התקנה</string>
<string name="section_home">בית</string>
<string name="section_theme">עיצוב</string>
<string name="denylist">רשימת דחייה</string>
<!--Home-->
<string name="no_connection">אין חיבור זמין</string>
@ -18,10 +20,11 @@
<string name="hide">הסתרה</string>
<string name="home_package">חבילה</string>
<string name="home_app_title">יישום</string>
<string name="home_notice_content">הורד את Magisk רק מהדף הרשמי של GitHub. קבצים ממקורות לא ידועים יכולים להיות זדוניים!</string>
<string name="home_support_title">תמיכה בנו</string>
<string name="home_notice_content">יש להוריד את Magisk רק מהדף הרשמי של GitHub. קבצים ממקורות לא ידועים יכולים להיות זדוניים!</string>
<string name="home_support_title">תמיכה בנו</string>
<string name="home_follow_title">עקבו אחרינו</string>
<string name="home_item_source">מקור</string>
<string name="home_support_content">Magisk היה ותמיד יהיה בעל קוד מקור פתוח. עם זאת אתה יכול להראות לנו שאכפת לך על ידי שליחת תרומה קטנה.</string>
<string name="home_support_content">Magisk היה ותמיד יהיה בעל קוד מקור פתוח. עם זאת באפשרותך להראות לנו שאכפת לך על ידי שליחת תרומה קטנה.</string>
<string name="home_installed_version">מותקנת</string>
<string name="home_latest_version">אחרונה</string>
<string name="invalid_update_channel">ערוץ עדכון לא חוקי</string>
@ -31,18 +34,19 @@
<!--Install-->
<string name="keep_force_encryption">שמירה על הצפנה בכח</string>
<string name="keep_dm_verity">שמירה על AVB 2.0/dm-verity</string>
<string name="patch_vbmeta">תיקון vbmeta בתמונת האתחול</string>
<string name="recovery_mode">מצב שחזור</string>
<string name="install_options_title">אפשרויות</string>
<string name="install_method_title">שיטה</string>
<string name="install_next">הבא</string>
<string name="install_start">צא לדרך</string>
<string name="manager_download_install">לחץ להורדה והתקנה</string>
<string name="manager_download_install">לחיצה להורדה והתקנה</string>
<string name="direct_install">התקנה ישירה (מומלץ)</string>
<string name="install_inactive_slot">התקן לחריץ לא פעיל (לאחר OTA)</string>
<string name="install_inactive_slot">התקנה לחריץ לא פעיל (לאחר OTA)</string>
<string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לחריץ הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string>
<string name="setup_title">התקנה נוספת</string>
<string name="select_patch_file">בחר והתקן קובץ</string>
<string name="patch_file_msg">בחר תמונה גולמית (*.img) או ODIN קובץ tar (*.tar)</string>
<string name="select_patch_file">בחירה והתקנת קובץ</string>
<string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN קובץ tar (*.tar)</string>
<string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string>
<string name="flash_screen_title">התקנה</string>
@ -52,7 +56,7 @@
<string name="deny">דחה</string>
<string name="prompt">מיידי</string>
<string name="grant">הענק</string>
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nדחה באם אינך בטוח!</string>
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nיש לדחות באי וודאות!</string>
<string name="forever">לצמיתות</string>
<string name="once">פעם אחת</string>
<string name="tenmin">10 דקות</string>
@ -76,13 +80,16 @@
<string name="superuser_policy_none">לא נתבקשו הרשאות משתמש על על ידי שום יישום</string>
<!--Logs-->
<string name="log_data_none">הינך ללא יומן רישום, נסה להשתמש ביישומים מותאמים יותר למשתמש העל שלך</string>
<string name="log_data_none">הינך ללא יומן רישום, יש לנסות להשתמש ביישומים מותאמים יותר למשתמש העל שלך</string>
<string name="log_data_magisk_none">יומני רישום Magisk ריקים, זה מוזר</string>
<string name="menuSaveLog">שמור יומן רישום</string>
<string name="menuClearLog">נקה יומן רישום כעת</string>
<string name="menuSaveLog">שמירת יומן רישום</string>
<string name="menuClearLog">ניקוי יומן רישום כעת</string>
<string name="logs_cleared">יומני רישום נוקו בהצלחה</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">יעד UID: %1$d</string>
<string name="target_pid">מציב ns יעד PID: %s</string>
<string name="selinux_context">הקשר SELinux: %s</string>
<string name="supp_group">קבוצה משלימה: %s</string>
<!--SafetyNet-->
@ -100,35 +107,47 @@
<string name="reboot_download">אתחול מצב הורדה</string>
<string name="reboot_edl">אתחול למצב EDL</string>
<string name="module_version_author">%1$s מאת %2$s</string>
<string name="module_state_remove">הסר</string>
<string name="module_state_restore">שחזר</string>
<string name="module_action_install_external">התקן מהאחסון</string>
<string name="module_state_remove">הסרה</string>
<string name="module_state_restore">שיחזור</string>
<string name="module_action_install_external">התקנה מהאחסון</string>
<string name="update_available">עדכונים זמינים</string>
<string name="suspend_text_riru">מודול מושעה כי %1$s מופעל</string>
<string name="suspend_text_zygisk">המודול הושעה כי %1$s אינו מופעל</string>
<string name="zygisk_module_unloaded">מודול Zygisk לא נטען עקב חוסר תאימות</string>
<string name="module_empty">לא מותקן מודול</string>
<string name="confirm_install">להתקין מודול %1$s?</string>
<string name="confirm_install_title">אישור התקנה</string>
<!--Settings -->
<string name="settings_dark_mode_title">מצב עיצוב</string>
<string name="settings_dark_mode_message">בחר מצב המתאים ביותר לסגנון שלך!</string>
<string name="settings_dark_mode_message">נא לבחור מצב המתאים ביותר לסגנון שלך!</string>
<string name="settings_dark_mode_light">תמיד בהיר</string>
<string name="settings_dark_mode_system">בהתאם למערכת</string>
<string name="settings_dark_mode_dark">תמיד כהה</string>
<string name="settings_download_path_title">נתיב הורדה</string>
<string name="settings_download_path_message">הקבצים ישמרו אל %1$s</string>
<string name="settings_hide_app_title">הסתר את היישום Magisk</string>
<string name="settings_hide_app_summary">התקן יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string>
<string name="settings_restore_app_title">שחזר את יישום Magisk</string>
<string name="settings_restore_app_summary">בטל את הסתרת היישום ושחזר אותה ל-APK המקורי</string>
<string name="language">שפה</string>
<string name="settings_hide_app_title">הסתרת היישום Magisk</string>
<string name="settings_hide_app_summary">התקנת יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string>
<string name="settings_restore_app_title">שיחזור היישום Magisk</string>
<string name="settings_restore_app_summary">יש לבטל את הסתרת היישום ולשחזור אותו ל-APK המקורי</string>
<string name="language">שפה</string>
<string name="system_default">(ברירת מחדל מערכת)</string>
<string name="settings_check_update_title">בדוק עדכונים</string>
<string name="settings_check_update_title">בדיקת עדכונים</string>
<string name="settings_check_update_summary">בדוק מעת לעת ברקע אם יש עדכונים</string>
<string name="settings_update_channel_title">ערוץ עדכון</string>
<string name="settings_update_stable">יציב</string>
<string name="settings_update_beta">בטא</string>
<string name="settings_update_custom">ערוץ מותאם אישית</string>
<string name="settings_update_custom_msg">הזן כתובת מותאמת אישית</string>
<string name="settings_update_custom">מותאם אישית</string>
<string name="settings_update_custom_msg">הזנת כתובת מותאמת אישית</string>
<string name="settings_zygisk_summary">הפעל חלקים של Magisk בדמון zygote</string>
<string name="settings_denylist_title">אכיפת רשימת דחייה</string>
<string name="settings_denylist_summary">כל השינויים של Magisk יוחזרו לתהליכים ברשימת הדחייה</string>
<string name="settings_denylist_error">תכונה זו דורשת הפעלה של %1$s</string>
<string name="settings_denylist_config_title">הגדרת רשימת הדחייה</string>
<string name="settings_denylist_config_summary">בחירת התהליכים שייכללו ברשימת הדחייה</string>
<string name="settings_hosts_title">מארחים חסרי מערכת</string>
<string name="settings_hosts_summary">מארחים חסרי מערכת תומכים ביישומים חוסמי פרסומות</string>
<string name="settings_hosts_toast">הוסף מודול מארחים חסרי מערכת</string>
<string name="settings_hosts_toast">הוספת מודול מארחים חסרי מערכת</string>
<string name="settings_app_name_hint">שם חדש</string>
<string name="settings_app_name_helper">היישום יארז מחדש בשם זה</string>
<string name="settings_app_name_error">פורמט לא חוקי</string>
@ -146,15 +165,15 @@
<string name="auto_response">תגובה אוטומטית</string>
<string name="request_timeout">בקש פסק זמן</string>
<string name="superuser_notification">התראות משתמש על</string>
<string name="settings_su_reauth_title">אמת מחדש לאחר שדרוג</string>
<string name="settings_su_reauth_title">אימות מחדש לאחר שדרוג</string>
<string name="settings_su_reauth_summary">אימות מחדש הרשאות של משתמש על לאחר שדרוג יישום</string>
<string name="settings_su_tapjack_title">הפעלת הגנת Tapjacking</string>
<string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או כיסוי אחר</string>
<string name="settings_su_biometric_title">אפשר אימות ביומטרי</string>
<string name="settings_su_biometric_summary">השתמש באימות ביומטרי כדי לאפשר בקשות לשימוש במשתמש על</string>
<string name="no_biometric">התקן לא נתמך או הגדרות ביומטריות אינן מאופשרות</string>
<string name="settings_su_auth_title">אימות משתמש</string>
<string name="settings_su_auth_summary">בקשת אימות משתמש במהלך בקשות משתמש על</string>
<string name="settings_su_auth_insecure">לא מוגדרת שיטת אימות בהתקן</string>
<string name="settings_customization">התאמה אישית</string>
<string name="setting_add_shortcut_summary">הוסף קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string>
<string name="setting_add_shortcut_summary">הוספת קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string>
<string name="settings_doh_title">DNS על HTTPS</string>
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
<string name="multiuser_mode">מצב מרובה משתמשים</string>
@ -175,13 +194,17 @@
<!--Notifications-->
<string name="update_channel">עדכוני Magisk</string>
<string name="progress_channel">התראות התקדמות</string>
<string name="updated_channel">העדכון הושלם</string>
<string name="download_complete">ההורדה הושלמה</string>
<string name="download_file_error">שגיאה בהורדת קובץ</string>
<string name="magisk_update_title">עדכון Magisk זמין!</string>
<string name="updated_title">עדכון Magisk</string>
<string name="updated_text">הקשה כדי לפתוח יישום</string>
<!--Toasts, Dialogs-->
<string name="yes">כן</string>
<string name="no">לא</string>
<string name="repo_install_title">מתקין %1$s %2$s(%3$d)</string>
<string name="download">הורדה</string>
<string name="reboot">הפעלה מחדש</string>
<string name="release_notes">הערות שחרור</string>
@ -189,7 +212,7 @@
<string name="done">בוצע!</string>
<string name="failure">נכשל</string>
<string name="hide_app_title">מסתיר את יישום Magisk…</string>
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
<string name="complete_uninstall">הסרה מלאה</string>
<string name="restore_img">שיחזור תמונות</string>
<string name="restore_img_msg">משחזר…</string>
@ -197,8 +220,9 @@
<string name="restore_fail">גיבוי מקורי אינו קיים!</string>
<string name="setup_fail">ההתקנה כשלה</string>
<string name="env_fix_title">דורש התקנה נוספת</string>
<string name="env_fix_msg">המכשיר שלך זקוק להתקנה נוספת כדי ש-Magisk יפעל כראוי. האם ברצונך להמשיך ולהפעיל מחדש?</string>
<string name="setup_msg">הגדרת סביבת ריצה…</string>
<string name="env_fix_msg">ההתקן שלך זקוק להתקנה נוספת כדי ש-Magisk יפעל כראוי. האם ברצונך להמשיך ולהפעיל מחדש?</string>
<string name="env_full_fix_msg">ההתקן שלך זקוק לצריבה מחדש של Magisk כדי לעבוד כראוי. נא להתקין מחדש את Magisk בתוך היישום, מצב השחזור אינו יכול לקבל מידע נכון על ההתקן.</string>
<string name="setup_msg">הגדרת סביבת ריצה…</string>
<string name="authenticate">אימות</string>
<string name="unsupport_magisk_title">גרסת Magisk אינה נתמכת</string>
<string name="unsupport_magisk_msg">גרסה זו של היישום אינה תומכת ביישום Magisk הנמוך מ- %1$s.\n\nהיישום יתנהג כאילו Magisk אינו מותקן,יש לשדרג את Magisk במהירות האפשריות.</string>
@ -208,8 +232,12 @@
<string name="unsupport_external_storage_msg">Magisk מותקן באחסון החיצוני. נא להעביר את היישום לאחסון הפנימי.</string>
<string name="unsupport_nonroot_stub_msg">היישום אינו יכול להמשיך לעבוד במצב הנסתר מכיוון שגישת השורש אבדה. נא לשחזר אותו חזרה ל-APK המקורי.</string>
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
<string name="external_rw_permission_denied">הענק הרשאת אחסון להפעלת פונקציונליות זו</string>
<string name="add_shortcut_title">הוסף קיצור דרך למסך הבית</string>
<string name="external_rw_permission_denied">הענת הרשאת אחסון להפעלת פונקציה זו</string>
<string name="post_notifications_denied">הענקת הרשאה להתראות כדי להפעיל פונקציה זו</string>
<string name="install_unknown_denied">יש לאפשר "התקנה ממקורות לא ידועים" בכדי להפעיל פונקציה זו</string>
<string name="add_shortcut_title">הוספת קיצור דרך למסך הבית</string>
<string name="add_shortcut_msg">לאחר הסתרת היישום הזה, השם והסמליל שלה עשויים להיות קשים לזיהוי. האם ברצונך להוסיף קיצור דרך יפה למסך הבית?</string>
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
<string name="reboot_apply_change">ייש להפעיל מחדש כדי להחיל שינויים</string>
<string name="restore_app_confirmation">פעולה זו תשחזר את היישום המוסתר חזרה ליישום המקורי. האם בוודאות ברצונך לעשות את זה?</string>
</resources>

View File

@ -165,9 +165,9 @@
<string name="settings_su_reauth_summary">アプリのアップグレード後にスーパーユーザー権限を再認証します</string>
<string name="settings_su_tapjack_title">タップジャッキング保護を有効にする</string>
<string name="settings_su_tapjack_summary">他のウィンドウやオーバーレイで表示されている間は、スーパーユーザー権限の要求ダイアログが入力に応答しないようにします</string>
<string name="settings_su_biometric_title">生体認証の有効化</string>
<string name="settings_su_biometric_summary">スーパーユーザー権限の要求時に生体認証を使用します</string>
<string name="no_biometric">生体認証に対応していないか、有効化されていません</string>
<string name="settings_su_auth_title">ユーザー認証</string>
<string name="settings_su_auth_summary">スーパーユーザー権限の要求でユーザー認証を行ないます</string>
<string name="settings_su_auth_insecure">端末の認証方法が設定されていません</string>
<string name="settings_customization">カスタマイズ</string>
<string name="setting_add_shortcut_summary">アプリを隠した後に見つけられなくなったときは、ここでホーム画面にショートカットを追加できます</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@ -152,9 +152,6 @@
<string name="settings_su_reauth_summary">სუპერმომხმარებლის ნებართვის რეაუტენთიფიკაცია აპის განახლების შემდეგ</string>
<string name="settings_su_tapjack_title">Tapjacking-სგან თავის დაცვა</string> <!-- TODO: tapjacking has no direct translation; must make something up later -->
<string name="settings_su_tapjack_summary">superuser-ის დიალოგის ღილაკებზე დაჭერა არ იქნება შესაძლებელი თუ სხვა აპი არის მასზე გადახურული</string>
<string name="settings_su_biometric_title">ბიომეტრიკული აუტენთიფიკაციის ჩართვა</string>
<string name="settings_su_biometric_summary">ბიომეტრიკული აუტენთიფიკაციის გამოყენება სუპერმომხმარებლის ნებართვის გასაცემად</string>
<string name="no_biometric">შეუთავსებელი მოწყობილობა ან არასწორად დაყენებული ბიომეტრიკული პარამეტრები</string>
<string name="settings_customization">პერსონალიზაცია</string>
<string name="setting_add_shortcut_summary">ლამაზი ხატულის დამატება საწყისს ეკრანზე, იმ შემთხვევაში თუ აპის ამოცნობა არის რთული დამალვის შემდეგ</string>
<string name="settings_doh_title">DNS HTTPS-ზე</string>

View File

@ -163,9 +163,6 @@
<string name="settings_su_reauth_summary">앱이 업데이트되면 권한 승인 요청을 다시 합니다.</string>
<string name="settings_su_tapjack_title">탭재킹 보호 활성화</string>
<string name="settings_su_tapjack_summary">슈퍼유저 프롬프트가 다른 창이나 오버레이로 가려지는 동안의 입력을 무시합니다.</string>
<string name="settings_su_biometric_title">생체 인증 활성화</string>
<string name="settings_su_biometric_summary">슈퍼유저 요청 허용에 생체 인증을 사용합니다.</string>
<string name="no_biometric">지원되지 않는 기기이거나 등록된 생체 정보가 없습니다.</string>
<string name="settings_customization">커스터마이즈</string>
<string name="setting_add_shortcut_summary">앱을 숨긴 후 아이콘과 이름을 알아보기 힘들 경우를 위해 알아보기 쉬운 바로가기를 홈 화면에 추가합니다.</string>
<string name="settings_doh_title">DNS over HTTPS</string>
@ -185,7 +182,7 @@
<string name="settings_ns_isolate">격리된 네임스페이스</string>
<string name="global_summary">모든 루트 세션이 전역 마운트 네임스페이스를 사용합니다.</string>
<string name="requester_summary">루트 세션은 요청자의 네임스페이스를 상속합니다.</string>
<string name="isolate_summary">각각의 루트 세션은 자신만의 독립된 네임스페이를 사용합니다.</string>
<string name="isolate_summary">각각의 루트 세션은 자신만의 독립된 네임스페이를 사용합니다.</string>
<!--Notifications-->
<string name="update_channel">Magisk 업데이트</string>

View File

@ -167,9 +167,6 @@
<string name="settings_su_reauth_summary">Iš naujo prašyti supernaudotojo teisių po programėlių naujinimo</string>
<string name="settings_su_tapjack_title">Bakstelėjimų perėmimo apsauga</string>
<string name="settings_su_tapjack_summary">Supernaudotojo užklausos langas bus neaktyvus, kol jis yra užstotas kito lango</string>
<string name="settings_su_biometric_title">Biometrinis autentifikavimas</string>
<string name="settings_su_biometric_summary">Naudoti biometrinį autentifikavimą supernaudotojo užklausų patvirtinimui</string>
<string name="no_biometric">Nepalaikomas įrenginys arba biometriniai nustatymai neįjungti</string>
<string name="settings_customization">Tinkinimas</string>
<string name="setting_add_shortcut_summary">Pridėti nuorodą į pagrindinį ekraną, jei po programėlės paslėpimo yra sunku atpažinti jos pavadinimą ir piktogramą</string>
<string name="settings_doh_title">DNS virš HTTPS</string>

View File

@ -22,7 +22,7 @@
<string name="home_notice_content">ഔദ്യോഗിക ഗിറ്റ്ഹബ് പേജിൽ നിന്ന് മാത്രം മജിസ്‌ക് ഡൗൺലോഡ് ചെയ്യുക. അജ്ഞാത ഉറവിടങ്ങളിൽ നിന്നുള്ള ഫയലുകൾ ക്ഷുദ്രകരമാകാം!</string>
<string name="home_support_title">ഞങ്ങളെ തുണയ്‌ക്കുക</string>
<string name="home_follow_title">ഞങ്ങളെ പിന്തുടരുക</string>
<string name="home_follow_title">ഞങ്ങളെ ഫോളോ ചെയ്യുക</string>
<string name="home_item_source">സോഴ്സ്</string>
<string name="home_support_content">മജിസ്‌ക് എല്ലായ്പ്പോഴും സ്വതന്ത്രവും ഓപ്പൺ സോഴ്‌സും ആയിരിക്കും. എന്നിരുന്നാലും, ഒരു സംഭാവന നൽകിക്കൊണ്ട് നിങ്ങൾ പിന്തുണയ്ക്കുന്നുവെന്ന് ഞങ്ങളെ കാണിക്കാനാകും.</string>
<string name="home_installed_version">ഇൻസ്റ്റാൾ ചെയ്ത പതിപ്പ്</string>
@ -58,7 +58,7 @@
<string name="grant">അനുവദിക്കുക</string>
<string name="su_warning">നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് പൂർണ്ണ ആക്‌സസ് നൽകും.\nനിങ്ങൾക്ക് ഉറപ്പില്ലെങ്കിൽ നിരസിക്കുക!</string>
<string name="forever">എന്നേക്കും</string>
<string name="once">ഒരിക്കല്</string>
<string name="once">ഒരിക്ക</string>
<string name="tenmin">10 മിനിറ്റ്</string>
<string name="twentymin">20 മിനിറ്റ്</string>
<string name="thirtymin">30 മിനിറ്റ്</string>
@ -133,8 +133,8 @@
<string name="settings_update_channel_title">അപ്ഡേറ്റിനുള്ള ചാനൽ</string>
<string name="settings_update_stable">സ്റ്റേബിൾ</string>
<string name="settings_update_beta">ബീറ്റ</string>
<string name="settings_update_custom">കസ്റ്റമ്</string>
<string name="settings_update_custom_msg">കസ്റ്റമ് ചാനലിന്റെ URL ചേർക്കുക</string>
<string name="settings_update_custom">കസ്റ്റ</string>
<string name="settings_update_custom_msg">കസ്റ്റ ചാനലിന്റെ URL ചേർക്കുക</string>
<string name="settings_zygisk_summary">സൈഗോട്ട് ഡെമണിൽ മജിസ്കിന്റെ ഭാഗങ്ങൾ പ്രവർത്തിപ്പിക്കുക</string>
<string name="settings_denylist_title">നിഷിദ്ധ പട്ടിക പ്രാബല്യത്തിലാകുക</string>
<string name="settings_denylist_summary">നിഷിദ്ധ പട്ടികയിലെ പ്രോസസ്സുകൾക്കായി എല്ലാ മജിസ്‌ക് പരിഷ്‌ക്കരണങ്ങളും പഴയപടിയാക്കും</string>
@ -165,13 +165,10 @@
<string name="settings_su_reauth_summary">ആപ്പുകൾ അപ്‌ഗ്രേഡ് ചെയ്‌തതിന് ശേഷം സൂപ്പർയൂസർ അനുമതികൾക്കായി വീണ്ടും ആവശ്യപ്പെടുക</string>
<string name="settings_su_tapjack_title">ടാപ്പ്ജാക്കിംഗ് സംരക്ഷണം</string>
<string name="settings_su_tapjack_summary">സൂപ്പർയൂസർ പ്രോംപ്റ്റ് ഡയലോഗ് മറ്റേതെങ്കിലും വിൻഡോയോ ഓവർലേയോ മറയ്ക്കുമ്പോൾ ഇൻപുട്ടിനോട് പ്രതികരിക്കില്</string>
<string name="settings_su_biometric_title">ബയോമെട്രിക് പ്രാമാണീകരണം</string>
<string name="settings_su_biometric_summary">സൂപ്പർയൂസർ അഭ്യർത്ഥനകൾ അനുവദിക്കുന്നതിന് ബയോമെട്രിക് പ്രാമാണീകരണം ഉപയോഗിക്കുക</string>
<string name="settings_customization">Customization</string>
<string name="no_biometric">പിന്തുണയ്‌ക്കാത്ത ഉപകരണം അല്ലെങ്കിൽ ബയോമെട്രിക് ഒന്നും പ്രവർത്തനക്ഷമമാക്കിയിട്ടില്ല</string>
<string name="settings_customization">കസ്റ്റമയിസേഷൻ</string>
<string name="setting_add_shortcut_summary">ആപ്പ് മറച്ചതിന് ശേഷം പേരും ഐക്കണും തിരിച്ചറിയാൻ പ്രയാസമാണെങ്കിൽ ഹോം സ്‌ക്രീനിലേക്ക് മനോഹരമായ ഒരു ഷോർട്ട്ക്കട് ചേർക്കുക</string>
<string name="settings_doh_title">DNS ഓവർ HTTPS</string>
<string name="settings_doh_description">ചില രാജ്യങ്ങളി DNS പോയ്സണിങിന് പരിഹാരം</string>
<string name="settings_doh_description">ചില രാജ്യങ്ങളിലെ DNS പോയ്സണിങിന് പരിഹാരം</string>
<string name="multiuser_mode">മൾട്ടിയൂസർ മോഡ്</string>
<string name="settings_owner_only">ഉപകരണ ഉടമ മാത്രം</string>
@ -232,7 +229,7 @@
<string name="external_rw_permission_denied">ഈ പ്രവർത്തനം പ്രവർത്തനക്ഷമമാക്കാൻ സ്റ്റോറജ് ​​അനുമതി നൽകുക</string>
<string name="post_notifications_denied">ഈ പ്രവർത്തനം പ്രവർത്തനക്ഷമമാക്കാൻ അറിയിപ്പ്‌ അനുമതി നൽകുക</string>
<string name="install_unknown_denied">ഈ പ്രവർത്തനം പ്രവർത്തനക്ഷമമാക്കാൻ "install unknown apps" അനുവദിക്കുക</string>
<string name="add_shortcut_title">ഹോം സ്ക്രീനിലേക്ക് ഷോർറ്റ്കറ്റ് ചേർക്കുക</string>
<string name="add_shortcut_title">ഹോം സ്ക്രീനിലേക്ക് ഷോർട്ട്കട്ട് ചേർക്കുക</string>
<string name="add_shortcut_msg">ഈ ആപ്പ് മറച്ചതിന് ശേഷം, അതിന്റെ പേരും ഐക്കണും തിരിച്ചറിയാൻ ബുദ്ധിമുട്ടായേക്കാം. ഹോം സ്‌ക്രീനിലേക്ക് മനോഹരമായ ഒരു ഷോർറ്റ്കറ്റ ചേർക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?</string>
<string name="app_not_found">ഈ പ്രവർത്തനം കൈകാര്യം ചെയ്യാൻ ഒരു ആപ്പും കണ്ടെത്തിയില്ല</string>
<string name="reboot_apply_change">മാറ്റങ്ങൾ പ്രയോഗിക്കാൻ റീബൂട്ട് ചെയ്യുക</string>

View File

@ -152,9 +152,6 @@
<string name="settings_su_reauth_summary">Identitetsbekreft superbrukertilganger etter programoppgraderinger</string>
<string name="settings_su_tapjack_title">Trykkstjelingsbeskyttelse</string>
<string name="settings_su_tapjack_summary">Superbrukings-forespørselsdialogen vil ikke svare på inndata mens den dekkes av et annet vindu eller lag</string>
<string name="settings_su_biometric_title">Biometrisk identitetsbekreftelse</string>
<string name="settings_su_biometric_summary">Bruk biometrisk identitetsbekreftelse for å tillate superbruker-forespørsler</string>
<string name="no_biometric">Ustøttet enhet, eller mangel på biometrisk oppsett</string>
<string name="settings_customization">Tilpasning</string>
<string name="setting_add_shortcut_summary">Legg til fin snarvei på hjemmeskjermen i fall navnet og ikonet er vanskelig å gjenkjenne etter skjuling av programmet</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@ -141,9 +141,6 @@
<string name="superuser_notification">Superusermelding</string>
<string name="settings_su_reauth_title">Opnieuw goedkeuren na update</string>
<string name="settings_su_reauth_summary">Superuserrechten opnieuw goedkeuren na app-updates.</string>
<string name="settings_su_biometric_title">Biometrische authenticatie gebruiken</string>
<string name="settings_su_biometric_summary">Gebruik biometrische authenticatie om superuserverzoeken goed te keuren.</string>
<string name="no_biometric">Niet-ondersteund apparaat of geen biometrische authenticatie ingesteld</string>
<string name="settings_customization">Aanpassingen</string>
<string name="multiuser_mode">Meerdere gebruikers</string>

View File

@ -143,9 +143,6 @@
<string name="superuser_notification">ਸੁਪਰਯੂਜ਼ਰ ਸੂਚਨਾ</string>
<string name="settings_su_reauth_title">ਅਪਗ੍ਰੇਡ ਹੋਣ ਤੋਂ ਬਾਅਦ ਪ੍ਰਮਾਣਿਕਤਾ</string>
<string name="settings_su_reauth_summary">ਇੱਕ ਐਪ ਦੇ ਅਪਡੇਟ ਹੋਣ ਤੋਂ ਬਾਅਦ ਸੁਪਰਯੂਜ਼ਰ ਆਗਿਆ ਪ੍ਰਮਾਣਿਤ ਕਰੋ</string>
<string name="settings_su_biometric_title">ਬਾਇਓਮੈਟ੍ਰਿਕ ਪ੍ਰਮਾਣਿਕਤਾ ਦਾ ਯੋਗ ਕਰੋ</string>
<string name="settings_su_biometric_summary">ਸੁਪਰਯੂਜ਼ਰ ਦੀ ਆਗਿਆ ਦੇਣ ਲਈ ਬਾਇਓਮੈਟ੍ਰਿਕ ਪ੍ਰਮਾਣੀਕਰਣ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>
<string name="no_biometric">ਅਸਮਰਥਿਤ ਡਿਵਾਈਸ ਜਾਂ ਕੋਈ ਬਾਇਓਮੈਟ੍ਰਿਕ ਸੈਟਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ</string>
<string name="settings_customization">ਕਸਟਮਾਈਜੇਸ਼ਨ</string>
<string name="setting_add_shortcut_summary">ਐਪ ਨੂੰ ਲੁਕਾਉਣ ਤੋਂ ਬਾਅਦ ਨਾਮ ਅਤੇ ਆਈਕਾਨ ਨੂੰ ਪਛਾਣਨਾ ਮੁਸ਼ਕਲ ਹੈ, ਤਾਂ ਹੋਮ ਸਕ੍ਰੀਨ ਵਿਚ ਇਕ ਸੁੰਦਰ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰੋ</string>
<string name="settings_doh_title">DNS ਉੱਤੇ HTTPS</string>

View File

@ -8,7 +8,7 @@
<string name="install">Instaluj</string>
<string name="section_home">Strona główna</string>
<string name="section_theme">Motywy</string>
<string name="denylist">Lista odmów</string>
<string name="denylist">Lista odmów (DenyList)</string>
<!--Home-->
<string name="no_connection">Połączenie niedostępne</string>
@ -28,8 +28,8 @@
<string name="home_installed_version">Zainstalowany</string>
<string name="home_latest_version">Ostatni</string>
<string name="invalid_update_channel">Nieprawidłowy kanał aktualizacji</string>
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
<string name="uninstall_magisk_msg">Wszystkie moduły zostaną wyłączone/usunięte!\nRoot zostanie usunięty!\nTwoje dane mogą zostać potencjalnie zaszyfrowane, jeśli jeszcze nie są!</string>
<string name="uninstall_magisk_title">Odinstalowywanie Magisk</string>
<string name="uninstall_magisk_msg">Wszystkie moduły zostaną wyłączone/usunięte!\nRoot zostanie usunięty!\nWszelka wewnętrzna pamięć niezaszyfrowana w związku z użytkowaniem Magisk zostanie ponownie zaszyfrowana!</string>
<!--Install-->
<string name="keep_force_encryption">Zachowaj force encryption (wymuszenie szyfrowania)</string>
@ -40,23 +40,23 @@
<string name="install_method_title">Metoda</string>
<string name="install_next">Dalej</string>
<string name="install_start">Zaczynajmy</string>
<string name="manager_download_install">Naciśnij, aby pobrać i zainstalować</string>
<string name="manager_download_install">Kliknij, aby pobrać i zainstalować</string>
<string name="direct_install">Bezpośrednia instalacja (zalecana)</string>
<string name="install_inactive_slot">Zainstaluj w nieaktywnym gnieździe (po OTA)</string>
<string name="install_inactive_slot_msg">Po restarcie twoje urządzenie zostanie ZMUSZONE do rozruchu z aktualnie nieaktywnego gniazda!\nUżyj tej opcji wyłącznie po ukończeniu aktualizacji OTA.\nKontynuować?</string>
<string name="install_inactive_slot">Zainstaluj w nieaktywnym slocie (po OTA)</string>
<string name="install_inactive_slot_msg">Po ponownym uruchomieniu twoje urządzenie zostanie ZMUSZONE do rozruchu z aktualnie nieaktywnego slotu!\nUżywaj tej opcji tylko po ukończeniu aktualizacji OTA.\nKontynuować?</string>
<string name="setup_title">Dodatkowa konfiguracja</string>
<string name="select_patch_file">Wybierz i załataj plik</string>
<string name="patch_file_msg">Wybierz obraz raw (*.img) lub plik tar ODIN (*.tar)</string>
<string name="patch_file_msg">Wybierz obraz raw (*.img) lub plik tar ODIN (*.tar) lub payload.bin (*.bin)</string>
<string name="reboot_delay_toast">Ponowne uruchomienie za 5 sekund…</string>
<string name="flash_screen_title">Instalacja</string>
<!--Superuser-->
<string name="su_request_title">Żądanie dostępu do Superusera</string>
<string name="touch_filtered_warning">Ponieważ zapytanie o Superuser aplikacji jest przysłonięte, Magisk nie może zweryfikować twojej odpowiedzi.</string>
<string name="touch_filtered_warning">Ponieważ aplikacja zasłania żądanie o Superusera, Magisk nie może zweryfikować twojej odpowiedzi</string>
<string name="deny">Odmów</string>
<string name="prompt">Zapytaj</string>
<string name="grant">Zezwól</string>
<string name="su_warning">Udziela pełnego dostępu do urządzenia.\nOdmów jeśli nie jesteś pewien!</string>
<string name="su_warning">Udziela pełnego dostępu do urządzenia.\nOdmów, jeżeli nie jesteś pewien!</string>
<string name="forever">Zawsze</string>
<string name="once">Raz</string>
<string name="tenmin">10 min</string>
@ -66,28 +66,31 @@
<string name="su_allow_toast">%1$s otrzymał uprawnienia Superusera</string>
<string name="su_deny_toast">%1$s odmówiono uprawnień Superusera</string>
<string name="su_snack_grant">Przyznano uprawnienia Superusera dla %1$s</string>
<string name="su_snack_deny">Odmówiono uprawnień Superusera dla %1$s</string>
<string name="su_snack_deny">Unieważniono uprawnienia Superusera dla %1$s</string>
<string name="su_snack_notif_on">Włączono powiadomienia dla %1$s</string>
<string name="su_snack_notif_off">Wyłączono powiadomienia dla %1$s</string>
<string name="su_snack_log_on">Włączono logowanie dla %1$s</string>
<string name="su_snack_log_off">Wyłączono logowanie dla %1$s</string>
<string name="su_revoke_title">Odwołać?</string>
<string name="su_revoke_msg">Potwierdzasz odwołanie uprawnień dla %1$s?</string>
<string name="su_revoke_title">Unieważnić?</string>
<string name="su_revoke_msg">Potwierdź, aby unieważnić uprawnienia Superusera dla %1$s</string>
<string name="toast">Wyskakujące powiadomienie</string>
<string name="none">Brak</string>
<string name="superuser_toggle_notification">Powiadomienia</string>
<string name="superuser_toggle_revoke">Odwołaj</string>
<string name="superuser_toggle_revoke">Unieważnij</string>
<string name="superuser_policy_none">Żadna aplikacja nie poprosiła jeszcze o uprawnienia Superusera.</string>
<!--Logs-->
<string name="log_data_none">Logi są puste, spróbuj użyć aplikacji wymagających roota.</string>
<string name="log_data_magisk_none">Logi Magisk są puste, to jest dziwne.</string>
<string name="log_data_none">Nie masz żadnych logów, spróbuj użyć aplikacji wymagających roota</string>
<string name="log_data_magisk_none">Logi Magisk są puste, to jest dziwne</string>
<string name="menuSaveLog">Zapisz log</string>
<string name="menuClearLog">Wyczyść log</string>
<string name="logs_cleared">Log został pomyślnie wyczyszczony.</string>
<string name="logs_cleared">Log został pomyślnie wyczyszczony</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Docelowy UID: %1$d</string>
<string name="target_pid">Docelowy PID p.n. montowania: %s</string>
<string name="selinux_context">Kontekst SELinux: %s</string>
<string name="supp_group">Grupa uzupełniająca: %s</string>
<!--SafetyNet-->
@ -98,7 +101,7 @@
<string name="hide_search">Szukaj</string>
<!--Module -->
<string name="no_info_provided">(Nie umieszczono informacji)</string>
<string name="no_info_provided">(Brak informacji)</string>
<string name="reboot_userspace">Miękki reboot</string>
<string name="reboot_recovery">Reboot do trybu Recovery</string>
<string name="reboot_bootloader">Reboot do trybu Bootloader</string>
@ -109,11 +112,11 @@
<string name="module_state_restore">Przywróć</string>
<string name="module_action_install_external">Zainstaluj z pamięci</string>
<string name="update_available">Dostępna aktualizacja</string>
<string name="suspend_text_riru">Moduł uśpiony ponieważ %1$s jest włączony</string>
<string name="suspend_text_zygisk">Moduł uśpiony ponieważ %1$s jest wyłączony</string>
<string name="zygisk_module_unloaded">Moduł Zygisk nie załadowany ze względu na niekompatybilność</string>
<string name="module_empty">Żaden moduł nie jest zainstalowany</string>
<string name="confirm_install">Zainstaloać moduł %1$s?</string>
<string name="suspend_text_riru">Moduł jest zawieszony, ponieważ %1$s jest włączony</string>
<string name="suspend_text_zygisk">Moduł jest zawieszony, ponieważ %1$s nie jest włączony</string>
<string name="zygisk_module_unloaded">Moduł Zygisk nie został załadowany z powodu niekompatybilności</string>
<string name="module_empty">Brak zainstalowanych modułów</string>
<string name="confirm_install">Zainstalować moduł %1$s?</string>
<string name="confirm_install_title">Potwierdzenie instalacji</string>
<!--Settings -->
@ -125,7 +128,7 @@
<string name="settings_download_path_title">Ścieżka pobierania plików</string>
<string name="settings_download_path_message">Pliki zostaną zapisane do %1$s</string>
<string name="settings_hide_app_title">Ukryj aplikację Magisk</string>
<string name="settings_hide_app_summary">Zainstaluj aplikację z losowym ID pakietu i własną etykietą.</string>
<string name="settings_hide_app_summary">Zainstaluj aplikację proxy z losowym ID pakietu i własną etykietą</string>
<string name="settings_restore_app_title">Przywróć aplikację Magisk</string>
<string name="settings_restore_app_summary">Przestań ukrywać aplikację i przywróć oryginalny plik APK</string>
<string name="language">Język</string>
@ -137,18 +140,18 @@
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Własny kanał</string>
<string name="settings_update_custom_msg">Wprowadź adres URL własnego kanału</string>
<string name="settings_zygisk_summary">Uruchom cześć Magiska w zygocie Demona</string>
<string name="settings_denylist_title">Wymuś Listę Odmów</string>
<string name="settings_denylist_summary">Procesy z Listy Odmów będą miały wszystkie modyfikacje Magisk cofnięte</string>
<string name="settings_denylist_error">Ta funkcja wymaga aby %1$s było włączone</string>
<string name="settings_denylist_config_title">Ustaw Listę Odmów</string>
<string name="settings_denylist_config_summary">Wybierz proces który ma zostać zawarty w Liście Odmów</string>
<string name="settings_zygisk_summary">Uruchom część Magisk w demonie zygote</string>
<string name="settings_denylist_title">Egzekwowanie listy odmów (DenyList)</string>
<string name="settings_denylist_summary">Procesy znajdujące się na liście odmów (DenyList) będą miały cofnięte wszystkie modyfikacje Magisk</string>
<string name="settings_denylist_error">Ta funkcja wymaga, aby %1$s było włączone</string>
<string name="settings_denylist_config_title">Konfiguracja listy odmów (DenyList)</string>
<string name="settings_denylist_config_summary">Wybierz procesy, które mają się znajdować na liście odmów (DenyList)</string>
<string name="settings_hosts_title">Hosty Systemless</string>
<string name="settings_hosts_summary">Wsparcie hostów Systemless dla aplikacji typu Adblock</string>
<string name="settings_hosts_summary">Wsparcie hostów Systemless dla aplikacji blokujących reklamy</string>
<string name="settings_hosts_toast">Dodano moduł hostów Systemless</string>
<string name="settings_app_name_hint">Nowa nazwa</string>
<string name="settings_app_name_helper">Aplikacja zostanie przepakowana do tej nazwy</string>
<string name="settings_app_name_error">Błędny format</string>
<string name="settings_app_name_helper">Aplikacja zostanie przepakowana z tą nazwą</string>
<string name="settings_app_name_error">Nieprawidłowy format</string>
<string name="settings_su_app_adb">Aplikacje i ADB</string>
<string name="settings_su_app">Tylko aplikacje</string>
<string name="settings_su_adb">Tylko ADB</string>
@ -164,23 +167,23 @@
<string name="request_timeout">Limit czasu żądania</string>
<string name="superuser_notification">Powiadomienia Superusera</string>
<string name="settings_su_reauth_title">Ponowienie uwierzytelniania po aktualizacji</string>
<string name="settings_su_reauth_summary">Ponowienie dostępu do uprawnień Superusera po uaktualnieniu aplikacji</string>
<string name="settings_su_tapjack_title">Włącz ochronę przed Tapjacking (niezamierzone kliknięcie)</string>
<string name="settings_su_tapjack_summary">Pytanie o Superuser nie będzie reagować na odpowiedź jeżeli będzie zasłonięte lub przyćmione.</string>
<string name="settings_su_biometric_title">Uwierzytelnianie biometryczne</string>
<string name="settings_su_biometric_summary">Używaj uwierzytelniania biometrycznego (np. odcisku palca) aby przyznać uprawnienia Superusera</string>
<string name="no_biometric">Urządzenie jest nieobsługiwane lub ustawienia biometryczne nie są włączone</string>
<string name="settings_su_reauth_summary">Zapytaj ponownie o uprawnienia Superusera po uaktualnieniu aplikacji</string>
<string name="settings_su_tapjack_title">Ochrona przed Tapjackingiem (niezamierzonym kliknięciem)</string>
<string name="settings_su_tapjack_summary">Okno dialogowe z żądaniem Superusera nie będzie reagować na odpowiedź, jeżeli będzie zasłonięte przez inne okno lub nakładkę</string>
<string name="settings_su_auth_title">Uwierzytelnianie użytkownika</string>
<string name="settings_su_auth_summary">Pytaj o uwierzytelnienie użytkownika podczas żądań Superusera</string>
<string name="settings_su_auth_insecure">Nie skonfigurowano żadnej metody uwierzytelniania na tym urządzeniu</string>
<string name="settings_customization">Personalizacja</string>
<string name="setting_add_shortcut_summary">Dodaj ładny skrót na ekranie głównym na wypadek, gdyby nazwa i ikona były trudne do rozpoznania po ukryciu aplikacji</string>
<string name="setting_add_shortcut_summary">Umieść ładny skrót na ekranie głównym na wypadek, gdyby nazwa i ikona były trudne do rozpoznania po ukryciu aplikacji</string>
<string name="settings_doh_title">DNS over HTTPS</string>
<string name="settings_doh_description">Zapobiegaj zatruwaniu DNS (DNS poisoning) w niektórych krajach</string>
<string name="multiuser_mode">Tryb wielu użytkowników (Multiuser)</string>
<string name="settings_owner_only">Tylko właściciel urządzenia</string>
<string name="settings_owner_manage">Zarządzanie przez właściciela urządzenia</string>
<string name="settings_user_independent">Niezależni użytkownicy</string>
<string name="settings_user_independent">Niezależne ustawienia użytkowników</string>
<string name="owner_only_summary">Tylko właściciel ma dostęp do roota</string>
<string name="owner_manage_summary">Tylko właściciel może zarządzać ustawieniami dostępu do roota i otrzymywać żądania dostępu</string>
<string name="owner_manage_summary">Tylko właściciel może zarządzać dostępem do roota i otrzymywać żądania dostępu do roota</string>
<string name="user_independent_summary">Każdy użytkownik ma niezależne ustawienia dostępu do roota</string>
<string name="mount_namespace_mode">Tryb przestrzeni nazw montowania</string>
@ -188,7 +191,7 @@
<string name="settings_ns_requester">Dziedziczona przestrzeń nazw</string>
<string name="settings_ns_isolate">Izolowana przestrzeń nazw</string>
<string name="global_summary">Wszystkie sesje roota będą używać globalnej przestrzeni nazw montowania</string>
<string name="requester_summary">Sesje roota odziedziczą przestrzeń nazw od żądającego</string>
<string name="requester_summary">Sesje roota odziedziczą przestrzeń nazw żądającego dostępu</string>
<string name="isolate_summary">Każda sesja roota otrzyma własną, izolowaną przestrzeń nazw</string>
<!--Notifications-->
@ -199,7 +202,7 @@
<string name="download_file_error">Błąd pobierania pliku</string>
<string name="magisk_update_title">Aktualizacja Magisk dostępna!</string>
<string name="updated_title">Magisk zaktualizowany</string>
<string name="updated_text">Naciśnij aby otworzyć applikację</string>
<string name="updated_text">Kliknij, aby otworzyć aplikację</string>
<!--Toasts, Dialogs-->
<string name="yes">Tak</string>
@ -211,7 +214,7 @@
<string name="flashing">Flashowanie…</string>
<string name="done">Gotowe!</string>
<string name="failure">Błąd</string>
<string name="hide_app_title">Ukrywam aplikację Magisk…</string>
<string name="hide_app_title">Ukrywanie aplikacji Magisk…</string>
<string name="open_link_failed_toast">Nie znaleziono aplikacji do otwarcia linku</string>
<string name="complete_uninstall">Odinstaluj całkowicie</string>
<string name="restore_img">Przywróć obrazy</string>
@ -219,26 +222,26 @@
<string name="restore_done">Przywracanie zakończone!</string>
<string name="restore_fail">Kopia zapasowa nie istnieje!</string>
<string name="setup_fail">Konfiguracja nieudana</string>
<string name="env_fix_title">Wymaga dodatkowej konfiguracji</string>
<string name="env_fix_msg">Twoje urządzenie wymaga dodatkowej konfiguracji aby Magisk działał właściwie. Czy chcesz kontynuować i uruchomić ponownie?</string>
<string name="env_full_fix_msg">Twoje urządzenie musi wgrać ponowanie Magisk, aby działać poprawnie. Proszę przeinstaluj Magisk w aplikacji, tryb Recovery nie potrafi poprawnie rozpoznać urządzenia.</string>
<string name="env_fix_title">Wymagana dodatkowa konfiguracja</string>
<string name="env_fix_msg">Twoje urządzenie wymaga dodatkowej konfiguracji, aby Magisk działał poprawnie. Czy chcesz kontynuować i uruchomić ponownie?</string>
<string name="env_full_fix_msg">Twoje urządzenie wymaga ponownej instalacji Magisk, aby działać poprawnie. Zainstaluj ponownie Magisk używając aplikacji, tryb recovery nie może uzyskać prawidłowych informacji o urządzeniu.</string>
<string name="setup_msg">Uruchamianie środowiska konfiguracji…</string>
<string name="authenticate">Uwierzytelnianie</string>
<string name="unsupport_magisk_title">Nieobsługiwana wersja Magisk</string>
<string name="unsupport_magisk_msg">Ta wersja aplikacji nie obsługuje Magisk w wersji niższej niż %1$s.\n\nAplikacja będzie zachowywać się tak jakby Magisk nie był zainstalowany, proszę uaktualnij Magisk.</string>
<string name="unsupport_magisk_msg">Ta wersja aplikacji nie obsługuje Magisk w wersji niższej niż %1$s.\n\nAplikacja będzie zachowywać się tak, jakby Magisk nie był zainstalowany, zaktualizuj Magisk tak szybko, jak to możliwe.</string>
<string name="unsupport_general_title">Nieprawidłowy stan</string>
<string name="unsupport_system_app_msg">Uruchomienie tej aplikacji jako systemowa nie jest obsługiwane. Proszę przemienić ją na aplikację użytkownika.</string>
<string name="unsupport_other_su_msg">Wykryto komendę \"su\" nie należącą do Magisk. Proszę usunąć tę drugą aplikację \"su\".</string>
<string name="unsupport_external_storage_msg">Zainstalowano Magisk na pamięci zewnętrznej. Proszę przenieść ją na pamięć wewnętrzną.</string>
<string name="unsupport_nonroot_stub_msg">Ta aplikacja nie może dłużej działać w trybie ukrycia jako że root został utracony. Proszę przywrócić ją do oryginalnego stanu.</string>
<string name="unsupport_system_app_msg">Uruchomienie tej aplikacji jako aplikacja systemowa nie jest obsługiwane. Przywróć aplikację do stanu aplikacji użytkownika.</string>
<string name="unsupport_other_su_msg">Wykryto plik binarny \"su\" nie należący do Magisk. Usuń wszelkie konkurencyjne rozwiązania root i/lub zainstaluj ponownie Magisk.</string>
<string name="unsupport_external_storage_msg">Magisk jest zainstalowany w pamięci zewnętrznej. Przenieś aplikację do pamięci wewnętrznej.</string>
<string name="unsupport_nonroot_stub_msg">Ukryta aplikacja Magisk nie może dłużej działać, ponieważ uprawnienia roota zostały utracone. Przywróć oryginalny plik APK.</string>
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
<string name="external_rw_permission_denied">Zezwól na dostęp do pamięci wewnętrznej, aby włączyć tę funkcję.</string>
<string name="post_notifications_denied">Zezwól na otrzymywanie powiadomień, aby aktywować tą funkcję</string>
<string name="install_unknown_denied">Zezwól na "Instaluj z nieznanych źródeł" by włączyć tą funkcję</string>
<string name="external_rw_permission_denied">Zezwól na dostęp do pamięci, aby włączyć tę funkcję</string>
<string name="post_notifications_denied">Zezwól na otrzymywanie powiadomień, aby włączyć tę funkcję</string>
<string name="install_unknown_denied">Zezwól na \"Instaluj z nieznanych źródeł\", aby włączyć tę funkcję</string>
<string name="add_shortcut_title">Utwórz skrót na ekranie głównym</string>
<string name="add_shortcut_msg">Po ukryciu tej aplikacji, jej nazwa i ikona może być trudna do rozpoznania. Czy chcesz dodać ładny skrót na ekranie głównym?</string>
<string name="app_not_found">Nie znaleziono aplikacji do wykonania tej czynności</string>
<string name="reboot_apply_change">Uruchom ponownie by zastosować zmiany</string>
<string name="restore_app_confirmation">To przywróci ukrytą aplikację z powrotem do orginalnej aplikacji. Czy na pewno chcesz to zrobić?</string>
<string name="reboot_apply_change">Uruchom ponownie, aby zastosować zmiany</string>
<string name="restore_app_confirmation">Spowoduje to przywrócenie ukrytej aplikacji z powrotem do stanu oryginalnej aplikacji. Czy na pewno chcesz to zrobić?</string>
</resources>

View File

@ -6,35 +6,35 @@
<string name="logs">Registros</string>
<string name="settings">Configurações</string>
<string name="install">Instalar</string>
<string name="section_home">Resumo</string>
<string name="section_home">Início</string>
<string name="section_theme">Temas</string>
<string name="denylist">Lista de Negação</string>
<string name="denylist">Lista de negação</string>
<!--Home-->
<string name="no_connection">Nenhuma conexão disponível</string>
<string name="app_changelog">Registro de alterações</string>
<string name="loading">Carregando…</string>
<string name="update">Atualizar</string>
<string name="not_available">N/A</string>
<string name="not_available">Não disponível</string>
<string name="hide">Ocultar</string>
<string name="home_package">Pacote</string>
<string name="home_app_title">App</string>
<string name="home_notice_content">Baixe o Magisk SOMENTE pela página oficial do Github. Arquivos de fontes desconhecidas podem ser maliciosos e danificar seu aparelho.</string>
<string name="home_support_title">Apoie</string>
<string name="home_follow_title">Siga</string>
<string name="home_notice_content">Baixe o Magisk SOMENTE pela página oficial do GitHub. Arquivos de fontes desconhecidas podem ser maliciosos!</string>
<string name="home_support_title">Apoie-nos</string>
<string name="home_follow_title">Siga-nos</string>
<string name="home_item_source">Fonte</string>
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode agradecer enviando uma pequena doação.</string>
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode nos ajudar enviando uma pequena doação.</string>
<string name="home_installed_version">Instalado</string>
<string name="home_latest_version">Recente</string>
<string name="invalid_update_channel">Canal de atualização inválido</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nA raiz será removida!\nSeus dados não criptografados devido uso do Magisk, serão re-criptografados!</string>
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nO root será removido!\nSeus dados não criptografados devido ao uso do Magisk, serão re-criptografados!</string>
<!--Install-->
<string name="keep_force_encryption">Manter criptografia forçada</string>
<string name="keep_dm_verity">Manter AVB 2.0/dm-verity</string>
<string name="patch_vbmeta">Corrigir vbmeta na imagem de boot</string>
<string name="recovery_mode">Modo de recuperação</string>
<string name="recovery_mode">Modo Recovery</string>
<string name="install_options_title">Opções</string>
<string name="install_method_title">Método</string>
<string name="install_next">Próximo</string>
@ -51,7 +51,7 @@
<!--Superuser-->
<string name="su_request_title">Solicitação de SuperUsuário</string>
<string name="touch_filtered_warning">Devido um app estar obscurecendo a solicitação de SuperUsuário, o Magisk não pode conferir suas resposta</string>
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="grant">Permitir</string>
@ -62,28 +62,28 @@
<string name="twentymin">20 mins</string>
<string name="thirtymin">30 mins</string>
<string name="sixtymin">60 mins</string>
<string name="su_allow_toast">%1$s foi permitido o acesso SuperUsuário</string>
<string name="su_deny_toast">%1$s foi negado o acesso SuperUsuário</string>
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram permitidos</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de SuperUsuário</string>
<string name="su_deny_toast">%1$s foi negado o acesso de SuperUsuário</string>
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram concedidos</string>
<string name="su_snack_deny">Os acessos de SuperUsuário de %1$s foram negados</string>
<string name="su_snack_notif_on">As notificações de %1$s foram ativadas</string>
<string name="su_snack_notif_off">As notificações de %1$s foram desativadas</string>
<string name="su_snack_log_on">Os registros de %1$s foram ativados</string>
<string name="su_snack_log_off">Os registros de %1$s foram desativados</string>
<string name="su_revoke_title">Remover?</string>
<string name="su_revoke_msg">Confirmar a remoção do acesso de %1$s?</string>
<string name="su_revoke_title">Revogar?</string>
<string name="su_revoke_msg">Confirmar a remoção do acesso de SuperUsuário de %1$s?</string>
<string name="toast">Notificação (Pop-up)</string>
<string name="none">Nenhum</string>
<string name="superuser_toggle_notification">Notificações</string>
<string name="superuser_toggle_revoke">Remover</string>
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda.</string>
<string name="superuser_toggle_revoke">Revogar</string>
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda</string>
<!--Logs-->
<string name="log_data_none">Não há registros. Tente usar os apps permitidos para SuperUsuário.</string>
<string name="log_data_magisk_none">Os Registro de atividade do Magisk estão vazios, isso é estranho.</string>
<string name="menuSaveLog">Salvar Registro</string>
<string name="menuClearLog">Limpar Registro agora</string>
<string name="logs_cleared">Registro limpo com sucesso.</string>
<string name="log_data_none">Não há registros. Tente usar mais seus apps root.</string>
<string name="log_data_magisk_none">Os registros do Magisk estão vazios, isso é estranho.</string>
<string name="menuSaveLog">Salvar registros</string>
<string name="menuClearLog">Limpar registros agora</string>
<string name="logs_cleared">Registros limpo com sucesso</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Alvo UID: %1$d</string>
<string name="target_pid">Alvo PID: %s</string>
@ -91,65 +91,66 @@
<string name="supp_group">Grupo suplementar: %s</string>
<!--MagiskHide-->
<string name="show_system_app">Mostrar apps do Sistema</string>
<string name="show_os_app">Mostrar apps do Sistema</string>
<string name="show_system_app">Mostrar apps do sistema</string>
<string name="show_os_app">Mostrar apps do sistema operacional</string>
<string name="hide_filter_hint">Filtrar pelo nome</string>
<string name="hide_search">Pesquisa</string>
<string name="hide_search">Pesquisar</string>
<!--Module-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
<string name="reboot_userspace">Reinício rápido</string>
<string name="reboot_userspace">Reinicialização suave</string>
<string name="reboot_recovery">Reiniciar em modo Recovery</string>
<string name="reboot_bootloader">Reiniciar em modo Bootloader</string>
<string name="reboot_download">Reiniciar em modo Download</string>
<string name="reboot_edl">Reiniciar em modo EDL</string>
<string name="reboot_safe_mode">Modo de segurança</string>
<string name="module_version_author">%1$s por %2$s</string>
<string name="module_state_remove">Remover</string>
<string name="module_state_restore">Restaurar</string>
<string name="module_action_install_external">Instalar a partir do armazenamento</string>
<string name="update_available">Atualização disponível</string>
<string name="suspend_text_riru">Módulo suspenso porque %1$s está ativo</string>
<string name="suspend_text_zygisk">Módulo suspenso porque %1$s não está ativo</string>
<string name="suspend_text_riru">Módulo suspenso porque %1$s está ativado</string>
<string name="suspend_text_zygisk">Módulo suspenso porque %1$s não está ativado</string>
<string name="zygisk_module_unloaded">Modulo Zygisk não carregado devido a incompatibilidade</string>
<string name="module_empty">Nenhum módulo instalado</string>
<string name="confirm_install">Instalar módulo %1$s?</string>
<string name="confirm_install_title">Confirmação de Instalação</string>
<string name="confirm_install_title">Confirmação de instalação</string>
<!--Settings-->
<string name="settings_dark_mode_title">Modo de tema</string>
<string name="settings_dark_mode_message">Selecione o modo mais adequado ao seu estilo!</string>
<string name="settings_dark_mode_light">Sempre Claro</string>
<string name="settings_dark_mode_system">Baseado no Sistema</string>
<string name="settings_dark_mode_dark">Sempre Escuro</string>
<string name="settings_download_path_title">Caminho para Baixar</string>
<string name="settings_dark_mode_title">Modo do tema</string>
<string name="settings_dark_mode_message">Selecione o modo mais adequado para você!</string>
<string name="settings_dark_mode_light">Sempre claro</string>
<string name="settings_dark_mode_system">Seguir sistema</string>
<string name="settings_dark_mode_dark">Sempre escuro</string>
<string name="settings_download_path_title">Caminho para baixar</string>
<string name="settings_download_path_message">Os arquivos serão salvos em %1$s</string>
<string name="settings_hide_app_title">Ocultar o app do Magisk</string>
<string name="settings_hide_app_title">Ocultar app do Magisk</string>
<string name="settings_hide_app_summary">Instala o app oculto com ID aleatório e nome personalizado</string>
<string name="settings_restore_app_title">Restaurar o App do Magisk</string>
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
<string name="settings_restore_app_summary">Desoculta o app do Magisk e restaura o APK original</string>
<string name="language">Idioma</string>
<string name="system_default">(Padrão do sistema)</string>
<string name="settings_check_update_title">Ativar Verificação de Atualizações</string>
<string name="settings_check_update_summary">Verifica periodicamente em segundo plano se há atualizações</string>
<string name="settings_update_channel_title">Canal de Atualização</string>
<string name="settings_check_update_title">Verificar por atualizações</string>
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="settings_update_channel_title">Canal de atualização</string>
<string name="settings_update_stable">Estável</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Canal Personalizado</string>
<string name="settings_update_custom_msg">Insira um URL personalizado</string>
<string name="settings_update_custom">Personalizado</string>
<string name="settings_update_custom_msg">Insira um URL de canal personalizado</string>
<string name="settings_zygisk_summary">Executa partes do Magisk no Zygote</string>
<string name="settings_denylist_title">Forçar Aplicação da Lista de Negação</string>
<string name="settings_denylist_summary">Os processos na lista de negação terão revertidas todas as modificações feitas pelo Magisk</string>
<string name="settings_denylist_error">Isso requer %1$s para ser ativado</string>
<string name="settings_denylist_config_title">Configurar Lista de Negação</string>
<string name="settings_denylist_title">Aplicar lista de negação</string>
<string name="settings_denylist_summary">Os processos na lista de negação terão todas as modificações do Magisk revertidas</string>
<string name="settings_denylist_error">Este recurso requer que %1$s esteja ativado</string>
<string name="settings_denylist_config_title">Configurar lista de negação</string>
<string name="settings_denylist_config_summary">Selecione os processos a serem incluídos na lista de negação</string>
<string name="settings_hosts_title">Ativar /etc/hosts systemless</string>
<string name="settings_hosts_summary">Suporte de /etc/hosts fora do sistema para aplicativos Adblock</string>
<string name="settings_hosts_toast">Adicionado módulo do /etc/hosts systemless</string>
<string name="settings_hosts_title">Hosts sem sistema</string>
<string name="settings_hosts_summary">Suporte de hosts sem sistema para apps AdBlock</string>
<string name="settings_hosts_toast">Adicionado módulo de hosts sem sistema</string>
<string name="settings_app_name_hint">Novo nome</string>
<string name="settings_app_name_helper">O app do Magisk será reinstalado com este nome</string>
<string name="settings_app_name_error">Formato inválido</string>
<string name="settings_su_app_adb">Aplicativos e ADB</string>
<string name="settings_su_app">Apenas aplicativos</string>
<string name="settings_su_app_adb">Apps e ADB</string>
<string name="settings_su_app">Apenas apps</string>
<string name="settings_su_adb">Apenas ADB</string>
<string name="settings_su_disable">Desativado</string>
<string name="settings_su_request_10">10 segundos</string>
@ -160,33 +161,33 @@
<string name="settings_su_request_60">60 segundos</string>
<string name="superuser_access">Acesso de SuperUsuário</string>
<string name="auto_response">Resposta automática</string>
<string name="request_timeout">Tempo Limite da Solicitação</string>
<string name="request_timeout">Tempo limite da solicitação</string>
<string name="superuser_notification">Notificação de SuperUsuário</string>
<string name="settings_su_reauth_title">Autenticar novamente após a atualização</string>
<string name="settings_su_reauth_summary">Reautenticar permissões de SuperUsuário após atualizar aplicativo</string>
<string name="settings_su_tapjack_title">Ativar Proteção Contra Atividades Sobrepostas</string>
<string name="settings_su_tapjack_summary">A caixa de diálogo do SuperUsuário não responderá à entrada enquanto estiver obscurecida por qualquer outra janela ou sobreposição</string>
<string name="settings_su_biometric_title">Ativar Autenticação Biométrica</string>
<string name="settings_su_biometric_summary">Use a autenticação biométrica para permitir solicitações de SuperUsuário</string>
<string name="no_biometric">Dispositivo não suportado ou nenhuma configuração biométrica está ativada</string>
<string name="settings_su_reauth_title">Reautenticar após atualização</string>
<string name="settings_su_reauth_summary">Solicite permissões de SuperUsuário novamente após atualizar os apps</string>
<string name="settings_su_tapjack_title">Proteção contra atividades sobrepostas</string>
<string name="settings_su_tapjack_summary">A caixa de diálogo do SuperUsuário não responderá à entrada enquanto estiver oculta por qualquer outra janela ou sobreposição</string>
<string name="settings_su_auth_title">Autenticação de usuário</string>
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
<string name="settings_customization">Personalizações</string>
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o aplicativo</string>
<string name="settings_doh_title">Ativar DNS sobre HTTPS</string>
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
<string name="multiuser_mode">Ativar Modo Multiusuário</string>
<string name="multiuser_mode">Modo Multiusuário</string>
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
<string name="settings_user_independent">Independente do usuário</string>
<string name="owner_only_summary">Somente o proprietário tem acesso ao SuperUsuário</string>
<string name="owner_manage_summary">Somente o proprietário pode gerenciar o acesso do SuperUsuário e receber pedidos de solicitação</string>
<string name="owner_only_summary">Somente o proprietário tem acesso root</string>
<string name="owner_manage_summary">Somente o proprietário pode gerenciar o acesso root e receber pedidos de solicitação</string>
<string name="user_independent_summary">Cada usuário tem suas próprias regras de root separadas</string>
<string name="mount_namespace_mode">Ativar Modo Namespace</string>
<string name="settings_ns_global">Namespace global</string>
<string name="settings_ns_requester">Herdar Namespace</string>
<string name="settings_ns_isolate">Namespace isolado</string>
<string name="mount_namespace_mode">Montar namespace</string>
<string name="settings_ns_global">Global</string>
<string name="settings_ns_requester">Herdado</string>
<string name="settings_ns_isolate">Individual</string>
<string name="global_summary">Todas as sessões root usam o namespace de montagem global</string>
<string name="requester_summary">As sessões root herdarão o namespace do solicitante</string>
<string name="isolate_summary">Cada sessão do SuperUsuário terá seu próprio namespace isolado</string>
<string name="isolate_summary">Cada sessão root terá seu próprio namespace individual</string>
<!--Notifications-->
<string name="update_channel">Atualizações do Magisk</string>
@ -194,8 +195,8 @@
<string name="updated_channel">Atualização concluída</string>
<string name="download_complete">Download concluído</string>
<string name="download_file_error">Erro ao baixar arquivo</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="updated_title">Magisk Atualizado</string>
<string name="magisk_update_title">Atualização do Magisk disponível!</string>
<string name="updated_title">Magisk atualizado</string>
<string name="updated_text">Toque para abrir o app</string>
<!--Toasts, Dialogs-->
@ -205,35 +206,35 @@
<string name="download">Baixar</string>
<string name="reboot">Reiniciar</string>
<string name="release_notes">Notas da atualização</string>
<string name="flashing">Fazendo Flash…</string>
<string name="flashing">Flashando</string>
<string name="done">Concluído!</string>
<string name="failure">Falha</string>
<string name="failure">Falhou!</string>
<string name="hide_app_title">Ocultando o app do Magisk…</string>
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>
<string name="complete_uninstall">Desinstalação completa</string>
<string name="restore_img">Restaurar imagens</string>
<string name="restore_img_msg">Restaurando…</string>
<string name="restore_done">Restauração concluída!</string>
<string name="restore_fail">O backup original não foi encontrado!</string>
<string name="restore_fail">O backup original não existe!</string>
<string name="setup_fail">Falha na instalação</string>
<string name="env_fix_title">Configuração adicional exigida</string>
<string name="env_fix_msg">Seu dispositivo exige uma configuração adicional para o Magisk funcionar corretamente. Deseja continuar e reiniciar?</string>
<string name="env_full_fix_msg">Seu dispositivo precisa refazer o flash do Magisk para funcionar corretamente. Reinstale o Magisk no aplicativo, o modo de recuperação não pode obter as devidas informações do dispositivo.</string>
<string name="env_full_fix_msg">Seu dispositivo precisa refazer o flash do Magisk para funcionar corretamente. Por favor, reinstale o Magisk no app, o modo Recovery não pode obter as devidas informações do dispositivo.</string>
<string name="setup_msg">Executando a configuração do ambiente…</string>
<string name="authenticate">Autenticar</string>
<string name="unsupport_magisk_title">Versão do Magisk não suportada</string>
<string name="unsupport_magisk_msg">Essa versão do app não suporta versão do Magisk inferior a %1$s.\n\nO app irá se comportar como se nenhum Magisk estivesse sido instalado. Por favor, atualize o Magisk assim que possível.</string>
<string name="unsupport_general_title">Estado Anormal</string>
<string name="unsupport_system_app_msg">Não há suporte para executar este app como um app do sistema. Por favor, reverta o app para um app do usuário.</string>
<string name="unsupport_magisk_msg">Esta versão do app não suporta a versão do Magisk inferior a %1$s.\n\nO app irá se comportar como se nenhum Magisk estivesse sido instalado. Por favor, atualize o Magisk assim que possível.</string>
<string name="unsupport_general_title">Estado anormal</string>
<string name="unsupport_system_app_msg">Não há suporte para executar este app como um app do sistema. Por favor, reverta o app para um app de usuário.</string>
<string name="unsupport_other_su_msg">Não foi possível detectar o binário \"su\" do Magisk. Por favor, remova qualquer outro root concorrente e/ou reinstale o Magisk.</string>
<string name="unsupport_external_storage_msg">O app do Magisk está instalado no armazenamento externo, Por favor, mova o app para o armazenamento interno.</string>
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar a funcionar porque o SuperUsuário foi perdido. Por favor, restaure o APK original.</string>
<string name="unsupport_external_storage_msg">O app do Magisk está instalado no armazenamento externo. Por favor, mova o app para o armazenamento interno.</string>
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar funcionando porque o root foi perdido. Por favor, restaure o APK original.</string>
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
<string name="external_rw_permission_denied">Autorize a permissão de armazenamento para ativar esta funcionalidade</string>
<string name="post_notifications_denied">Autorize a permissão de notificaçoes para ativar esta funcionalidade</string>
<string name="install_unknown_denied">Permita a "instalação apps desconhecidos" para ativar esta funcionalidade</string>
<string name="add_shortcut_title">Adicionar Atalho à Tela Inicial</string>
<string name="add_shortcut_msg">Depois de ocultar o app do Magisk, o seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
<string name="external_rw_permission_denied">Conceda permissão de armazenamento para ativar esta funcionalidade</string>
<string name="post_notifications_denied">Conceda permissão às notificações para ativar esta funcionalidade</string>
<string name="install_unknown_denied">Permita a opção "Instalar apps de fontes desconhecidas" para ativar esta funcionalidade</string>
<string name="add_shortcut_title">Adicionar atalho à tela inicial</string>
<string name="add_shortcut_msg">Após ocultar o app do Magisk, seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
<string name="app_not_found">Nenhum app encontrado para realizar esta ação</string>
<string name="reboot_apply_change">Reinicie para aplicar as mudanças</string>
<string name="restore_app_confirmation">Isso irá restaurar o app oculto do Magisk de volta para o app original. Deseja realmente fazer isso?</string>

View File

@ -6,35 +6,35 @@
<string name="logs">Registros</string>
<string name="settings">Configurações</string>
<string name="install">Instalar</string>
<string name="section_home">Resumo</string>
<string name="section_home">Início</string>
<string name="section_theme">Temas</string>
<string name="denylist">Lista de Negação</string>
<string name="denylist">Lista de negação</string>
<!--Home-->
<string name="no_connection">Nenhuma conexão disponível</string>
<string name="app_changelog">Registro de alterações</string>
<string name="loading">Carregando…</string>
<string name="update">Atualizar</string>
<string name="not_available">N/A</string>
<string name="not_available">Não disponível</string>
<string name="hide">Ocultar</string>
<string name="home_package">Pacote</string>
<string name="home_app_title">App</string>
<string name="home_notice_content">Baixe o Magisk SOMENTE pela página oficial do Github. Arquivos de fontes desconhecidas podem ser maliciosos e danificar seu aparelho.</string>
<string name="home_support_title">Apoie</string>
<string name="home_follow_title">Siga</string>
<string name="home_notice_content">Baixe o Magisk SOMENTE pela página oficial do GitHub. Arquivos de fontes desconhecidas podem ser maliciosos!</string>
<string name="home_support_title">Apoie-nos</string>
<string name="home_follow_title">Siga-nos</string>
<string name="home_item_source">Fonte</string>
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode agradecer enviando uma pequena doação.</string>
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode nos ajudar enviando uma pequena doação.</string>
<string name="home_installed_version">Instalado</string>
<string name="home_latest_version">Recente</string>
<string name="invalid_update_channel">Canal de atualização inválido</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nA raiz será removida!\nSeus dados não criptografados devido uso do Magisk, serão re-criptografados!</string>
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nO root será removido!\nSeus dados não criptografados devido ao uso do Magisk, serão re-criptografados!</string>
<!--Install-->
<string name="keep_force_encryption">Manter criptografia forçada</string>
<string name="keep_dm_verity">Manter AVB 2.0/dm-verity</string>
<string name="patch_vbmeta">Corrigir vbmeta na imagem de boot</string>
<string name="recovery_mode">Modo de recuperação</string>
<string name="recovery_mode">Modo Recovery</string>
<string name="install_options_title">Opções</string>
<string name="install_method_title">Método</string>
<string name="install_next">Próximo</string>
@ -51,7 +51,7 @@
<!--Superuser-->
<string name="su_request_title">Solicitação de SuperUsuário</string>
<string name="touch_filtered_warning">Devido um app estar obscurecendo a solicitação de SuperUsuário, o Magisk não pode conferir suas resposta</string>
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="grant">Permitir</string>
@ -62,28 +62,28 @@
<string name="twentymin">20 mins</string>
<string name="thirtymin">30 mins</string>
<string name="sixtymin">60 mins</string>
<string name="su_allow_toast">%1$s foi permitido o acesso SuperUsuário</string>
<string name="su_deny_toast">%1$s foi negado o acesso SuperUsuário</string>
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram permitidos</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de SuperUsuário</string>
<string name="su_deny_toast">%1$s foi negado o acesso de SuperUsuário</string>
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram concedidos</string>
<string name="su_snack_deny">Os acessos de SuperUsuário de %1$s foram negados</string>
<string name="su_snack_notif_on">As notificações de %1$s foram ativadas</string>
<string name="su_snack_notif_off">As notificações de %1$s foram desativadas</string>
<string name="su_snack_log_on">Os registros de %1$s foram ativados</string>
<string name="su_snack_log_off">Os registros de %1$s foram desativados</string>
<string name="su_revoke_title">Remover?</string>
<string name="su_revoke_msg">Confirmar a remoção do acesso de %1$s?</string>
<string name="su_revoke_title">Revogar?</string>
<string name="su_revoke_msg">Confirmar a remoção do acesso de SuperUsuário de %1$s?</string>
<string name="toast">Notificação (Pop-up)</string>
<string name="none">Nenhum</string>
<string name="superuser_toggle_notification">Notificações</string>
<string name="superuser_toggle_revoke">Remover</string>
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda.</string>
<string name="superuser_toggle_revoke">Revogar</string>
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda</string>
<!--Logs-->
<string name="log_data_none">Não há registros. Tente usar os apps permitidos para SuperUsuário.</string>
<string name="log_data_magisk_none">Os Registro de atividade do Magisk estão vazios, isso é estranho.</string>
<string name="menuSaveLog">Salvar Registro</string>
<string name="menuClearLog">Limpar Registro agora</string>
<string name="logs_cleared">Registro limpo com sucesso.</string>
<string name="log_data_none">Não há registros. Tente usar mais seus apps root.</string>
<string name="log_data_magisk_none">Os registros do Magisk estão vazios, isso é estranho.</string>
<string name="menuSaveLog">Salvar registros</string>
<string name="menuClearLog">Limpar registros agora</string>
<string name="logs_cleared">Registros limpo com sucesso</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Alvo UID: %1$d</string>
<string name="target_pid">Alvo PID: %s</string>
@ -91,65 +91,66 @@
<string name="supp_group">Grupo suplementar: %s</string>
<!--MagiskHide-->
<string name="show_system_app">Mostrar apps do Sistema</string>
<string name="show_os_app">Mostrar apps do Sistema</string>
<string name="show_system_app">Mostrar apps do sistema</string>
<string name="show_os_app">Mostrar apps do sistema operacional</string>
<string name="hide_filter_hint">Filtrar pelo nome</string>
<string name="hide_search">Pesquisa</string>
<string name="hide_search">Pesquisar</string>
<!--Module-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
<string name="reboot_userspace">Reinício rápido</string>
<string name="reboot_userspace">Reinicialização suave</string>
<string name="reboot_recovery">Reiniciar em modo Recovery</string>
<string name="reboot_bootloader">Reiniciar em modo Bootloader</string>
<string name="reboot_download">Reiniciar em modo Download</string>
<string name="reboot_edl">Reiniciar em modo EDL</string>
<string name="reboot_safe_mode">Modo de segurança</string>
<string name="module_version_author">%1$s por %2$s</string>
<string name="module_state_remove">Remover</string>
<string name="module_state_restore">Restaurar</string>
<string name="module_action_install_external">Instalar a partir do armazenamento</string>
<string name="update_available">Atualização disponível</string>
<string name="suspend_text_riru">Módulo suspenso porque %1$s está ativo</string>
<string name="suspend_text_zygisk">Módulo suspenso porque %1$s não está ativo</string>
<string name="suspend_text_riru">Módulo suspenso porque %1$s está ativado</string>
<string name="suspend_text_zygisk">Módulo suspenso porque %1$s não está ativado</string>
<string name="zygisk_module_unloaded">Modulo Zygisk não carregado devido a incompatibilidade</string>
<string name="module_empty">Nenhum módulo instalado</string>
<string name="confirm_install">Instalar módulo %1$s?</string>
<string name="confirm_install_title">Confirmação de Instalação</string>
<string name="confirm_install_title">Confirmação de instalação</string>
<!--Settings-->
<string name="settings_dark_mode_title">Modo de tema</string>
<string name="settings_dark_mode_message">Selecione o modo mais adequado ao seu estilo!</string>
<string name="settings_dark_mode_light">Sempre Claro</string>
<string name="settings_dark_mode_system">Baseado no Sistema</string>
<string name="settings_dark_mode_dark">Sempre Escuro</string>
<string name="settings_download_path_title">Caminho para Baixar</string>
<string name="settings_dark_mode_title">Modo do tema</string>
<string name="settings_dark_mode_message">Selecione o modo mais adequado para você!</string>
<string name="settings_dark_mode_light">Sempre claro</string>
<string name="settings_dark_mode_system">Seguir sistema</string>
<string name="settings_dark_mode_dark">Sempre escuro</string>
<string name="settings_download_path_title">Caminho para baixar</string>
<string name="settings_download_path_message">Os arquivos serão salvos em %1$s</string>
<string name="settings_hide_app_title">Ocultar o app do Magisk</string>
<string name="settings_hide_app_title">Ocultar app do Magisk</string>
<string name="settings_hide_app_summary">Instala o app oculto com ID aleatório e nome personalizado</string>
<string name="settings_restore_app_title">Restaurar o App do Magisk</string>
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
<string name="settings_restore_app_summary">Desoculta o app do Magisk e restaura o APK original</string>
<string name="language">Idioma</string>
<string name="system_default">(Padrão do sistema)</string>
<string name="settings_check_update_title">Ativar Verificação de Atualizações</string>
<string name="settings_check_update_summary">Verifica periodicamente em segundo plano se há atualizações</string>
<string name="settings_update_channel_title">Canal de Atualização</string>
<string name="settings_check_update_title">Verificar por atualizações</string>
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="settings_update_channel_title">Canal de atualização</string>
<string name="settings_update_stable">Estável</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Canal Personalizado</string>
<string name="settings_update_custom_msg">Insira um URL personalizado</string>
<string name="settings_update_custom">Personalizado</string>
<string name="settings_update_custom_msg">Insira um URL de canal personalizado</string>
<string name="settings_zygisk_summary">Executa partes do Magisk no Zygote</string>
<string name="settings_denylist_title">Forçar Aplicação da Lista de Negação</string>
<string name="settings_denylist_summary">Os processos na lista de negação terão revertidas todas as modificações feitas pelo Magisk</string>
<string name="settings_denylist_error">Isso requer %1$s para ser ativado</string>
<string name="settings_denylist_config_title">Configurar Lista de Negação</string>
<string name="settings_denylist_title">Aplicar lista de negação</string>
<string name="settings_denylist_summary">Os processos na lista de negação terão todas as modificações do Magisk revertidas</string>
<string name="settings_denylist_error">Este recurso requer que %1$s esteja ativado</string>
<string name="settings_denylist_config_title">Configurar lista de negação</string>
<string name="settings_denylist_config_summary">Selecione os processos a serem incluídos na lista de negação</string>
<string name="settings_hosts_title">Ativar /etc/hosts systemless</string>
<string name="settings_hosts_summary">Suporte de /etc/hosts fora do sistema para aplicativos Adblock</string>
<string name="settings_hosts_toast">Adicionado módulo do /etc/hosts systemless</string>
<string name="settings_hosts_title">Hosts sem sistema</string>
<string name="settings_hosts_summary">Suporte de hosts sem sistema para apps AdBlock</string>
<string name="settings_hosts_toast">Adicionado módulo de hosts sem sistema</string>
<string name="settings_app_name_hint">Novo nome</string>
<string name="settings_app_name_helper">O app do Magisk será reinstalado com este nome</string>
<string name="settings_app_name_error">Formato inválido</string>
<string name="settings_su_app_adb">Aplicativos e ADB</string>
<string name="settings_su_app">Apenas aplicativos</string>
<string name="settings_su_app_adb">Apps e ADB</string>
<string name="settings_su_app">Apenas apps</string>
<string name="settings_su_adb">Apenas ADB</string>
<string name="settings_su_disable">Desativado</string>
<string name="settings_su_request_10">10 segundos</string>
@ -160,33 +161,33 @@
<string name="settings_su_request_60">60 segundos</string>
<string name="superuser_access">Acesso de SuperUsuário</string>
<string name="auto_response">Resposta automática</string>
<string name="request_timeout">Tempo Limite da Solicitação</string>
<string name="request_timeout">Tempo limite da solicitação</string>
<string name="superuser_notification">Notificação de SuperUsuário</string>
<string name="settings_su_reauth_title">Autenticar novamente após a atualização</string>
<string name="settings_su_reauth_summary">Reautenticar permissões de SuperUsuário após atualizar aplicativo</string>
<string name="settings_su_tapjack_title">Ativar Proteção Contra Atividades Sobrepostas</string>
<string name="settings_su_tapjack_summary">A caixa de diálogo do SuperUsuário não responderá à entrada enquanto estiver obscurecida por qualquer outra janela ou sobreposição</string>
<string name="settings_su_biometric_title">Ativar Autenticação Biométrica</string>
<string name="settings_su_biometric_summary">Use a autenticação biométrica para permitir solicitações de SuperUsuário</string>
<string name="no_biometric">Dispositivo não suportado ou nenhuma configuração biométrica está ativada</string>
<string name="settings_su_reauth_title">Reautenticar após atualização</string>
<string name="settings_su_reauth_summary">Solicite permissões de SuperUsuário novamente após atualizar os apps</string>
<string name="settings_su_tapjack_title">Proteção contra atividades sobrepostas</string>
<string name="settings_su_tapjack_summary">A caixa de diálogo do SuperUsuário não responderá à entrada enquanto estiver oculta por qualquer outra janela ou sobreposição</string>
<string name="settings_su_auth_title">Autenticação de usuário</string>
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
<string name="settings_customization">Personalizações</string>
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o aplicativo</string>
<string name="settings_doh_title">Ativar DNS sobre HTTPS</string>
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
<string name="settings_doh_title">DNS sobre HTTPS</string>
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
<string name="multiuser_mode">Ativar Modo Multiusuário</string>
<string name="multiuser_mode">Modo Multiusuário</string>
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
<string name="settings_user_independent">Independente do usuário</string>
<string name="owner_only_summary">Somente o proprietário tem acesso ao SuperUsuário</string>
<string name="owner_manage_summary">Somente o proprietário pode gerenciar o acesso do SuperUsuário e receber pedidos de solicitação</string>
<string name="owner_only_summary">Somente o proprietário tem acesso root</string>
<string name="owner_manage_summary">Somente o proprietário pode gerenciar o acesso root e receber pedidos de solicitação</string>
<string name="user_independent_summary">Cada usuário tem suas próprias regras de root separadas</string>
<string name="mount_namespace_mode">Ativar Modo Namespace</string>
<string name="settings_ns_global">Namespace global</string>
<string name="settings_ns_requester">Herdar Namespace</string>
<string name="settings_ns_isolate">Namespace isolado</string>
<string name="mount_namespace_mode">Montar namespace</string>
<string name="settings_ns_global">Global</string>
<string name="settings_ns_requester">Herdado</string>
<string name="settings_ns_isolate">Individual</string>
<string name="global_summary">Todas as sessões root usam o namespace de montagem global</string>
<string name="requester_summary">As sessões root herdarão o namespace do solicitante</string>
<string name="isolate_summary">Cada sessão do SuperUsuário terá seu próprio namespace isolado</string>
<string name="isolate_summary">Cada sessão root terá seu próprio namespace individual</string>
<!--Notifications-->
<string name="update_channel">Atualizações do Magisk</string>
@ -194,8 +195,8 @@
<string name="updated_channel">Atualização concluída</string>
<string name="download_complete">Download concluído</string>
<string name="download_file_error">Erro ao baixar arquivo</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="updated_title">Magisk Atualizado</string>
<string name="magisk_update_title">Atualização do Magisk disponível!</string>
<string name="updated_title">Magisk atualizado</string>
<string name="updated_text">Toque para abrir o app</string>
<!--Toasts, Dialogs-->
@ -205,35 +206,35 @@
<string name="download">Baixar</string>
<string name="reboot">Reiniciar</string>
<string name="release_notes">Notas da atualização</string>
<string name="flashing">Fazendo Flash…</string>
<string name="flashing">Flashando</string>
<string name="done">Concluído!</string>
<string name="failure">Falha</string>
<string name="failure">Falhou!</string>
<string name="hide_app_title">Ocultando o app do Magisk…</string>
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>
<string name="complete_uninstall">Desinstalação completa</string>
<string name="restore_img">Restaurar imagens</string>
<string name="restore_img_msg">Restaurando…</string>
<string name="restore_done">Restauração concluída!</string>
<string name="restore_fail">O backup original não foi encontrado!</string>
<string name="restore_fail">O backup original não existe!</string>
<string name="setup_fail">Falha na instalação</string>
<string name="env_fix_title">Configuração adicional exigida</string>
<string name="env_fix_msg">Seu dispositivo exige uma configuração adicional para o Magisk funcionar corretamente. Deseja continuar e reiniciar?</string>
<string name="env_full_fix_msg">Seu dispositivo precisa refazer o flash do Magisk para funcionar corretamente. Reinstale o Magisk no aplicativo, o modo de recuperação não pode obter as devidas informações do dispositivo.</string>
<string name="env_full_fix_msg">Seu dispositivo precisa refazer o flash do Magisk para funcionar corretamente. Por favor, reinstale o Magisk no app, o modo Recovery não pode obter as devidas informações do dispositivo.</string>
<string name="setup_msg">Executando a configuração do ambiente…</string>
<string name="authenticate">Autenticar</string>
<string name="unsupport_magisk_title">Versão do Magisk não suportada</string>
<string name="unsupport_magisk_msg">Essa versão do app não suporta versão do Magisk inferior a %1$s.\n\nO app irá se comportar como se nenhum Magisk estivesse sido instalado. Por favor, atualize o Magisk assim que possível.</string>
<string name="unsupport_general_title">Estado Anormal</string>
<string name="unsupport_system_app_msg">Não há suporte para executar este app como um app do sistema. Por favor, reverta o app para um app do usuário.</string>
<string name="unsupport_magisk_msg">Esta versão do app não suporta a versão do Magisk inferior a %1$s.\n\nO app irá se comportar como se nenhum Magisk estivesse sido instalado. Por favor, atualize o Magisk assim que possível.</string>
<string name="unsupport_general_title">Estado anormal</string>
<string name="unsupport_system_app_msg">Não há suporte para executar este app como um app do sistema. Por favor, reverta o app para um app de usuário.</string>
<string name="unsupport_other_su_msg">Não foi possível detectar o binário \"su\" do Magisk. Por favor, remova qualquer outro root concorrente e/ou reinstale o Magisk.</string>
<string name="unsupport_external_storage_msg">O app do Magisk está instalado no armazenamento externo, Por favor, mova o app para o armazenamento interno.</string>
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar a funcionar porque o SuperUsuário foi perdido. Por favor, restaure o APK original.</string>
<string name="unsupport_external_storage_msg">O app do Magisk está instalado no armazenamento externo. Por favor, mova o app para o armazenamento interno.</string>
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar funcionando porque o root foi perdido. Por favor, restaure o APK original.</string>
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
<string name="external_rw_permission_denied">Autorize a permissão de armazenamento para ativar esta funcionalidade</string>
<string name="post_notifications_denied">Autorize a permissão de notificaçoes para ativar esta funcionalidade</string>
<string name="install_unknown_denied">Permita a "instalação apps desconhecidos" para ativar esta funcionalidade</string>
<string name="add_shortcut_title">Adicionar Atalho à Tela Inicial</string>
<string name="add_shortcut_msg">Depois de ocultar o app do Magisk, o seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
<string name="external_rw_permission_denied">Conceda permissão de armazenamento para ativar esta funcionalidade</string>
<string name="post_notifications_denied">Conceda permissão às notificações para ativar esta funcionalidade</string>
<string name="install_unknown_denied">Permita a opção "Instalar apps de fontes desconhecidas" para ativar esta funcionalidade</string>
<string name="add_shortcut_title">Adicionar atalho à tela inicial</string>
<string name="add_shortcut_msg">Após ocultar o app do Magisk, seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
<string name="app_not_found">Nenhum app encontrado para realizar esta ação</string>
<string name="reboot_apply_change">Reinicie para aplicar as mudanças</string>
<string name="restore_app_confirmation">Isso irá restaurar o app oculto do Magisk de volta para o app original. Deseja realmente fazer isso?</string>

View File

@ -167,9 +167,6 @@
<string name="settings_su_reauth_summary">Cere din nou permisiunile de superutilizator după actualizarea aplicațiilor</string>
<string name="settings_su_tapjack_title">Protecție față de tapjacking</string>
<string name="settings_su_tapjack_summary">Caseta de dialog pentru solicitarea permisiunilor de superutilizator nu va răspunde la input cât timp este ascunsă de orice altă fereastră sau suprapunere</string>
<string name="settings_su_biometric_title">Autentificare biometrică</string>
<string name="settings_su_biometric_summary">Folosește autentificarea biometrică pentru a permite cereri de superutilizator</string>
<string name="no_biometric">Dispozitiv nesuportat sau nu sunt activate setări biometrice</string>
<string name="settings_customization">Personalizare</string>
<string name="setting_add_shortcut_summary">Adaugă o comandă rapidă frumoasă în ecranul de pornire în cazul în care numele și pictograma sunt dificil de recunoscut după ascunderea aplicației</string>
<string name="settings_doh_title">DNS prin HTTPS</string>

View File

@ -167,9 +167,6 @@
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
<string name="settings_su_tapjack_title">Защита от перехвата нажатий</string>
<string name="settings_su_tapjack_summary">Окно запроса прав суперпользователя будет неактивно пока активированы наложения экрана</string>
<string name="settings_su_biometric_title">Биометрическая аутентификация</string>
<string name="settings_su_biometric_summary">Принимать запросы прав суперпользователя только после биометрической аутентификации</string>
<string name="no_biometric">Функция не поддерживается устройством или не заданы настройки блокировки экрана</string>
<string name="settings_customization">Персонализация</string>
<string name="setting_add_shortcut_summary">Добавить ярлык на рабочий стол для удобного восприятия приложения после его скрытия</string>
<string name="settings_doh_title">DNS поверх HTTPS</string>

View File

@ -107,6 +107,7 @@
<string name="reboot_bootloader">Reštartovať do Bootloader</string>
<string name="reboot_download">Reštartovať do Download</string>
<string name="reboot_edl">Reštartovať do EDL</string>
<string name="reboot_safe_mode">Núdzový režim</string>
<string name="module_version_author">%1$s od %2$s</string>
<string name="module_state_remove">Odstrániť</string>
<string name="module_state_restore">Obnoviť</string>
@ -170,9 +171,9 @@
<string name="settings_su_reauth_summary">Opätovne vyzve na udelenie oprávnení Superužívateľa po upgrade aplikácie</string>
<string name="settings_su_tapjack_title">Ochrana pred tapjackingom</string>
<string name="settings_su_tapjack_summary">Dialógové okno superužívateľa nebude reagovať na zadanie, ak je zakryté alebo prekryté iným oknom</string>
<string name="settings_su_biometric_title">Biometrické overenie</string>
<string name="settings_su_biometric_summary">Použije biometrickú autentifikáciu na povolenie žiadostí superužívateľa</string>
<string name="no_biometric">Nepodporované zariadenie alebo žiadne biometrické nastavenia nie sú povolené</string>
<string name="settings_su_auth_title">Overenie používateľa</string>
<string name="settings_su_auth_summary">Žiadosť o overenie používateľa počas požiadaviek Superužívateľa</string>
<string name="settings_su_auth_insecure">V zariadení nie je nakonfigurovaná žiadna metóda overovania</string>
<string name="settings_customization">Prispôsobenie</string>
<string name="setting_add_shortcut_summary">V prípade, že sa po skrytí apky názov a ikona ťažko rozpoznávajú, pridať na domovskú obrazovku odkaz</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@ -107,6 +107,7 @@
<string name="reboot_bootloader">Rinis te Bootloader</string>
<string name="reboot_download">Rinis te Download</string>
<string name="reboot_edl">Rinis te EDL</string>
<string name="reboot_safe_mode">Rinis në safe mode</string>
<string name="module_version_author">%1$s nga %2$s</string>
<string name="module_state_remove">Hiqe</string>
<string name="module_state_restore">Rikëthe</string>
@ -170,9 +171,6 @@
<string name="settings_su_reauth_summary">Ri-vërtetoni lejet e super-përdoruesit pas azhurnimit të aplikacionit</string>
<string name="settings_su_tapjack_title">Aktivizo mbrojtjen tapjacking</string>
<string name="settings_su_tapjack_summary">Dialogu i menjëhershëm i super-përdoruesit nuk do ti përgjigjet hyrjes ndërsa është i errësuar nga ndonjë dritare ose mbivendosje tjetër</string>
<string name="settings_su_biometric_title">Aktivizo vërtetimin biometrik</string>
<string name="settings_su_biometric_summary">Përdorni vërtetimin biometrik për të lejuar kërkesat e super-përdoruesit</string>
<string name="no_biometric">Pajisja e pambështetur ose cilësimet biometrike nuk janë të aktivizuara</string>
<string name="settings_customization">Personalizimi</string>
<string name="setting_add_shortcut_summary">Shtoni një shkurtore mjaft të mirë në ekranin fillestar në rast se emri dhe ikona janë të vështira për tu njohur pasi keni fshehur aplikacionin</string>
<string name="settings_doh_title">DNS mbi HTTPS</string>
@ -191,7 +189,10 @@
<string name="global_summary">Të gjitha sesionet rrënjë përdorin hapësirën globale të emrave të montimit</string>
<string name="requester_summary">Seancat rrënjësore do të trashëgojnë hapësirën e emrave të kërkuesit të tyre</string>
<string name="isolate_summary">Çdo sesion rrënjë do të ketë hapësirën e vet të izoluar të emrave</string>
<string name="settings_su_auth_title">Vërtetimi i përdoruesit</string>
<string name="settings_su_auth_summary">Kërkoni vërtetimin e përdoruesit gjatë kërkesave të Superpërdoruesit</string>
<string name="settings_su_auth_insecure">Asnjë metodë vërtetimi nuk është konfiguruar në pajisje</string>
<!--Notifications-->
<string name="update_channel">Përditësimet e magisk</string>
<string name="updated_channel">Përditësimi përfundoi</string>

View File

@ -151,9 +151,6 @@
<string name="settings_su_reauth_summary">Återautentisera superuser-rättigheter efter en applikationsuppdatering</string>
<string name="settings_su_tapjack_title">Aktivera Tapjacking-skydd</string>
<string name="settings_su_tapjack_summary">Superuser-dialogrutan kommer inte att lyssna på någon input om den är dold eller övertäckt utav något annat fönster.</string>
<string name="settings_su_biometric_title">Aktivera biometriskt autentisering</string>
<string name="settings_su_biometric_summary">Använd biometriskt autentisering för att tillåta förfrågan om superuser-tillgång</string>
<string name="no_biometric">Denna enhet stöds ej eller så är inte biometrisk autentisering aktiverad</string>
<string name="settings_customization">Anpassning</string>
<string name="setting_add_shortcut_summary">Lägg till en snygg genväg på startskärmen om namnet och ikonen är svåra att känna igen efter att appen har döljts</string>
<string name="settings_doh_title">DNS över HTTPS</string>

View File

@ -163,9 +163,6 @@
<string name="settings_su_reauth_summary">Ask for Superuser permissions again after upgrading apps</string>
<string name="settings_su_tapjack_title">Tapjacking Protection</string>
<string name="settings_su_tapjack_summary">The Superuser prompt dialog will not respond to input while obscured by any other window or overlay</string>
<string name="settings_su_biometric_title">Biometric Authentication</string>
<string name="settings_su_biometric_summary">Use biometric authentication to allow Superuser requests</string>
<string name="no_biometric">Unsupported device or no biometric settings are enabled</string>
<string name="settings_customization">Customization</string>
<string name="setting_add_shortcut_summary">Add a pretty shortcut to the home screen in case the name and icon are difficult to recognize after hiding the app</string>
<string name="settings_doh_title">DNS over HTTPS</string>

View File

@ -152,9 +152,6 @@
<string name="settings_su_reauth_summary">பயன்பாட்டு மேம்படுத்தல்களுக்குப் பிறகு சூப்பர் யூசர் அனுமதிகளை மீண்டும் அங்கீகரிக்கவும்</string>
<string name="settings_su_tapjack_title">டாப்ஜாகிங் பாதுகாப்பை இயக்கு</string>
<string name="settings_su_tapjack_summary">வேறு எந்த சாளரத்தாலும் அல்லது மேலடுக்கினாலும் மறைக்கப்படும்போது சூப்பர் யூசர் வரியில் உரையாடல் உள்ளீட்டிற்கு பதிலளிக்காது</string>
<string name="settings_su_biometric_title">பயோமெட்ரிக் அங்கீகாரத்தை இயக்கு</string>
<string name="settings_su_biometric_summary">சூப்பர் யூசர் கோரிக்கைகளை அனுமதிக்க பயோமெட்ரிக் அங்கீகாரத்தைப் பயன்படுத்தவும்</string>
<string name="no_biometric">ஆதரிக்கப்படாத சாதனம் அல்லது பயோமெட்ரிக் அமைப்புகள் எதுவும் செயல்படுத்தப்படவில்லை</string>
<string name="settings_customization">தனிப்பயனாக்கம்</string>
<string name="setting_add_shortcut_summary">பயன்பாட்டை மறைத்தபின் பெயர் மற்றும் ஐகான் அடையாளம் காண கடினமாக இருந்தால் முகப்புத் திரையில் அழகான குறுக்குவழியைச் சேர்க்கவும்</string>
<string name="settings_doh_title">HTTPS வழியாக டி.என்.எஸ்</string>

Some files were not shown because too many files have changed in this diff Show More