Compare commits

...

344 Commits

Author SHA1 Message Date
topjohnwu
0495468d02 Release new canary build 2024-07-24 23:13:21 -07:00
topjohnwu
300a2a242c Add release script 2024-07-24 23:10:57 -07:00
topjohnwu
33aebb5976 Stop embedding executables 2024-07-24 22:49:48 -07:00
pndwal
b3d6809c0b Update README.MD
Remove redundant Canary changelog link
2024-07-24 19:04:50 -07:00
LoveSy
461f7e9f89 Use metadata even if it is f2fs 2024-07-24 19:02:35 -07:00
LoveSy
9cc50b20d8 Correctly handle comments in sepolicy.rule 2024-07-24 19:02:25 -07:00
LoveSy
f488e9df8f Fix sepolicy rule path 2024-07-24 19:02:12 -07:00
LoveSy
0dc596e206 Update Chinese translation 2024-07-24 19:01:59 -07:00
topjohnwu
c3bf03190b Use K2 in kapt 2024-07-24 17:06:41 -07:00
topjohnwu
021ae891a9 Update dependencies 2024-07-24 16:53:15 -07:00
topjohnwu
9c03514eb1 Create :app:clean task 2024-07-24 16:46:47 -07:00
topjohnwu
eb74b266e1 Do not modify args
Close #8242
2024-07-24 16:37:22 -07:00
topjohnwu
80eb6ff25a Update README 2024-07-23 21:37:04 -07:00
topjohnwu
7b81e2d2d1 Release new canary build 2024-07-23 17:23:50 -07:00
topjohnwu
a8789073f1 Run copy_preinit_files in run_migrations 2024-07-23 02:21:49 -07:00
残页
c8fe0f5524 Catch possible exceptions when the receiver is already unregistered 2024-07-23 02:06:15 -07:00
vvb2060
d33b077a13 Remove NVBASE
We only move /cache/data_adb/magisk and /data/magisk to /data/adb/magisk (#7638), so NVBASE is redundant and we can just use MAGISKBIN.
2024-07-23 02:03:47 -07:00
vvb2060
2282365cf8 clean code 2024-07-23 02:02:56 -07:00
vvb2060
9a00b7b942 update copy_preinit_files 2024-07-23 02:02:56 -07:00
vvb2060
d54baadbed Use ro.crypto.metadata.enabled 2024-07-23 02:02:56 -07:00
LoveSy
0869a90fe3 Use symlink to setup preinit 2024-07-23 02:02:56 -07:00
LoveSy
2754b1dcf8 Add comment about the choice 2024-07-23 02:02:56 -07:00
LoveSy
0db6314661 Refactor preinit finding 2024-07-23 02:02:56 -07:00
topjohnwu
b5d2ef18e8 Move more data and function into HookContext 2024-07-22 20:36:55 -07:00
topjohnwu
6e22476acc Update test scripts 2024-07-22 03:39:04 -07:00
topjohnwu
b26db8cee6 Switch over to ANDROID_HOME
Keep ANDROID_SDK_ROOT as a fallback
2024-07-21 00:53:13 -07:00
topjohnwu
33cb39c8af Minor code changes for hook.cpp 2024-07-21 00:52:43 -07:00
LoveSy
f247759a6e No need _orig to call backup 2024-07-20 21:36:26 -07:00
LoveSy
de7e5bdfe7 Update comments 2024-07-20 21:36:26 -07:00
LoveSy
53a8ba8cfe Use hookJniNativeMethods to hook zygote pre/post fork 2024-07-20 21:36:26 -07:00
LoveSy
f2d057baba Refine hookJniNativeMethods 2024-07-20 21:36:26 -07:00
LoveSy
93bcf2cd25 Correct debug symbol configuration 2024-07-20 20:29:58 -07:00
LoveSy
6d82515cfc No default features of pb-rs 2024-07-20 20:29:38 -07:00
topjohnwu
a177d3b022 Fix AVD test on API 23 2024-07-20 15:08:06 -07:00
topjohnwu
92b2e06e57 Increase cgu on debug builds 2024-07-20 04:59:20 -07:00
topjohnwu
f919bb0e99 Minor changes 2024-07-20 04:52:25 -07:00
topjohnwu
054971e899 Add permissions 2024-07-20 03:43:06 -07:00
topjohnwu
93c3d36452 Add Cuttlefish tests in CI 2024-07-20 03:10:18 -07:00
topjohnwu
4c38af994d Sync native and Java implementation 2024-07-19 23:22:08 -07:00
topjohnwu
bbb8efe92c Support Cuttlefish 2024-07-19 22:08:35 -07:00
topjohnwu
659dd09723 Do not modify system-images contents when patching 2024-07-19 16:47:12 -07:00
LoveSy
4931825912 Fix zygisk v5 2024-07-17 10:52:16 -07:00
topjohnwu
ef81cdab4f Prebuild Busybox
Prebuild with tools in ndk-box-kitchen
2024-07-17 02:58:31 -07:00
topjohnwu
7c0b25cad9 Release new canary build 2024-07-12 15:54:16 -07:00
topjohnwu
b38ab2a7d6 Use K2 to compile buildSrc
Make all Kotlin source code build with K2.
K2 seems to have bugs with lazy property assignment, revert it to set().
2024-07-12 15:27:04 -07:00
LoveSy
a97191052b Upgrade gradle 2024-07-12 13:46:06 -07:00
vvb2060
2963d4ca9e Rewrite get_manager 2024-07-12 13:45:48 -07:00
vvb2060
6aab856de7 Enhanced denylist app id tracking 2024-07-12 13:45:48 -07:00
topjohnwu
94d1c66f8a Make AVD test timeout at 10 minutes 2024-07-12 11:39:11 -07:00
topjohnwu
7ff4d7608e Update dependencies 2024-07-11 23:28:01 -07:00
sn-o-w
46ef915c83 Update Romanian 2024-07-11 22:31:32 -07:00
LoveSy
63b0a0d96b Fix incomplete native debug symbols
See https://github.com/android/ndk/issues/2039
2024-07-11 22:31:09 -07:00
LoveSy
ea4cabdfc5 Use simple property assignment 2024-07-11 22:28:59 -07:00
LoveSy
0185ddf577 Fix building on higher version of jdk 2024-07-11 22:28:59 -07:00
topjohnwu
ddae568741 Move SplashActivity logic into core module 2024-07-11 22:08:01 -07:00
topjohnwu
fcb7ebb090 Cleanup resources 2024-07-11 17:58:52 -07:00
topjohnwu
8d446fcc16 Move all core code into the same parent package 2024-07-11 16:49:01 -07:00
topjohnwu
881d3b5221 App migration minor refactoring 2024-07-11 16:28:56 -07:00
topjohnwu
fe9ec3bc6d Move app initialization routine into core module 2024-07-11 16:10:49 -07:00
topjohnwu
480198dcd0 Improve package migration 2024-07-11 15:50:40 -07:00
topjohnwu
4ab7bc0d97 Minor SettingsItem cleanup 2024-07-11 02:44:38 -07:00
topjohnwu
7173693d1b Use platform LocaleManager if possible 2024-07-11 02:44:38 -07:00
topjohnwu
6b81716440 Update stub implementation 2024-07-11 02:44:38 -07:00
topjohnwu
88e8e15607 Create singleton AppContext 2024-07-11 02:44:38 -07:00
LoveSy
69181a6b72 Fix wrong sepolicy rule 2024-07-08 12:09:45 -07:00
Wang Han
b11b81122a Tighten rules for tmpfs file
Before magiskd is executed, all files in magisk tmpfs still shares
tmpfs label. This commit tightens the rule to only allow init, zygote
and shell to access magisk tmpfs files. Zygotes rules is needed
because lower Android versions don't have rule for zygote itself
using memfd even memfd is supported in kernel.
2024-07-08 12:06:49 -07:00
Wang Han
648e3ee36b Update build.yml 2024-07-08 12:02:51 -07:00
LoveSy
724b94f320 Update README.MD (#8192)
Co-authored-by: 南宫雪珊 <vvb2060@gmail.com>
2024-07-08 12:02:14 -07:00
topjohnwu
a6e65f9a7e Fix building release builds 2024-07-06 01:55:09 -07:00
topjohnwu
af5c4d09c4 Re-enable nonTransitiveRClass 2024-07-06 01:31:43 -07:00
topjohnwu
872394cb58 Decouple core module from AppCompatActivity 2024-07-05 00:49:26 -07:00
topjohnwu
fcbbe9a22e Move :app to :app:apk 2024-07-04 02:27:20 -07:00
topjohnwu
b168163ef0 Move :stub to :app:stub 2024-07-04 00:21:34 -07:00
topjohnwu
3e38b8fed1 Separate core codebase into its own module
- Separate UI specific code and resources outside of the core
  application logic
- Allow most of the code to move forward and use KSP for annotation
  processing and isolate rotton code that is stuck with databinding
- Make full UI rewrite more feasible
2024-07-04 00:02:42 -07:00
kubalav
f90c548f27 Update Slovak translation 2024-07-03 22:55:31 -07:00
igor
c981c40218 Update Portuguese translation 2024-07-03 22:55:12 -07:00
Rom
dcbf37c5e8 Update French translation
To match with changes of "Add option to disable filename randomization"
2024-07-03 22:54:47 -07:00
topjohnwu
300b233a27 Simplify MediaStoreUtils 2024-07-02 17:15:27 -07:00
topjohnwu
e32cd03d0b Update docs to cover riscv64 2024-07-02 14:53:46 -07:00
LoveSy
a07b9315a5 Add riscv64 support 2024-07-02 14:34:22 -07:00
topjohnwu
e9694c6195 Add option to disable filename randomization 2024-07-02 14:28:26 -07:00
Wang Han
4a2a37c87a Catch PendingIntent.CanceledException caused by send()
Accidentally changed in 050a073.
2024-07-02 14:24:27 -07:00
vvb2060
7dca5b831a check empty init_boot partition
For upgrading devices that continue to use Android 12 or older kernel versions, the generic ramdisk remains where it was with no requirement for a new init_boot image.
2024-07-02 14:23:28 -07:00
topjohnwu
be5ff68140 Exclude apache commons codec resources 2024-07-01 18:56:08 -07:00
topjohnwu
59f40d5fe5 Move manager.sh to app_functions.sh 2024-07-01 18:42:05 -07:00
topjohnwu
1fbd053a42 Prevent polluting global shell env 2024-07-01 18:20:21 -07:00
topjohnwu
966c6314f8 Cleanup configs 2024-07-01 17:23:48 -07:00
Li Hua
c92204c724 Update Simplified Chinese Translation
Signed-off-by: Li Hua <lihua@email.com>
2024-07-01 14:51:06 -07:00
igor
bb9947d4d2 Update Portuguese translation 2024-07-01 14:50:52 -07:00
Wang Han
7c8cdb4ad6 Set default visibility of restart button to GONE
This fixes the issue that button still shows when installation fails.
2024-07-01 14:50:34 -07:00
Wang Han
bd7f9c9e46 Unset FLAG_ACTIVITY_NO_HISTORY for SuRequestActivity
This fixes device credential confirm activity on OnePlus devices
because SuRequestActivity is accidentally finished before a valid
response is delivered to it.
2024-07-01 14:50:09 -07:00
vvb2060
9a33a4dfe2 Fix StackOverflowError
Now field from base class java.io.ByteArrayOutputStream shadows the property with custom getter from derived class com.topjohnwu.magisk.core.utils.AXML.RawByteStream. This behavior will be changed soon in favor of the property. Please use explicit cast to java.io.ByteArrayOutputStream if you wish to preserve current behavior. See https://youtrack.jetbrains.com/issue/KT-55017 for details
2024-07-01 14:36:20 -07:00
topjohnwu
47e918bc92 Fix vbmeta.img tar patching 2024-07-01 03:20:09 -07:00
Wang Han
c194168d9b Fix item match when extracting lib from stub
Close #8083.
2024-06-29 22:14:24 -07:00
topjohnwu
cacc60b1ac Migrate to Apache commons-compress
Close #8121
2024-06-29 22:11:02 -07:00
topjohnwu
52063b3652 Update to Kotlin 2.0.0 2024-06-29 17:04:40 -07:00
topjohnwu
85a4eaff59 Release new canary build 2024-06-28 16:16:41 -07:00
topjohnwu
45fa1fce70 Update libsu 2024-06-28 15:45:40 -07:00
loselarry
2112c916f5 chore: remove repetitive word
Signed-off-by: loselarry <bikangning@yeah.net>
2024-06-22 19:17:20 -07:00
LoveSy
d6e159bff9 Use pidfd in more senarios 2024-06-22 19:16:58 -07:00
LoveSy
2f710a564f allow more -v for build.py for more verbose output 2024-06-22 19:16:37 -07:00
Fontan030
27cfc4945c Kazakh translation 2024-06-22 18:53:14 -07:00
eklerismunir
7cdada92c8 Improve azerbaijani locales and add the missing strings 2024-06-22 18:52:59 -07:00
topjohnwu
8f1e57d4f9 16k pages on x64 is broken 2024-06-22 18:51:44 -07:00
topjohnwu
8178666b49 Add 16k page testing in CI 2024-06-21 03:13:16 -07:00
topjohnwu
313532dcaa Disable verbose output by default 2024-06-21 02:45:48 -07:00
topjohnwu
2f8f3dc266 Add new test cases 2024-06-20 21:39:30 -07:00
topjohnwu
df6ada5ce3 Update avd_test to support custom type 2024-06-20 18:25:49 -07:00
topjohnwu
a89b9e6af1 Support 16K page size 2024-06-18 22:04:53 -07:00
topjohnwu
23ed275614 Update to ONDK r27.2 2024-06-18 14:34:30 -07:00
topjohnwu
cfd1e0cf22 Update libsu and dependencies 2024-06-18 11:26:18 -07:00
topjohnwu
eb400f19b1 Support Python 3.12+ 2024-06-18 03:36:16 -07:00
LoveSy
19f15f16f6 Use icf to further minimize binary size 2024-06-10 14:47:26 -07:00
topjohnwu
e158cfddfa Update system_properties 2024-06-07 13:51:24 -07:00
pndwal
d0cf93a08d Fix typos install.md 2024-06-06 21:12:18 -07:00
LoveSy
08ad0e74dd Upgrade deps
Co-authored-by: vvb2060 <vvb2060@gmail.com>
2024-06-06 21:11:52 -07:00
topjohnwu
722374a024 Update system_properties 2024-06-05 18:42:30 -07:00
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
611 changed files with 10811 additions and 10276 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

@@ -6,7 +6,6 @@ on:
paths:
- "app/**"
- "native/**"
- "stub/**"
- "buildSrc/**"
- "build.py"
- "gradle.properties"
@@ -17,12 +16,12 @@ 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-13]
steps:
- name: Check out
uses: actions/checkout@v4
@@ -30,99 +29,167 @@ jobs:
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
path: app/apk/build/outputs
compression-level: 9
test:
name: Test on ${{ matrix.api }}
runs-on: macos-13
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
avd-test:
name: Test API ${{ matrix.version }} (x86_64)
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
api: [23, 26, 28, 29, 34]
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
type: [""]
include:
- version: 35
type: "google_apis"
steps:
- name: Check out
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3
uses: actions/setup-python@v4
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 bash
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: Run AVD test
timeout-minutes: 10
env:
AVD_TEST_VERBOSE: 1
run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }}
avd-test-32:
name: Test API ${{ matrix.version }} (x86)
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
version: [23, 24, 25, 26, 27, 28, 29, 30]
steps:
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
- 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: Run AVD test
timeout-minutes: 10
env:
FORCE_32_BIT: 1
AVD_TEST_VERBOSE: 1
run: scripts/avd_test.sh ${{ matrix.version }}
cf_test:
name: Test ${{ matrix.branch }} (${{ matrix.target }})
runs-on: ubuntu-24.04
needs: build
env:
CF_HOME: /home/runner/aosp_cf_phone
strategy:
fail-fast: false
matrix:
include:
- branch: "aosp-main"
target: "aosp_cf_x86_64_phone-trunk_staging-userdebug"
steps:
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: ${{ github.sha }}
path: out
- name: Setup Cuttlefish environment
run: |
scripts/cuttlefish.sh setup
scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.target }}
- name: Run Cuttlefish test
timeout-minutes: 10
run: su $USER -c 'scripts/cuttlefish.sh test'
- name: Upload logs on error
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: "cvd-logs"
path: |
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/logs
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/cuttlefish_config.json

3
.gitignore vendored
View File

@@ -3,8 +3,9 @@ out
*.jks
*.apk
/config.prop
/notes.md
/update.sh
/dict.txt
/app/dict.txt
# Built binaries
native/out

12
.gitmodules vendored
View File

@@ -1,9 +1,6 @@
[submodule "selinux"]
path = native/src/external/selinux
url = https://github.com/topjohnwu/selinux.git
[submodule "busybox"]
path = native/src/external/busybox
url = https://github.com/topjohnwu/ndk-busybox.git
[submodule "lz4"]
path = native/src/external/lz4
url = https://github.com/lz4/lz4.git
@@ -13,18 +10,12 @@
[submodule "xz"]
path = native/src/external/xz
url = https://github.com/xz-mirror/xz.git
[submodule "pcre"]
path = native/src/external/pcre
url = https://android.googlesource.com/platform/external/pcre
[submodule "libcxx"]
path = native/src/external/libcxx
url = https://github.com/topjohnwu/libcxx.git
[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
@@ -37,6 +28,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,16 +18,18 @@ 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.3-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v26.3)
[![](https://img.shields.io/badge/Magisk%20Beta-v26.3-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v26.3)
[![](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)
Click the icon below to download Magisk apk.
[![](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://github.com/topjohnwu/Magisk/releases/tag/canary-27006)
## Useful Links
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
## Bug Reports
@@ -41,8 +43,8 @@ For Magisk app crashes, record and upload the logcat when the crash occurs.
Default string resources for the Magisk app and its stub APK are located here:
- `app/src/main/res/values/strings.xml`
- `stub/src/main/res/values/strings.xml`
- `app/core/src/main/res/values/strings.xml`
- `app/stub/src/main/res/values/strings.xml`
Translate each and place them in the respective locations (`[module]/src/main/res/values-[lang]/strings.xml`).

11
app/.gitignore vendored
View File

@@ -1,11 +0,0 @@
*.iml
.gradle
/local.properties
.idea/
/build
*.hprof
.externalNativeBuild/
*.apk
src/*/assets
src/*/jniLibs
src/*/resources

1
app/apk/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

69
app/apk/build.gradle.kts Normal file
View File

@@ -0,0 +1,69 @@
plugins {
id("com.android.application")
kotlin("android")
kotlin("plugin.parcelize")
kotlin("kapt")
id("androidx.navigation.safeargs.kotlin")
}
setupAppCommon()
kapt {
correctErrorTypes = true
useBuildCache = true
mapDiagnosticLocations = true
javacOptions {
option("-Xmaxerrs", 1000)
}
}
android {
namespace = "com.topjohnwu.magisk"
defaultConfig {
applicationId = "com.topjohnwu.magisk"
vectorDrawables.useSupportLibrary = true
versionName = Config.version
versionCode = Config.versionCode
ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
debugSymbolLevel = "FULL"
}
}
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles("proguard-rules.pro")
}
}
buildFeatures {
dataBinding = true
}
}
dependencies {
implementation(project(":app:core"))
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
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")
val vNav = "2.7.7"
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.transition:transition:1.5.1")
implementation("androidx.fragment:fragment-ktx:1.8.2")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
// Make sure kapt runs with a proper kotlin-stdlib
kapt(kotlin("stdlib"))
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application android:localeConfig="@xml/locale_config">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ui.surequest.SuRequestActivity"
android:directBootAware="true"
android:exported="false"
android:taskAffinity=""
tools:ignore="AppLinkUrlError">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

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
@@ -8,7 +10,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.navigation.NavDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.databinding.ObservableHost
import com.topjohnwu.magisk.events.BackPressEvent
import com.topjohnwu.magisk.events.DialogBuilder

View File

@@ -1,11 +1,13 @@
package com.topjohnwu.magisk.arch
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.res.use
import androidx.core.view.WindowCompat
@@ -18,14 +20,20 @@ import com.google.android.material.snackbar.Snackbar
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.base.ActivityExtension
import com.topjohnwu.magisk.core.base.IActivityExtension
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.reflectField
import com.topjohnwu.magisk.core.wrap
import rikka.insets.WindowInsetsHelper
import rikka.layoutinflater.view.LayoutInflaterFactory
abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModelHolder {
abstract class UIActivity<Binding : ViewDataBinding>
: AppCompatActivity(), ViewModelHolder, IActivityExtension {
protected lateinit var binding: Binding
protected abstract val layoutRes: Int
override val extension = ActivityExtension(this)
protected val binded get() = ::binding.isInitialized
@@ -36,10 +44,23 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
AppCompatDelegate.setDefaultNightMode(Config.darkTheme)
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base.wrap())
}
override fun onCreate(savedInstanceState: Bundle?) {
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
.addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
extension.onCreate(savedInstanceState)
if (isRunningAsStub) {
// Overwrite private members to avoid nasty "false" stack traces being logged
val delegate = delegate
val clz = delegate.javaClass
clz.reflectField("mActivityHandlesConfigFlagsChecked").set(delegate, true)
clz.reflectField("mActivityHandlesConfigFlags").set(delegate, 0)
}
super.onCreate(savedInstanceState)
startObserveLiveData()
@@ -70,6 +91,11 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
extension.onSaveInstanceState(outState)
}
fun setContentView() {
binding = DataBindingUtil.setContentView<Binding>(this, layoutRes).also {
it.setVariable(BR.viewModel, viewModel)

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

@@ -7,26 +7,27 @@ import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.core.R as CoreR
class DarkThemeDialog : DialogBuilder {
override fun build(dialog: MagiskDialog) {
val activity = dialog.ownerActivity!!
dialog.apply {
setTitle(R.string.settings_dark_mode_title)
setMessage(R.string.settings_dark_mode_message)
setTitle(CoreR.string.settings_dark_mode_title)
setMessage(CoreR.string.settings_dark_mode_message)
setButton(MagiskDialog.ButtonType.POSITIVE) {
text = R.string.settings_dark_mode_light
text = CoreR.string.settings_dark_mode_light
icon = R.drawable.ic_day
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_NO, activity) }
}
setButton(MagiskDialog.ButtonType.NEUTRAL) {
text = R.string.settings_dark_mode_system
text = CoreR.string.settings_dark_mode_system
icon = R.drawable.ic_day_night
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, activity) }
}
setButton(MagiskDialog.ButtonType.NEGATIVE) {
text = R.string.settings_dark_mode_dark
text = CoreR.string.settings_dark_mode_dark
icon = R.drawable.ic_night
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_YES, activity) }
}

View File

@@ -1,10 +1,9 @@
package com.topjohnwu.magisk.dialog
import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.home.HomeViewModel
@@ -27,7 +26,7 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
resetButtons()
setCancelable(false)
}
(dialog.ownerActivity as BaseActivity).lifecycleScope.launch {
dialog.activity.lifecycleScope.launch {
MagiskInstaller.FixEnv {
dialog.dismiss()
}.exec()
@@ -40,8 +39,8 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
}
if (code == 2 || // No rules block, module policy not loaded
Info.env.versionCode != BuildConfig.VERSION_CODE ||
Info.env.versionString != BuildConfig.VERSION_NAME) {
Info.env.versionCode != BuildConfig.APP_VERSION_CODE ||
Info.env.versionString != BuildConfig.APP_VERSION_NAME) {
dialog.setMessage(R.string.env_full_fix_msg)
dialog.setButton(MagiskDialog.ButtonType.POSITIVE) {
text = android.R.string.ok

View File

@@ -2,8 +2,8 @@ package com.topjohnwu.magisk.dialog
import android.net.Uri
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.module.ModuleViewModel
import com.topjohnwu.magisk.view.MagiskDialog

View File

@@ -1,10 +1,10 @@
package com.topjohnwu.magisk.dialog
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.R
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

@@ -13,6 +13,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
import com.topjohnwu.magisk.core.R as CoreR
abstract class MarkDownDialog : DialogBuilder {
@@ -30,7 +31,7 @@ abstract class MarkDownDialog : DialogBuilder {
ServiceLocator.markwon.setMarkdown(tv, text)
} catch (e: IOException) {
Timber.e(e)
tv.setText(R.string.download_file_error)
tv.setText(CoreR.string.download_file_error)
}
}
}

View File

@@ -1,11 +1,11 @@
package com.topjohnwu.magisk.dialog
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.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.ui.flash.FlashFragment
import com.topjohnwu.magisk.view.MagiskDialog
class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() {
@@ -22,9 +22,9 @@ 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)
val module = Subject.Module(item, install)
module.piCreator = FlashFragment::installIntent
DownloadEngine.startWithActivity(activity, module)
}
val title = context.getString(R.string.repo_install_title,

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.dialog
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.view.MagiskDialog

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.dialog
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.view.MagiskDialog

View File

@@ -3,8 +3,8 @@ package com.topjohnwu.magisk.dialog
import android.app.ProgressDialog
import android.content.Context
import android.widget.Toast
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.events.DialogBuilder
import com.topjohnwu.magisk.ui.flash.FlashFragment

View File

@@ -11,6 +11,7 @@ import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.arch.ViewEvent
import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.base.relaunch
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.view.MagiskDialog
@@ -47,7 +48,7 @@ class ShowUIEvent(private val delegate: View.AccessibilityDelegate?)
class RecreateEvent : ViewEvent(), ActivityExecutor {
override fun invoke(activity: UIActivity<*>) {
activity.recreate()
activity.relaunch()
}
}
@@ -56,8 +57,7 @@ class AuthEvent(
) : ViewEvent(), ActivityExecutor {
override fun invoke(activity: UIActivity<*>) {
activity.authenticateCallback = { if (it) callback() }
activity.requestAuthenticate.launch(Unit)
activity.withAuthentication { if (it) callback() }
}
}

View File

@@ -1,6 +1,7 @@
package com.topjohnwu.magisk.ui
import android.Manifest
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.ApplicationInfo
@@ -8,6 +9,7 @@ import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.forEach
import androidx.core.view.isGone
@@ -17,29 +19,35 @@ import androidx.navigation.NavDirections
import com.topjohnwu.magisk.MainDirections
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.NavigationActivity
import com.topjohnwu.magisk.arch.startAnimations
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.SplashController
import com.topjohnwu.magisk.core.base.SplashScreenHost
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.model.module.LocalModule
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.tasks.AppMigration
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
import com.topjohnwu.magisk.ui.theme.Theme
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Shortcuts
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import com.topjohnwu.magisk.core.R as CoreR
class MainViewModel : BaseViewModel()
class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
class MainActivity : NavigationActivity<ActivityMainMd2Binding>(), SplashScreenHost {
override val layoutRes = R.layout.activity_main_md2
override val viewModel by viewModel<MainViewModel>()
override val navHostId: Int = R.id.main_nav_host
override val splashController = SplashController(this)
override val snackbarView: View
get() {
val fragmentOverride = currentFragment?.snackbarView
@@ -57,12 +65,23 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
private var isRootFragment = true
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(Theme.selected.themeRes)
splashController.preOnCreate()
super.onCreate(savedInstanceState)
splashController.onCreate(savedInstanceState)
}
override fun onResume() {
super.onResume()
splashController.onResume()
}
@SuppressLint("InlinedApi")
override fun showMainUI(savedInstanceState: Bundle?) {
override fun onCreateUi(savedInstanceState: Bundle?) {
setContentView()
showUnsupportedMessage()
askForHomeShortcut()
checkStubComponent()
// Ask permission to post notifications for background update check
if (Config.checkUpdate) {
@@ -169,11 +188,36 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
}
}
@SuppressLint("InlinedApi")
override fun showInvalidStateMessage(): Unit = runOnUiThread {
MagiskDialog(this).apply {
setTitle(CoreR.string.unsupport_nonroot_stub_title)
setMessage(CoreR.string.unsupport_nonroot_stub_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) {
text = CoreR.string.install
onClick {
withPermission(REQUEST_INSTALL_PACKAGES) {
if (!it) {
toast(CoreR.string.install_unknown_denied, Toast.LENGTH_SHORT)
showInvalidStateMessage()
} else {
lifecycleScope.launch {
AppMigration.restore(this@MainActivity)
}
}
}
}
}
setCancelable(false)
show()
}
}
private fun showUnsupportedMessage() {
if (Info.env.isUnsupported) {
MagiskDialog(this).apply {
setTitle(R.string.unsupport_magisk_title)
setMessage(R.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
setTitle(CoreR.string.unsupport_magisk_title)
setMessage(CoreR.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
setCancelable(false)
}.show()
@@ -184,8 +228,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
?.filterNot { File("$it/magisk").exists() }
?.any { File("$it/su").exists() } == true) {
MagiskDialog(this).apply {
setTitle(R.string.unsupport_general_title)
setMessage(R.string.unsupport_other_su_msg)
setTitle(CoreR.string.unsupport_general_title)
setMessage(CoreR.string.unsupport_other_su_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
setCancelable(false)
}.show()
@@ -193,8 +237,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
if (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
MagiskDialog(this).apply {
setTitle(R.string.unsupport_general_title)
setMessage(R.string.unsupport_system_app_msg)
setTitle(CoreR.string.unsupport_general_title)
setMessage(CoreR.string.unsupport_system_app_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
setCancelable(false)
}.show()
@@ -202,8 +246,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
if (applicationInfo.flags and ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0) {
MagiskDialog(this).apply {
setTitle(R.string.unsupport_general_title)
setMessage(R.string.unsupport_external_storage_msg)
setTitle(CoreR.string.unsupport_general_title)
setMessage(CoreR.string.unsupport_external_storage_msg)
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
setCancelable(false)
}.show()
@@ -216,8 +260,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
// Ask and show dialog
Config.askedHome = true
MagiskDialog(this).apply {
setTitle(R.string.add_shortcut_title)
setMessage(R.string.add_shortcut_msg)
setTitle(CoreR.string.add_shortcut_title)
setMessage(CoreR.string.add_shortcut_msg)
setButton(MagiskDialog.ButtonType.NEGATIVE) {
text = android.R.string.cancel
}
@@ -231,22 +275,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

@@ -4,15 +4,20 @@ 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
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.Locale
import java.util.TreeSet
class CmdlineListItem(line: String) {
val packageName: String
@@ -97,7 +102,7 @@ class AppProcessInfo(
companion object {
private val comparator = compareBy<AppProcessInfo>(
{ it.label.lowercase(currentLocale) },
{ it.label.lowercase(Locale.ROOT) },
{ it.info.packageName }
)
}

View File

@@ -16,6 +16,7 @@ import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding
import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addItemSpacing
import rikka.recyclerview.fixEdgeEffect
import com.topjohnwu.magisk.core.R as CoreR
class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
@@ -26,7 +27,7 @@ class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.denylist)
activity?.setTitle(CoreR.string.denylist)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -58,7 +59,7 @@ class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_deny_md2, menu)
searchView = menu.findItem(R.id.action_search).actionView as SearchView
searchView.queryHint = searchView.context.getString(R.string.hide_filter_hint)
searchView.queryHint = searchView.context.getString(CoreR.string.hide_filter_hint)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
viewModel.query = query ?: ""

View File

@@ -6,7 +6,7 @@ import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.ktx.concurrentMap
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.filterList

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
@@ -17,6 +21,7 @@ import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.cmp
import com.topjohnwu.magisk.databinding.FragmentFlashMd2Binding
import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.core.R as CoreR
class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
@@ -35,14 +40,14 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.flash_screen_title)
activity?.setTitle(CoreR.string.flash_screen_title)
viewModel.state.observe(this) {
activity?.supportActionBar?.setSubtitle(
when (it) {
FlashViewModel.State.FLASHING -> R.string.flashing
FlashViewModel.State.SUCCESS -> R.string.done
FlashViewModel.State.FAILED -> R.string.failure
FlashViewModel.State.FLASHING -> CoreR.string.flashing
FlashViewModel.State.SUCCESS -> CoreR.string.done
FlashViewModel.State.FAILED -> CoreR.string.failure
}
)
if (it == FlashViewModel.State.SUCCESS && viewModel.showReboot) {

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 -> {
@@ -104,7 +105,7 @@ class FlashViewModel : BaseViewModel() {
val name = "magisk_install_log_%s.log".format(
System.currentTimeMillis().toTime(timeFormatStandard)
)
val file = MediaStoreUtils.getFile(name, true)
val file = MediaStoreUtils.getFile(name)
file.uri.outputStream().bufferedWriter().use { writer ->
synchronized(logItems) {
logItems.forEach {

View File

@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.home
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.core.R as CoreR
interface Dev {
val name: String
@@ -84,8 +85,8 @@ sealed class IconLink : RvItem() {
override val layoutRes get() = R.layout.item_icon_link
abstract class PayPal : IconLink(), Dev {
override val icon get() = R.drawable.ic_paypal
override val title get() = R.string.paypal
override val icon get() = CoreR.drawable.ic_paypal
override val title get() = CoreR.string.paypal
override val link get() = "https://paypal.me/$name"
object Project : PayPal() {
@@ -94,20 +95,20 @@ sealed class IconLink : RvItem() {
}
object Patreon : IconLink() {
override val icon get() = R.drawable.ic_patreon
override val title get() = R.string.patreon
override val icon get() = CoreR.drawable.ic_patreon
override val title get() = CoreR.string.patreon
override val link get() = Const.Url.PATREON_URL
}
abstract class Twitter : IconLink(), Dev {
override val icon get() = R.drawable.ic_twitter
override val title get() = R.string.twitter
override val icon get() = CoreR.drawable.ic_twitter
override val title get() = CoreR.string.twitter
override val link get() = "https://twitter.com/$name"
}
abstract class Github : IconLink() {
override val icon get() = R.drawable.ic_github
override val title get() = R.string.github
override val icon get() = CoreR.drawable.ic_github
override val title get() = CoreR.string.github
abstract class User : Github(), Dev {
override val link get() = "https://github.com/$name"
@@ -119,8 +120,8 @@ sealed class IconLink : RvItem() {
}
abstract class Sponsor : IconLink(), Dev {
override val icon get() = R.drawable.ic_favorite
override val title get() = R.string.github
override val icon get() = CoreR.drawable.ic_favorite
override val title get() = CoreR.string.github
override val link get() = "https://github.com/sponsors/$name"
}
}

View File

@@ -14,8 +14,9 @@ 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
import com.topjohnwu.magisk.core.R as CoreR
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
@@ -24,8 +25,8 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.section_home)
DownloadService.observeProgress(this, viewModel::onProgressUpdate)
activity?.setTitle(CoreR.string.section_home)
DownloadEngine.observeProgress(this, viewModel::onProgressUpdate)
}
private fun checkTitle(text: TextView, icon: ImageView) {

View File

@@ -7,13 +7,13 @@ import android.widget.Toast
import androidx.core.net.toUri
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.ActivityExecutor
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
import com.topjohnwu.magisk.arch.ContextExecutor
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.arch.ViewEvent
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.download.Subject
@@ -30,6 +30,7 @@ import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.superuser.Shell
import kotlin.math.roundToInt
import com.topjohnwu.magisk.core.R as CoreR
class HomeViewModel(
private val svc: NetworkService
@@ -52,7 +53,7 @@ class HomeViewModel(
get() = when {
Info.isRooted && Info.env.isUnsupported -> State.OUTDATED
!Info.env.isActive -> State.INVALID
Info.env.versionCode < BuildConfig.VERSION_CODE -> State.OUTDATED
Info.env.versionCode < BuildConfig.APP_VERSION_CODE -> State.OUTDATED
else -> State.UP_TO_DATE
}
@@ -65,15 +66,15 @@ class HomeViewModel(
if (isActive)
("$versionString ($versionCode)" + if (isDebug) " (D)" else "").asText()
else
R.string.not_available.asText()
CoreR.string.not_available.asText()
}
@get:Bindable
var managerRemoteVersion = R.string.loading.asText()
var managerRemoteVersion = CoreR.string.loading.asText()
set(value) = set(value, field, { field = it }, BR.managerRemoteVersion)
val managerInstalledVersion
get() = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" +
get() = "${BuildConfig.APP_VERSION_NAME} (${BuildConfig.APP_VERSION_CODE})" +
if (BuildConfig.DEBUG) " (D)" else ""
@get:Bindable
@@ -92,7 +93,7 @@ class HomeViewModel(
appState = State.LOADING
Info.getRemote(svc)?.apply {
appState = when {
BuildConfig.VERSION_CODE < magisk.versionCode -> State.OUTDATED
BuildConfig.APP_VERSION_CODE < magisk.versionCode -> State.OUTDATED
else -> State.UP_TO_DATE
}
@@ -102,7 +103,7 @@ class HomeViewModel(
if (isDebug) " (D)" else "").asText()
} ?: run {
appState = State.INVALID
managerRemoteVersion = R.string.not_available.asText()
managerRemoteVersion = CoreR.string.not_available.asText()
}
ensureEnv()
}
@@ -121,7 +122,7 @@ class HomeViewModel(
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
context.toast(R.string.open_link_failed_toast, Toast.LENGTH_SHORT)
context.toast(CoreR.string.open_link_failed_toast, Toast.LENGTH_SHORT)
}
}
}.publish()
@@ -129,8 +130,8 @@ class HomeViewModel(
fun onDeletePressed() = UninstallDialog().show()
fun onManagerPressed() = when (appState) {
State.LOADING -> SnackbarEvent(R.string.loading).publish()
State.INVALID -> SnackbarEvent(R.string.no_connection).publish()
State.LOADING -> SnackbarEvent(CoreR.string.loading).publish()
State.INVALID -> SnackbarEvent(CoreR.string.no_connection).publish()
else -> withExternalRW {
withInstallPermission {
ManagerInstallDialog().show()

View File

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.ui.home
import android.app.Activity
import android.os.Build
import android.os.PowerManager
import android.view.ContextThemeWrapper
@@ -7,7 +8,8 @@ import android.view.MenuItem
import android.widget.PopupMenu
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.ktx.reboot as systemReboot
object RebootMenu {
@@ -20,19 +22,30 @@ 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
}
fun inflate(activity: BaseActivity): PopupMenu {
fun inflate(activity: Activity): PopupMenu {
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

@@ -4,6 +4,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
import com.topjohnwu.magisk.core.R as CoreR
class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
@@ -12,6 +13,6 @@ class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
override fun onStart() {
super.onStart()
requireActivity().setTitle(R.string.install)
requireActivity().setTitle(CoreR.string.install)
}
}

View File

@@ -11,14 +11,14 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.repository.NetworkService
import com.topjohnwu.magisk.databinding.set
@@ -33,6 +33,7 @@ import kotlinx.parcelize.Parcelize
import timber.log.Timber
import java.io.File
import java.io.IOException
import com.topjohnwu.magisk.core.R as CoreR
class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() {
@@ -69,7 +70,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
init {
viewModelScope.launch(Dispatchers.IO) {
try {
val file = File(AppContext.cacheDir, "${BuildConfig.VERSION_CODE}.md")
val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md")
val text = when {
file.exists() -> file.readText()
Const.Url.CHANGELOG_URL.isEmpty() -> ""
@@ -121,7 +122,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
@Parcelize
class UriCallback : ContentResultCallback {
override fun onActivityLaunch() {
AppContext.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG)
}
override fun onActivityResult(result: Uri) {
uri.value = result

View File

@@ -16,6 +16,7 @@ import com.topjohnwu.magisk.utils.MotionRevealHelper
import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addItemSpacing
import rikka.recyclerview.fixEdgeEffect
import com.topjohnwu.magisk.core.R as CoreR
class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
@@ -41,7 +42,7 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
override fun onStart() {
super.onStart()
activity?.setTitle(R.string.logs)
activity?.setTitle(CoreR.string.logs)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@@ -4,10 +4,10 @@ import android.system.Os
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
import com.topjohnwu.magisk.core.ktx.toTime
import com.topjohnwu.magisk.core.repository.LogRepository
@@ -69,7 +69,7 @@ class LogViewModel(
viewModelScope.launch(Dispatchers.IO) {
val filename = "magisk_log_%s.log".format(
System.currentTimeMillis().toTime(timeFormatStandard))
val logFile = MediaStoreUtils.getFile(filename, true)
val logFile = MediaStoreUtils.getFile(filename)
logFile.uri.outputStream().bufferedWriter().use { file ->
file.write("---Detected Device Info---\n\n")
file.write("isAB=${Info.isAB}\n")
@@ -93,7 +93,7 @@ class LogViewModel(
if (Info.env.isActive) file.write(magiskLogRaw)
file.write("\n---Manager Logs---\n")
file.write("${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n\n")
file.write("${BuildConfig.APP_VERSION_NAME} (${BuildConfig.APP_VERSION_CODE})\n\n")
ProcessBuilder("logcat", "-d").start()
.inputStream.reader().use { it.copyTo(file) }
}

View File

@@ -3,13 +3,14 @@ package com.topjohnwu.magisk.ui.log
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.ktx.timeDateFormat
import com.topjohnwu.magisk.core.ktx.toTime
import com.topjohnwu.magisk.core.model.su.SuLog
import com.topjohnwu.magisk.databinding.DiffItem
import com.topjohnwu.magisk.databinding.ObservableRvItem
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.core.R as CoreR
class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
@@ -31,20 +32,20 @@ class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
val res = AppContext.resources
val sb = StringBuilder()
val date = log.time.toTime(timeDateFormat)
val toUid = res.getString(R.string.target_uid, log.toUid)
val fromPid = res.getString(R.string.pid, log.fromPid)
val toUid = res.getString(CoreR.string.target_uid, log.toUid)
val fromPid = res.getString(CoreR.string.pid, log.fromPid)
sb.append("$date\n$toUid $fromPid")
if (log.target != -1) {
val pid = if (log.target == 0) "magiskd" else log.target.toString()
val target = res.getString(R.string.target_pid, pid)
val target = res.getString(CoreR.string.target_pid, pid)
sb.append(" $target")
}
if (log.context.isNotEmpty()) {
val context = res.getString(R.string.selinux_context, log.context)
val context = res.getString(CoreR.string.selinux_context, log.context)
sb.append("\n$context")
}
if (log.gids.isNotEmpty()) {
val gids = res.getString(R.string.supp_group, log.gids)
val gids = res.getString(CoreR.string.supp_group, log.gids)
sb.append("\n$gids")
}
sb.append("\n${log.command}")

View File

@@ -11,6 +11,7 @@ import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addInvalidateItemDecorationsObserver
import rikka.recyclerview.addItemSpacing
import rikka.recyclerview.fixEdgeEffect
import com.topjohnwu.magisk.core.R as CoreR
class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
@@ -19,7 +20,7 @@ class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
override fun onStart() {
super.onStart()
activity?.title = resources.getString(R.string.modules)
activity?.title = resources.getString(CoreR.string.modules)
viewModel.data.observe(this) {
it ?: return@observe
val displayName = runCatching { it.displayName }.getOrNull() ?: return@observe

View File

@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.core.R as CoreR
object InstallModule : RvItem(), DiffItem<InstallModule> {
override val layoutRes = R.layout.item_module_download
@@ -36,9 +37,9 @@ class LocalModuleRvItem(
(!Info.isZygiskEnabled && isZygisk)
noticeText =
when {
zygiskUnloaded -> R.string.zygisk_module_unloaded.asText()
isRiru -> R.string.suspend_text_riru.asText(R.string.zygisk.asText())
else -> R.string.suspend_text_zygisk.asText(R.string.zygisk.asText())
zygiskUnloaded -> CoreR.string.zygisk_module_unloaded.asText()
isRiru -> CoreR.string.suspend_text_riru.asText(CoreR.string.zygisk.asText())
else -> CoreR.string.suspend_text_zygisk.asText(CoreR.string.zygisk.asText())
}
}

View File

@@ -22,6 +22,7 @@ import com.topjohnwu.magisk.events.SnackbarEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import com.topjohnwu.magisk.core.R as CoreR
class ModuleViewModel : AsyncLoadViewModel() {
@@ -77,7 +78,7 @@ class ModuleViewModel : AsyncLoadViewModel() {
if (item != null && Info.isConnected.value == true) {
withExternalRW { OnlineModuleInstallDialog(item).show() }
} else {
SnackbarEvent(R.string.no_connection).publish()
SnackbarEvent(CoreR.string.no_connection).publish()
}
fun installPressed() = withExternalRW {

View File

@@ -14,29 +14,34 @@ import com.topjohnwu.magisk.view.MagiskDialog
sealed class BaseSettingsItem : ObservableRvItem() {
interface Handler {
fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit)
fun onItemAction(view: View, item: BaseSettingsItem)
}
override val layoutRes get() = R.layout.item_settings
open val icon: Int get() = 0
open val title: TextHolder get() = TextHolder.EMPTY
@get:Bindable
open val description: TextHolder get() = TextHolder.EMPTY
open val showSwitch get() = false
@get:Bindable
open val isChecked get() = false
@get:Bindable
var isEnabled = true
set(value) = set(value, field, { field = it }, BR.enabled, BR.description)
open fun onToggle(view: View, handler: Handler, checked: Boolean) {}
open fun onPressed(view: View, handler: Handler) {
handler.onItemPressed(view, this)
handler.onItemPressed(view, this) {
handler.onItemAction(view, this)
}
}
open fun refresh() {}
interface Handler {
fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit = {})
fun onItemAction(view: View, item: BaseSettingsItem)
}
// Only for toggle
open val showSwitch get() = false
@get:Bindable
open val isChecked get() = false
fun onToggle(view: View, handler: Handler, checked: Boolean) =
set(checked, isChecked, { onPressed(view, handler) })
abstract class Value<T> : BaseSettingsItem() {
@@ -54,9 +59,6 @@ sealed class BaseSettingsItem : ObservableRvItem() {
override val showSwitch get() = true
override val isChecked get() = value
override fun onToggle(view: View, handler: Handler, checked: Boolean) =
set(checked, value, { onPressed(view, handler) })
override fun onPressed(view: View, handler: Handler) {
// Make sure the checked state is synced
notifyPropertyChanged(BR.checked)
@@ -140,5 +142,4 @@ sealed class BaseSettingsItem : ObservableRvItem() {
abstract class Section : BaseSettingsItem() {
override val layoutRes = R.layout.item_settings_section
}
}

View File

@@ -9,6 +9,7 @@ import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addItemSpacing
import rikka.recyclerview.fixEdgeEffect
import com.topjohnwu.magisk.core.R as CoreR
class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
@@ -19,7 +20,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
override fun onStart() {
super.onStart()
activity?.title = resources.getString(R.string.settings)
activity?.title = resources.getString(CoreR.string.settings)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@@ -7,81 +7,70 @@ import android.view.LayoutInflater
import android.view.View
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.ktx.activity
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.tasks.AppMigration
import com.topjohnwu.magisk.core.utils.LocaleSetting
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.availableLocales
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import com.topjohnwu.magisk.core.R as CoreR
// --- Customization
object Customization : BaseSettingsItem.Section() {
override val title = R.string.settings_customization.asText()
override val title = CoreR.string.settings_customization.asText()
}
object Language : BaseSettingsItem.Selector() {
private val names: Array<String> get() = LocaleSetting.available.names
private val tags: Array<String> get() = LocaleSetting.available.tags
override var value
get() = index
get() = tags.indexOf(Config.locale)
set(value) {
index = value
Config.locale = entryValues[value]
Config.locale = tags[value]
}
override val title = R.string.language.asText()
override val title = CoreR.string.language.asText()
private var entries = emptyArray<String>()
private var entryValues = emptyArray<String>()
private var index = -1
override fun entries(res: Resources) = names
override fun descriptions(res: Resources) = names
}
override fun entries(res: Resources) = entries
override fun descriptions(res: Resources) = entries
override fun onPressed(view: View, handler: Handler) {
if (entries.isNotEmpty())
super.onPressed(view, handler)
}
suspend fun loadLanguages(scope: CoroutineScope) {
scope.launch {
availableLocales().let { (names, values) ->
entries = names
entryValues = values
val selectedLocale = currentLocale.getDisplayName(currentLocale)
index = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it }
notifyPropertyChanged(BR.description)
}
object LanguageSystem : BaseSettingsItem.Blank() {
override val title = CoreR.string.language.asText()
override val description: TextHolder
get() {
val locale = LocaleSetting.instance.appLocale
return locale?.getDisplayName(locale)?.asText() ?: CoreR.string.system_default.asText()
}
}
}
object Theme : BaseSettingsItem.Blank() {
override val icon = R.drawable.ic_paint
override val title = R.string.section_theme.asText()
override val title = CoreR.string.section_theme.asText()
}
// --- App
object AppSettings : BaseSettingsItem.Section() {
override val title = R.string.home_app_title.asText()
override val title = CoreR.string.home_app_title.asText()
}
object Hide : BaseSettingsItem.Input() {
override val title = R.string.settings_hide_app_title.asText()
override val description = R.string.settings_hide_app_summary.asText()
override val title = CoreR.string.settings_hide_app_title.asText()
override val description = CoreR.string.settings_hide_app_summary.asText()
override var value = ""
override val inputResult
@@ -92,7 +81,7 @@ object Hide : BaseSettingsItem.Input() {
set(value) = set(value, field, { field = it }, BR.result, BR.error)
val maxLength
get() = HideAPK.MAX_LABEL_LENGTH
get() = AppMigration.MAX_LABEL_LENGTH
@get:Bindable
val isError
@@ -103,14 +92,14 @@ object Hide : BaseSettingsItem.Input() {
}
object Restore : BaseSettingsItem.Blank() {
override val title = R.string.settings_restore_app_title.asText()
override val description = R.string.settings_restore_app_summary.asText()
override val title = CoreR.string.settings_restore_app_title.asText()
override val description = CoreR.string.settings_restore_app_summary.asText()
override fun onPressed(view: View, handler: Handler) {
handler.onItemPressed(view, this) {
MagiskDialog(view.activity).apply {
setTitle(R.string.settings_restore_app_title)
setMessage(R.string.restore_app_confirmation)
setTitle(CoreR.string.settings_restore_app_title)
setMessage(CoreR.string.restore_app_confirmation)
setButton(MagiskDialog.ButtonType.POSITIVE) {
text = android.R.string.ok
onClick {
@@ -128,8 +117,8 @@ object Restore : BaseSettingsItem.Blank() {
}
object AddShortcut : BaseSettingsItem.Blank() {
override val title = R.string.add_shortcut_title.asText()
override val description = R.string.setting_add_shortcut_summary.asText()
override val title = CoreR.string.add_shortcut_title.asText()
override val description = CoreR.string.setting_add_shortcut_summary.asText()
}
object DownloadPath : BaseSettingsItem.Input() {
@@ -140,7 +129,7 @@ object DownloadPath : BaseSettingsItem.Input() {
notifyPropertyChanged(BR.description)
}
override val title = R.string.settings_download_path_title.asText()
override val title = CoreR.string.settings_download_path_title.asText()
override val description get() = MediaStoreUtils.fullPath(value).asText()
override var inputResult: String = value
@@ -161,9 +150,9 @@ object UpdateChannel : BaseSettingsItem.Selector() {
Info.remote = Info.EMPTY_REMOTE
}
override val title = R.string.settings_update_channel_title.asText()
override val title = CoreR.string.settings_update_channel_title.asText()
override val entryRes = R.array.update_channel
override val entryRes = CoreR.array.update_channel
override fun entries(res: Resources): Array<String> {
return super.entries(res).let {
if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
@@ -174,7 +163,7 @@ object UpdateChannel : BaseSettingsItem.Selector() {
}
object UpdateChannelUrl : BaseSettingsItem.Input() {
override val title = R.string.settings_update_custom.asText()
override val title = CoreR.string.settings_update_custom.asText()
override val description get() = value.asText()
override var value
get() = Config.customChannelUrl
@@ -196,56 +185,51 @@ object UpdateChannelUrl : BaseSettingsItem.Input() {
}
object UpdateChecker : BaseSettingsItem.Toggle() {
override val title = R.string.settings_check_update_title.asText()
override val description = R.string.settings_check_update_summary.asText()
override val title = CoreR.string.settings_check_update_title.asText()
override val description = CoreR.string.settings_check_update_summary.asText()
override var value by Config::checkUpdate
}
object DoHToggle : BaseSettingsItem.Toggle() {
override val title = R.string.settings_doh_title.asText()
override val description = R.string.settings_doh_description.asText()
override val title = CoreR.string.settings_doh_title.asText()
override val description = CoreR.string.settings_doh_description.asText()
override var value by Config::doh
}
object SystemlessHosts : BaseSettingsItem.Blank() {
override val title = R.string.settings_hosts_title.asText()
override val description = R.string.settings_hosts_summary.asText()
override val title = CoreR.string.settings_hosts_title.asText()
override val description = CoreR.string.settings_hosts_summary.asText()
}
object RandNameToggle : BaseSettingsItem.Toggle() {
override val title = CoreR.string.settings_random_name_title.asText()
override val description = CoreR.string.settings_random_name_description.asText()
override var value by Config::randName
}
// --- Magisk
object Magisk : BaseSettingsItem.Section() {
override val title = R.string.magisk.asText()
override val title = CoreR.string.magisk.asText()
}
object Zygisk : BaseSettingsItem.Toggle() {
override val title = R.string.zygisk.asText()
override val title = CoreR.string.zygisk.asText()
override val description get() =
if (mismatch) R.string.reboot_apply_change.asText()
else R.string.settings_zygisk_summary.asText()
if (mismatch) CoreR.string.reboot_apply_change.asText()
else CoreR.string.settings_zygisk_summary.asText()
override var value
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 title = CoreR.string.settings_denylist_title.asText()
override val description get() = CoreR.string.settings_denylist_summary.asText()
override var value = Config.denyList
set(value) {
@@ -260,55 +244,48 @@ 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
}
override val title = CoreR.string.settings_denylist_config_title.asText()
override val description = CoreR.string.settings_denylist_config_summary.asText()
}
// --- Superuser
object Tapjack : BaseSettingsItem.Toggle() {
override val title = R.string.settings_su_tapjack_title.asText()
override val description = R.string.settings_su_tapjack_summary.asText()
override val title = CoreR.string.settings_su_tapjack_title.asText()
override val description = CoreR.string.settings_su_tapjack_summary.asText()
override var value by Config::suTapjack
}
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 val title = CoreR.string.settings_su_auth_title.asText()
override var description = CoreR.string.settings_su_auth_summary.asText()
override var value by Config::suAuth
override fun refresh() {
isEnabled = Info.isDeviceSecure
if (!isEnabled) {
description = R.string.settings_su_auth_insecure.asText()
description = CoreR.string.settings_su_auth_insecure.asText()
}
}
}
object Superuser : BaseSettingsItem.Section() {
override val title = R.string.superuser.asText()
override val title = CoreR.string.superuser.asText()
}
object AccessMode : BaseSettingsItem.Selector() {
override val title = R.string.superuser_access.asText()
override val entryRes = R.array.su_access
override val title = CoreR.string.superuser_access.asText()
override val entryRes = CoreR.array.su_access
override var value by Config::rootMode
}
object MultiuserMode : BaseSettingsItem.Selector() {
override val title = R.string.multiuser_mode.asText()
override val entryRes = R.array.multiuser_mode
override val descriptionRes = R.array.multiuser_summary
override val title = CoreR.string.multiuser_mode.asText()
override val entryRes = CoreR.array.multiuser_mode
override val descriptionRes = CoreR.array.multiuser_summary
override var value by Config::suMultiuserMode
override fun refresh() {
@@ -317,21 +294,21 @@ object MultiuserMode : BaseSettingsItem.Selector() {
}
object MountNamespaceMode : BaseSettingsItem.Selector() {
override val title = R.string.mount_namespace_mode.asText()
override val entryRes = R.array.namespace
override val descriptionRes = R.array.namespace_summary
override val title = CoreR.string.mount_namespace_mode.asText()
override val entryRes = CoreR.array.namespace
override val descriptionRes = CoreR.array.namespace_summary
override var value by Config::suMntNamespaceMode
}
object AutomaticResponse : BaseSettingsItem.Selector() {
override val title = R.string.auto_response.asText()
override val entryRes = R.array.auto_response
override val title = CoreR.string.auto_response.asText()
override val entryRes = CoreR.array.auto_response
override var value by Config::suAutoResponse
}
object RequestTimeout : BaseSettingsItem.Selector() {
override val title = R.string.request_timeout.asText()
override val entryRes = R.array.request_timeout
override val title = CoreR.string.request_timeout.asText()
override val entryRes = CoreR.array.request_timeout
private val entryValues = listOf(10, 15, 20, 30, 45, 60)
override var value = entryValues.indexOfFirst { it == Config.suDefaultTimeout }
@@ -342,14 +319,14 @@ object RequestTimeout : BaseSettingsItem.Selector() {
}
object SUNotification : BaseSettingsItem.Selector() {
override val title = R.string.superuser_notification.asText()
override val entryRes = R.array.su_notification
override val title = CoreR.string.superuser_notification.asText()
override val entryRes = CoreR.array.su_notification
override var value by Config::suNotification
}
object Reauthenticate : BaseSettingsItem.Toggle() {
override val title = R.string.settings_su_reauth_title.asText()
override val description = R.string.settings_su_reauth_summary.asText()
override val title = CoreR.string.settings_su_reauth_title.asText()
override val description = CoreR.string.settings_su_reauth_summary.asText()
override var value by Config::suReAuth
override fun refresh() {

View File

@@ -1,21 +1,26 @@
package com.topjohnwu.magisk.ui.settings
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.view.View
import android.widget.Toast
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.BuildConfig
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.ktx.activity
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.tasks.HideAPK
import com.topjohnwu.magisk.core.tasks.AppMigration
import com.topjohnwu.magisk.core.utils.LocaleSetting
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.events.AddHomeIconEvent
import com.topjohnwu.magisk.events.AuthEvent
@@ -30,20 +35,14 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
it.put(BR.handler, this)
}
init {
viewModelScope.launch {
Language.loadLanguages(this)
}
}
private fun createItems(): List<BaseSettingsItem> {
val context = AppContext
val hidden = context.packageName != BuildConfig.APPLICATION_ID
val hidden = context.packageName != BuildConfig.APP_PACKAGE_NAME
// Customization
val list = mutableListOf(
Customization,
Theme, Language
Theme, if (LocaleSetting.useLocaleManager) LanguageSystem else Language
)
if (isRunningAsStub && ShortcutManagerCompat.isRequestPinShortcutSupported(context))
list.add(AddShortcut)
@@ -51,7 +50,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
// Manager
list.addAll(listOf(
AppSettings,
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath, RandNameToggle
))
if (Info.env.isActive && Const.USER_ID == 0) {
if (hidden) list.add(Restore) else list.add(Hide)
@@ -88,30 +87,37 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
return list
}
override fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit) {
override fun onItemPressed(view: View, item: BaseSettingsItem, doAction: () -> Unit) {
when (item) {
DownloadPath -> withExternalRW(andThen)
UpdateChecker -> withPostNotificationPermission(andThen)
Authentication -> AuthEvent(andThen).publish()
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
SystemlessHosts -> createHosts()
Hide, Restore -> withInstallPermission(andThen)
AddShortcut -> AddHomeIconEvent().publish()
else -> andThen()
DownloadPath -> withExternalRW(doAction)
UpdateChecker -> withPostNotificationPermission(doAction)
Authentication -> AuthEvent(doAction).publish()
Hide, Restore -> withInstallPermission(doAction)
else -> doAction()
}
}
override fun onItemAction(view: View, item: BaseSettingsItem) {
when (item) {
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
LanguageSystem -> launchAppLocaleSettings(view.activity)
AddShortcut -> AddHomeIconEvent().publish()
SystemlessHosts -> createHosts()
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
UpdateChannel -> openUrlIfNecessary(view)
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
Restore -> viewModelScope.launch { HideAPK.restore(view.activity) }
is Hide -> viewModelScope.launch { AppMigration.hide(view.activity, item.value) }
Restore -> viewModelScope.launch { AppMigration.restore(view.activity) }
Zygisk -> if (Zygisk.mismatch) SnackbarEvent(R.string.reboot_apply_change).publish()
else -> Unit
}
}
private fun launchAppLocaleSettings(activity: Activity) {
val intent = Intent(Settings.ACTION_APP_LOCALE_SETTINGS)
intent.data = Uri.fromParts("package", activity.packageName, null)
activity.startActivity(intent)
}
private fun openUrlIfNecessary(view: View) {
UpdateChannelUrl.refresh()
if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) {

View File

@@ -9,6 +9,7 @@ import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addItemSpacing
import rikka.recyclerview.fixEdgeEffect
import com.topjohnwu.magisk.core.R as CoreR
class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
@@ -17,7 +18,7 @@ class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
override fun onStart() {
super.onStart()
activity?.title = resources.getString(R.string.superuser)
activity?.title = resources.getString(CoreR.string.superuser)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@@ -8,15 +8,14 @@ import androidx.databinding.Bindable
import androidx.databinding.ObservableArrayList
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.AppContext
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.di.AppContext
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.MergeObservableList
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.bindExtra
@@ -30,6 +29,7 @@ import com.topjohnwu.magisk.view.TextItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
class SuperuserViewModel(
private val db: PolicyDao
@@ -92,7 +92,7 @@ class SuperuserViewModel(
policies.addAll(map)
}
policies.sortWith(compareBy(
{ it.appName.lowercase(currentLocale) },
{ it.appName.lowercase(Locale.ROOT) },
{ it.packageName }
))
itemsPolicies.update(policies)
@@ -117,7 +117,7 @@ class SuperuserViewModel(
}
}
if (Config.userAuth) {
if (Config.suAuth) {
AuthEvent { updateState() }.publish()
} else {
SuperuserRevokeDialog(item.title) { updateState() }.show()
@@ -170,7 +170,7 @@ class SuperuserViewModel(
}
}
if (Config.userAuth) {
if (Config.suAuth) {
AuthEvent { updateState() }.publish()
} else {
updateState()

View File

@@ -11,6 +11,7 @@ import androidx.lifecycle.lifecycleScope
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.base.UntrackedActivity
import com.topjohnwu.magisk.core.su.SuCallbackHandler
import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
@@ -19,7 +20,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
open class SuRequestActivity : UIActivity<ActivityRequestBinding>() {
open class SuRequestActivity : UIActivity<ActivityRequestBinding>(), UntrackedActivity {
override val layoutRes: Int = R.layout.activity_request
override val viewModel: SuRequestViewModel by viewModel()

View File

@@ -17,11 +17,11 @@ import android.widget.Toast
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.R
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.ktx.getLabel
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
@@ -76,7 +76,7 @@ class SuRequestViewModel(
fun grantPressed() {
cancelTimer()
if (Config.userAuth) {
if (Config.suAuth) {
AuthEvent { respond(ALLOW) }.publish()
} else {
respond(ALLOW)

View File

@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.databinding.FragmentThemeMd2Binding
import com.topjohnwu.magisk.databinding.ItemThemeBindingImpl
import com.topjohnwu.magisk.core.R as CoreR
class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
@@ -61,7 +62,7 @@ class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
override fun onStart() {
super.onStart()
activity?.title = getString(R.string.section_theme)
activity?.title = getString(CoreR.string.section_theme)
}
}

View File

@@ -14,7 +14,7 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.google.android.material.circularreveal.CircularRevealCompat
import com.google.android.material.circularreveal.CircularRevealWidget
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.core.utils.LocaleSetting
import kotlin.math.hypot
object MotionRevealHelper {
@@ -63,7 +63,9 @@ object MotionRevealHelper {
it.interpolator = FastOutSlowInInterpolator()
it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() })
val rtlMod = if (currentLocale.layoutDirection == View.LAYOUT_DIRECTION_RTL) 1f else -1f
val rtlMod =
if (LocaleSetting.instance.currentLocale.layoutDirection == View.LAYOUT_DIRECTION_RTL)
1f else -1f
val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f
val targetX = if (revealInfo.radius == 0f) 0f else maxX * rtlMod
val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX)

View File

@@ -21,7 +21,7 @@ import com.google.android.material.color.MaterialColors
import com.google.android.material.shape.MaterialShapeDrawable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.arch.UIActivity
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
import com.topjohnwu.magisk.databinding.DiffItem
import com.topjohnwu.magisk.databinding.ItemWrapper
@@ -42,7 +42,7 @@ class MagiskDialog(
DialogMagiskBaseBinding.inflate(LayoutInflater.from(context))
private val data = Data()
val activity: BaseActivity get() = ownerActivity as BaseActivity
val activity: UIActivity<*> get() = ownerActivity as UIActivity<*>
init {
binding.setVariable(BR.data, data)

View File

@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.view
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.DiffItem
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.core.R as CoreR
sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
@@ -22,7 +23,7 @@ sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
// --- objects
object ThemeMode : TappableHeadlineItem() {
override val title = R.string.settings_dark_mode_title
override val title = CoreR.string.settings_dark_mode_title
override val icon = R.drawable.ic_day_night
}

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"
android:valueTo="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"
android:valueTo="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"

View File

@@ -17,7 +17,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="500"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.744 3.12 17.24 4.927 19.052 C 6.74 20.87 9.244 22 12 22 C 13.911 22 15.701 21.457 17.224 20.517 C 18.628 19.651 19.804 18.448 20.638 17.024 C 21.503 15.545 22 13.828 22 12 C 22 10.2 21.518 8.507 20.677 7.044 C 19.755 5.441 18.402 4.114 16.779 3.224 C 15.357 2.444 13.728 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"
android:valueTo="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"

View File

@@ -17,7 +17,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="500"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"
android:valueTo="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.856 3.213 17.442 5.149 19.268 C 6.942 20.96 9.356 22 12 22 C 14.061 22 15.982 21.368 17.578 20.288 C 19.114 19.249 20.349 17.796 21.119 16.092 C 21.685 14.841 22 13.456 22 12 C 22 10.122 21.475 8.361 20.566 6.856 C 19.691 5.408 18.46 4.197 16.997 3.347 C 15.524 2.491 13.817 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"

View File

@@ -19,7 +19,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"
android:valueTo="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"

View File

@@ -19,7 +19,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"
android:valueTo="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"
android:valueTo="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"
android:valueTo="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"

View File

@@ -18,7 +18,7 @@
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:interpolator="@interpolator/fast_out_slow_in"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"

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