mirror of
https://github.com/topjohnwu/Magisk
synced 2025-11-10 02:12:30 +01:00
Compare commits
282 Commits
v28.0
...
canary-290
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1dc47a047 | ||
|
|
62b1310d97 | ||
|
|
0a86916d3a | ||
|
|
9907ce57aa | ||
|
|
b92626cacc | ||
|
|
5a762f0a8e | ||
|
|
5dd7a7d804 | ||
|
|
7831f40691 | ||
|
|
4f4b1ff885 | ||
|
|
97901979dd | ||
|
|
287316842c | ||
|
|
608786e8f3 | ||
|
|
9684a35cab | ||
|
|
e3e4202954 | ||
|
|
23c2054d46 | ||
|
|
a20a2a8fa0 | ||
|
|
a2896be4a6 | ||
|
|
e9220a28d9 | ||
|
|
cf12087e21 | ||
|
|
00c1b36837 | ||
|
|
03e034795d | ||
|
|
79c0fafe43 | ||
|
|
d499819ba0 | ||
|
|
86da917174 | ||
|
|
30bd7d6555 | ||
|
|
e5a12f0f5f | ||
|
|
c85a8434c6 | ||
|
|
427a1ca4e5 | ||
|
|
22884e173a | ||
|
|
d1829308e9 | ||
|
|
73840f8721 | ||
|
|
c7d1af9805 | ||
|
|
4ad26d3dfb | ||
|
|
0c70b7670c | ||
|
|
f44d044095 | ||
|
|
5c1cb13472 | ||
|
|
3327fc668e | ||
|
|
610945ac54 | ||
|
|
ddf5474917 | ||
|
|
6ba1685ade | ||
|
|
e02b5f7868 | ||
|
|
ab2e5d1e7e | ||
|
|
f3fef7bfe4 | ||
|
|
c34c7838bb | ||
|
|
c8a16b0e0c | ||
|
|
14f9ed91a1 | ||
|
|
7a207d4ccf | ||
|
|
92a42d901f | ||
|
|
084d89fcce | ||
|
|
55b036c071 | ||
|
|
30e79310ab | ||
|
|
f063fa5054 | ||
|
|
7bd901273c | ||
|
|
c1e061603b | ||
|
|
cb08504fe5 | ||
|
|
c0a1fb77be | ||
|
|
4864c1112a | ||
|
|
9ddeab034b | ||
|
|
c4847ed288 | ||
|
|
b8f1523fb2 | ||
|
|
fb7fa8a6b3 | ||
|
|
9c7d359093 | ||
|
|
eb54bc1fd7 | ||
|
|
d4a0286e13 | ||
|
|
83e66767ff | ||
|
|
7dc010749b | ||
|
|
8e8d013b1b | ||
|
|
bba0373808 | ||
|
|
1fa318dc8c | ||
|
|
6edc5e2037 | ||
|
|
1523ed9f78 | ||
|
|
8e604d2ab8 | ||
|
|
2aba7247a9 | ||
|
|
e66fe8533e | ||
|
|
b03fbb3917 | ||
|
|
c2ece62e4c | ||
|
|
8c972dcf34 | ||
|
|
50af14f2a3 | ||
|
|
e0a356b319 | ||
|
|
c09a792958 | ||
|
|
0bbfe7f44d | ||
|
|
a396abf565 | ||
|
|
1e3edb8883 | ||
|
|
3b8b61bf35 | ||
|
|
6f90456036 | ||
|
|
f56fd4e215 | ||
|
|
aa35aac5d5 | ||
|
|
1f162b819d | ||
|
|
52ef1d1cb2 | ||
|
|
f14e3a89cc | ||
|
|
95d3eac2e0 | ||
|
|
8e73536e02 | ||
|
|
12a0870bc9 | ||
|
|
6ff82c4e86 | ||
|
|
c64de35375 | ||
|
|
ee5283f4e8 | ||
|
|
bd0e954fea | ||
|
|
675471a49e | ||
|
|
c90e73ccec | ||
|
|
a43c1267d8 | ||
|
|
e8958c6b5c | ||
|
|
e8a3bf82c6 | ||
|
|
27fd79176a | ||
|
|
28d86a3454 | ||
|
|
c6c1a17ae6 | ||
|
|
2b47d47215 | ||
|
|
0e82df9e10 | ||
|
|
893821ad88 | ||
|
|
6b80fbfa99 | ||
|
|
8c3c7d0194 | ||
|
|
b94a3d9f2f | ||
|
|
442d0b5ddc | ||
|
|
494615d9a0 | ||
|
|
afbfb81837 | ||
|
|
3ed4e258a3 | ||
|
|
dddd41c95b | ||
|
|
5f2ca81e86 | ||
|
|
c9eac0c438 | ||
|
|
b6b34f7612 | ||
|
|
e55c413261 | ||
|
|
0399cde50a | ||
|
|
019eb03823 | ||
|
|
363410e1c0 | ||
|
|
fc2ef21660 | ||
|
|
18cb659ff3 | ||
|
|
63231d97ce | ||
|
|
9ac81a8a25 | ||
|
|
79af2787ae | ||
|
|
f5f9b285c0 | ||
|
|
6c05f2ae85 | ||
|
|
29043e1684 | ||
|
|
b73d4a7022 | ||
|
|
ad95e8951b | ||
|
|
bf591fca12 | ||
|
|
dcf027884d | ||
|
|
584f3820fe | ||
|
|
3c7c46307a | ||
|
|
4d80361805 | ||
|
|
9a74e19117 | ||
|
|
b1e17706a4 | ||
|
|
caad129d69 | ||
|
|
da58571ce5 | ||
|
|
2aa7f1c094 | ||
|
|
823e31a91b | ||
|
|
fb926ae302 | ||
|
|
e0489eeffd | ||
|
|
dc9d5a4cac | ||
|
|
143743d0b0 | ||
|
|
563f0d5ad5 | ||
|
|
c99f4a591b | ||
|
|
449204e380 | ||
|
|
a85c4c6528 | ||
|
|
d203a6fff6 | ||
|
|
6c612d66d7 | ||
|
|
540253a55b | ||
|
|
15b7c4ccd1 | ||
|
|
442d5335ea | ||
|
|
8a80eea597 | ||
|
|
5e35703091 | ||
|
|
b7ca73f431 | ||
|
|
a14fc90f07 | ||
|
|
c913f7ec74 | ||
|
|
7f6c9e8411 | ||
|
|
bb02ea3a20 | ||
|
|
3981c9665e | ||
|
|
88628fdf3c | ||
|
|
0469817781 | ||
|
|
a786801141 | ||
|
|
ab86732c89 | ||
|
|
59622d1688 | ||
|
|
58a25a3e2b | ||
|
|
15dca29a87 | ||
|
|
46980819c0 | ||
|
|
4fb6a7268c | ||
|
|
c05e963f37 | ||
|
|
7f7f625864 | ||
|
|
b25aa8295a | ||
|
|
15a605765c | ||
|
|
b575c95710 | ||
|
|
a48a9c858a | ||
|
|
0d8d6290a3 | ||
|
|
4dcd733ddd | ||
|
|
b62835cbeb | ||
|
|
6ea740b5ab | ||
|
|
7ab98dd5ac | ||
|
|
fc8b3400fc | ||
|
|
54428ba415 | ||
|
|
95d1e69d8e | ||
|
|
a0f13ab49f | ||
|
|
c3e8405020 | ||
|
|
a93593ea66 | ||
|
|
23eff70883 | ||
|
|
110dd4a8b9 | ||
|
|
d9c2bffc9f | ||
|
|
049db49dc8 | ||
|
|
7c1d2ec61e | ||
|
|
a1b2830c06 | ||
|
|
82d1d19267 | ||
|
|
4d4195c02d | ||
|
|
5637a258fc | ||
|
|
ee6810f417 | ||
|
|
7098248c64 | ||
|
|
0d31d356ef | ||
|
|
b782e7dcb7 | ||
|
|
a4671b4698 | ||
|
|
7edd8be169 | ||
|
|
24650eefe4 | ||
|
|
8e1a44e7eb | ||
|
|
2722875190 | ||
|
|
3ca6d06f69 | ||
|
|
10e47248de | ||
|
|
e73ff679ac | ||
|
|
53e401fa2d | ||
|
|
d2768357da | ||
|
|
a6c2ba7c1e | ||
|
|
aae5b466fb | ||
|
|
2b7be8b949 | ||
|
|
b6511a510d | ||
|
|
704541aef2 | ||
|
|
005560a4c5 | ||
|
|
231a5d1853 | ||
|
|
9e2b59060d | ||
|
|
08ea937f7c | ||
|
|
2baedf74d1 | ||
|
|
32faa4ced6 | ||
|
|
ccdb0b5d13 | ||
|
|
8506b672ad | ||
|
|
ce2e33bb20 | ||
|
|
6707b72260 | ||
|
|
5885b8c20d | ||
|
|
820710c086 | ||
|
|
51cf196bf7 | ||
|
|
dadba44cf9 | ||
|
|
2ce4a5543b | ||
|
|
9112a3a4f5 | ||
|
|
24615afda1 | ||
|
|
c5778f398b | ||
|
|
4eb4097b9b | ||
|
|
c512496847 | ||
|
|
506961a10d | ||
|
|
3414415907 | ||
|
|
dc2ae7cfd1 | ||
|
|
2e86d21c29 | ||
|
|
2654382c43 | ||
|
|
9e26b73813 | ||
|
|
10cd13bf80 | ||
|
|
f10ee5f887 | ||
|
|
47cc532d96 | ||
|
|
218327f92b | ||
|
|
4eae66a1a7 | ||
|
|
b09ceeb43c | ||
|
|
4fb539c110 | ||
|
|
849b284da5 | ||
|
|
895b5f6cbf | ||
|
|
cb3d4ea514 | ||
|
|
0d89a2a97d | ||
|
|
3ca5913055 | ||
|
|
df6b808f49 | ||
|
|
09c7ac754b | ||
|
|
805da67c23 | ||
|
|
3c6889505b | ||
|
|
c8e9ce7627 | ||
|
|
837c679a31 | ||
|
|
06616659b8 | ||
|
|
a34c04f999 | ||
|
|
da43ac89a0 | ||
|
|
830fc758b9 | ||
|
|
0f3cfef278 | ||
|
|
b32d7bfafd | ||
|
|
c0899f2939 | ||
|
|
082330808f | ||
|
|
024da05888 | ||
|
|
377b6d0cc2 | ||
|
|
c661009b31 | ||
|
|
613f2d31c5 | ||
|
|
7dbb973db5 | ||
|
|
f4502f8be8 | ||
|
|
455b13b83c | ||
|
|
8b98709743 | ||
|
|
1b12f45f39 | ||
|
|
a5cad532ff | ||
|
|
070719db50 |
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -12,13 +12,11 @@
|
|||||||
|
|
||||||
# Denote all files that are truly binary and should not be modified.
|
# Denote all files that are truly binary and should not be modified.
|
||||||
tools/** binary
|
tools/** binary
|
||||||
|
tools/rustup-wrapper/** -binary
|
||||||
|
tools/elf-cleaner/** -binary
|
||||||
*.jar binary
|
*.jar binary
|
||||||
*.exe binary
|
*.exe binary
|
||||||
*.apk binary
|
*.apk binary
|
||||||
*.png binary
|
*.png binary
|
||||||
*.jpg binary
|
*.jpg binary
|
||||||
*.ttf binary
|
*.ttf binary
|
||||||
|
|
||||||
# Help GitHub detect languages
|
|
||||||
native/jni/external/** linguist-vendored
|
|
||||||
native/jni/systemproperties/** linguist-language=C++
|
|
||||||
|
|||||||
25
.github/actions/setup/action.yml
vendored
25
.github/actions/setup/action.yml
vendored
@@ -6,7 +6,7 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 21
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
@@ -26,6 +26,15 @@ runs:
|
|||||||
|
|
||||||
- name: Cache sccache
|
- name: Cache sccache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
with:
|
||||||
|
path: .sccache
|
||||||
|
key: sccache-${{ runner.os }}-${{ github.sha }}
|
||||||
|
restore-keys: sccache-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Restore sccache
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
path: .sccache
|
path: .sccache
|
||||||
key: sccache-${{ runner.os }}-${{ github.sha }}
|
key: sccache-${{ runner.os }}-${{ github.sha }}
|
||||||
@@ -55,7 +64,7 @@ runs:
|
|||||||
|
|
||||||
- name: Cache Gradle dependencies
|
- name: Cache Gradle dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
if: inputs.is-asset-build == 'true'
|
if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
.gradle/caches
|
.gradle/caches
|
||||||
@@ -66,7 +75,7 @@ runs:
|
|||||||
|
|
||||||
- name: Restore Gradle dependencies
|
- name: Restore Gradle dependencies
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
if: inputs.is-asset-build == 'false'
|
if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
.gradle/caches
|
.gradle/caches
|
||||||
@@ -78,19 +87,17 @@ runs:
|
|||||||
|
|
||||||
- name: Cache Gradle build cache
|
- name: Cache Gradle build cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
if: inputs.is-asset-build == 'true'
|
if: ${{ inputs.is-asset-build == 'true' && github.event_name != 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: .gradle/caches/build-cache-*
|
||||||
.gradle/caches/build-cache-*
|
|
||||||
key: gradle-build-cache-${{ github.sha }}
|
key: gradle-build-cache-${{ github.sha }}
|
||||||
restore-keys: gradle-build-cache-
|
restore-keys: gradle-build-cache-
|
||||||
|
|
||||||
- name: Restore Gradle build cache
|
- name: Restore Gradle build cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
if: inputs.is-asset-build == 'false'
|
if: ${{ inputs.is-asset-build == 'false' || github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: .gradle/caches/build-cache-*
|
||||||
.gradle/caches/build-cache-*
|
|
||||||
key: gradle-build-cache-${{ github.sha }}
|
key: gradle-build-cache-${{ github.sha }}
|
||||||
restore-keys: gradle-build-cache-
|
restore-keys: gradle-build-cache-
|
||||||
enableCrossOsArchive: true
|
enableCrossOsArchive: true
|
||||||
|
|||||||
33
.github/workflows/build.yml
vendored
33
.github/workflows/build.yml
vendored
@@ -6,9 +6,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "app/**"
|
- "app/**"
|
||||||
- "native/**"
|
- "native/**"
|
||||||
- "buildSrc/**"
|
|
||||||
- "build.py"
|
- "build.py"
|
||||||
- "gradle.properties"
|
|
||||||
- ".github/workflows/build.yml"
|
- ".github/workflows/build.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
@@ -17,7 +15,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build Magisk artifacts
|
name: Build Magisk artifacts
|
||||||
runs-on: macos-14
|
runs-on: macos-15
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
@@ -38,7 +36,7 @@ jobs:
|
|||||||
run: ./build.py -v all
|
run: ./build.py -v all
|
||||||
|
|
||||||
- name: Stop gradle daemon
|
- name: Stop gradle daemon
|
||||||
run: ./gradlew --stop
|
run: ./app/gradlew --stop
|
||||||
|
|
||||||
- name: Upload build artifact
|
- name: Upload build artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -60,7 +58,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest]
|
os: [windows-2025, ubuntu-24.04]
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -74,20 +72,23 @@ jobs:
|
|||||||
run: python build.py -v -c .github/ci.prop all
|
run: python build.py -v -c .github/ci.prop all
|
||||||
|
|
||||||
- name: Stop gradle daemon
|
- name: Stop gradle daemon
|
||||||
run: ./gradlew --stop
|
run: ./app/gradlew --stop
|
||||||
|
|
||||||
avd-test:
|
avd-test:
|
||||||
name: Test API ${{ matrix.version }} (x86_64)
|
name: Test API ${{ matrix.version }} (x86_64)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
needs: build
|
needs: build
|
||||||
|
if: ${{ github.event_name != 'push' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
|
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
|
||||||
type: [""]
|
type: [""]
|
||||||
include:
|
include:
|
||||||
- version: 35
|
- version: 36
|
||||||
type: "google_apis"
|
type: "google_apis"
|
||||||
|
- version: 36
|
||||||
|
type: "google_apis_ps16k"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
@@ -122,8 +123,9 @@ jobs:
|
|||||||
|
|
||||||
avd-test-32:
|
avd-test-32:
|
||||||
name: Test API ${{ matrix.version }} (x86)
|
name: Test API ${{ matrix.version }} (x86)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
needs: build
|
needs: build
|
||||||
|
if: ${{ github.event_name != 'push' }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -161,20 +163,19 @@ jobs:
|
|||||||
kernel.log
|
kernel.log
|
||||||
logcat.log
|
logcat.log
|
||||||
|
|
||||||
cf_test:
|
cf-test:
|
||||||
name: Test ${{ matrix.device }}
|
name: Test ${{ matrix.device }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: build
|
needs: build
|
||||||
|
if: ${{ github.event_name != 'push' }}
|
||||||
env:
|
env:
|
||||||
CF_HOME: /home/runner/aosp_cf_phone
|
CF_HOME: /home/runner/aosp_cf_phone
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- branch: "aosp-main"
|
- branch: "aosp-android-latest-release"
|
||||||
device: "aosp_cf_x86_64_phone"
|
device: "aosp_cf_x86_64_only_phone"
|
||||||
- branch: "aosp-main-throttled"
|
|
||||||
device: "aosp_cf_x86_64_phone_pgagnostic"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
@@ -193,7 +194,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run Cuttlefish test
|
- name: Run Cuttlefish test
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
run: su $USER -c 'scripts/cuttlefish.sh test'
|
run: sudo -E -u $USER scripts/cuttlefish.sh test
|
||||||
|
|
||||||
- name: Upload logs on error
|
- name: Upload logs on error
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -2,18 +2,13 @@ out
|
|||||||
*.zip
|
*.zip
|
||||||
*.jks
|
*.jks
|
||||||
*.apk
|
*.apk
|
||||||
|
*.log
|
||||||
/config.prop
|
/config.prop
|
||||||
/notes.md
|
/notes.md
|
||||||
/update.sh
|
|
||||||
/app/dict.txt
|
|
||||||
|
|
||||||
# Built binaries
|
# Built binaries
|
||||||
native/out
|
native/out
|
||||||
|
|
||||||
# Android Studio / Gradle
|
# Android Studio
|
||||||
*.iml
|
*.iml
|
||||||
.gradle
|
|
||||||
.idea
|
.idea
|
||||||
/local.properties
|
|
||||||
/build
|
|
||||||
/captures
|
|
||||||
|
|||||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -4,18 +4,12 @@
|
|||||||
[submodule "lz4"]
|
[submodule "lz4"]
|
||||||
path = native/src/external/lz4
|
path = native/src/external/lz4
|
||||||
url = https://github.com/lz4/lz4.git
|
url = https://github.com/lz4/lz4.git
|
||||||
[submodule "bzip2"]
|
|
||||||
path = native/src/external/bzip2
|
|
||||||
url = https://github.com/nemequ/bzip2.git
|
|
||||||
[submodule "xz"]
|
[submodule "xz"]
|
||||||
path = native/src/external/xz
|
path = native/src/external/xz
|
||||||
url = https://github.com/xz-mirror/xz.git
|
url = https://github.com/xz-mirror/xz.git
|
||||||
[submodule "libcxx"]
|
[submodule "libcxx"]
|
||||||
path = native/src/external/libcxx
|
path = native/src/external/libcxx
|
||||||
url = https://github.com/topjohnwu/libcxx.git
|
url = https://github.com/topjohnwu/libcxx.git
|
||||||
[submodule "zlib"]
|
|
||||||
path = native/src/external/zlib
|
|
||||||
url = https://android.googlesource.com/platform/external/zlib
|
|
||||||
[submodule "zopfli"]
|
[submodule "zopfli"]
|
||||||
path = native/src/external/zopfli
|
path = native/src/external/zopfli
|
||||||
url = https://github.com/google/zopfli.git
|
url = https://github.com/google/zopfli.git
|
||||||
@@ -31,6 +25,3 @@
|
|||||||
[submodule "crt0"]
|
[submodule "crt0"]
|
||||||
path = native/src/external/crt0
|
path = native/src/external/crt0
|
||||||
url = https://github.com/topjohnwu/crt0.git
|
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
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ Some highlight features:
|
|||||||
|
|
||||||
Click the icon below to download Magisk apk.
|
Click the icon below to download Magisk apk.
|
||||||
|
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.0)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v29.0)
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-27008)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-29001)
|
||||||
|
|
||||||
## Useful Links
|
## Useful Links
|
||||||
|
|
||||||
|
|||||||
7
app/.gitignore
vendored
Normal file
7
app/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/dict.txt
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.gradle
|
||||||
|
.kotlin
|
||||||
|
/local.properties
|
||||||
|
/build
|
||||||
@@ -6,7 +6,7 @@ plugins {
|
|||||||
id("androidx.navigation.safeargs.kotlin")
|
id("androidx.navigation.safeargs.kotlin")
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAppCommon()
|
setupMainApk()
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
correctErrorTypes = true
|
correctErrorTypes = true
|
||||||
@@ -18,27 +18,6 @@ kapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
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 {
|
buildFeatures {
|
||||||
dataBinding = true
|
dataBinding = true
|
||||||
}
|
}
|
||||||
@@ -46,10 +25,17 @@ android {
|
|||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":app:core"))
|
implementation(project(":core"))
|
||||||
coreLibraryDesugaring(libs.jdk.libs)
|
coreLibraryDesugaring(libs.jdk.libs)
|
||||||
|
|
||||||
implementation(libs.indeterminate.checkbox)
|
implementation(libs.indeterminate.checkbox)
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.arch
|
package com.topjohnwu.magisk.arch
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import androidx.navigation.navOptions
|
||||||
|
import com.topjohnwu.magisk.utils.AccessibilityUtils
|
||||||
|
|
||||||
abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Binding>() {
|
abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Binding>() {
|
||||||
|
|
||||||
@@ -31,7 +34,17 @@ abstract class NavigationActivity<Binding : ViewDataBinding> : UIActivity<Bindin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun navigate(directions: NavDirections, navigation: NavController, cr: ContentResolver) {
|
||||||
|
if (AccessibilityUtils.isAnimationEnabled(cr)) {
|
||||||
|
navigation.navigate(directions)
|
||||||
|
} else {
|
||||||
|
navigation.navigate(directions, navOptions {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun NavDirections.navigate() {
|
fun NavDirections.navigate() {
|
||||||
navigation.navigate(this)
|
navigate(this, navigation, contentResolver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
viewModel.startFlashing()
|
viewModel.startFlashing()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import com.topjohnwu.magisk.core.Info
|
|||||||
import com.topjohnwu.magisk.core.download.DownloadEngine
|
import com.topjohnwu.magisk.core.download.DownloadEngine
|
||||||
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
|
||||||
import com.topjohnwu.magisk.core.R as CoreR
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
import androidx.navigation.findNavController
|
||||||
|
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||||
|
|
||||||
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
||||||
|
|
||||||
@@ -68,7 +70,13 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
|||||||
override fun onMenuItemSelected(item: MenuItem): Boolean {
|
override fun onMenuItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_settings ->
|
R.id.action_settings ->
|
||||||
HomeFragmentDirections.actionHomeFragmentToSettingsFragment().navigate()
|
activity?.let {
|
||||||
|
NavigationActivity.navigate(
|
||||||
|
HomeFragmentDirections.actionHomeFragmentToSettingsFragment(),
|
||||||
|
it.findNavController(R.id.main_nav_host),
|
||||||
|
it.contentResolver,
|
||||||
|
)
|
||||||
|
}
|
||||||
R.id.action_reboot -> activity?.let { RebootMenu.inflate(it).show() }
|
R.id.action_reboot -> activity?.let { RebootMenu.inflate(it).show() }
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ object RebootMenu {
|
|||||||
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
|
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
|
||||||
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
|
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
|
||||||
}
|
}
|
||||||
if (Const.Version.isCanary()) {
|
if (Const.Version.atLeast_28_0()) {
|
||||||
menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
|
menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
|
||||||
} else {
|
} else {
|
||||||
menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
|
menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.view.Menu
|
|||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.HorizontalScrollView
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
@@ -12,6 +13,7 @@ import com.topjohnwu.magisk.arch.BaseFragment
|
|||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
import com.topjohnwu.magisk.ui.MainActivity
|
||||||
|
import com.topjohnwu.magisk.utils.AccessibilityUtils
|
||||||
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
||||||
import rikka.recyclerview.addEdgeSpacing
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
@@ -56,6 +58,11 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
|
|||||||
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
fixEdgeEffect()
|
fixEdgeEffect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!AccessibilityUtils.isAnimationEnabled(requireContext().contentResolver)) {
|
||||||
|
val scrollView = view.findViewById<HorizontalScrollView>(R.id.log_scroll_magisk)
|
||||||
|
scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.view.Menu
|
|||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewTreeObserver
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@@ -16,8 +17,6 @@ import com.topjohnwu.magisk.arch.BaseFragment
|
|||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding
|
||||||
import com.topjohnwu.magisk.ui.flash.FlashViewModel
|
|
||||||
import timber.log.Timber
|
|
||||||
import com.topjohnwu.magisk.core.R as CoreR
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
||||||
@@ -37,39 +36,32 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
|||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.setTitle(viewModel.args.name)
|
activity?.setTitle(viewModel.args.name)
|
||||||
binding.closeBtn.setOnClickListener {
|
binding.closeBtn.setOnClickListener {
|
||||||
activity?.onBackPressed();
|
activity?.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.state.observe(this) {
|
viewModel.state.observe(this) {
|
||||||
activity?.supportActionBar?.setSubtitle(
|
if (it != ActionViewModel.State.RUNNING) {
|
||||||
when (it) {
|
binding.closeBtn.apply {
|
||||||
ActionViewModel.State.RUNNING -> CoreR.string.running
|
if (!this.isVisible) this.show()
|
||||||
ActionViewModel.State.SUCCESS -> CoreR.string.done
|
if (!this.isFocused) this.requestFocus()
|
||||||
ActionViewModel.State.FAILED -> CoreR.string.failure
|
}
|
||||||
|
}
|
||||||
|
if (it != ActionViewModel.State.SUCCESS) return@observe
|
||||||
|
view?.viewTreeObserver?.addOnWindowFocusChangeListener(
|
||||||
|
object : ViewTreeObserver.OnWindowFocusChangeListener {
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
if (hasFocus) return
|
||||||
|
view?.viewTreeObserver?.removeOnWindowFocusChangeListener(this)
|
||||||
|
view?.context?.apply {
|
||||||
|
toast(
|
||||||
|
getString(CoreR.string.done_action, viewModel.args.name),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
viewModel.back()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
when (it) {
|
|
||||||
ActionViewModel.State.SUCCESS -> {
|
|
||||||
activity?.apply {
|
|
||||||
toast(
|
|
||||||
getString(
|
|
||||||
com.topjohnwu.magisk.core.R.string.done_action,
|
|
||||||
this@ActionFragment.viewModel.args.name
|
|
||||||
), Toast.LENGTH_LONG
|
|
||||||
)
|
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActionViewModel.State.FAILED -> {
|
|
||||||
binding.closeBtn.apply {
|
|
||||||
if (!this.isVisible) this.show()
|
|
||||||
if (!this.isFocused) this.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +77,7 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
defaultOrientation = activity?.requestedOrientation ?: -1
|
defaultOrientation = activity?.requestedOrientation ?: -1
|
||||||
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
viewModel.startRunAction()
|
viewModel.startRunAction()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,26 @@
|
|||||||
package com.topjohnwu.magisk.ui.module
|
package com.topjohnwu.magisk.ui.module
|
||||||
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.databinding.Bindable
|
|
||||||
import androidx.databinding.ObservableArrayList
|
import androidx.databinding.ObservableArrayList
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.map
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
import com.topjohnwu.magisk.core.Info
|
|
||||||
import com.topjohnwu.magisk.core.ktx.synchronized
|
import com.topjohnwu.magisk.core.ktx.synchronized
|
||||||
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
|
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
|
||||||
import com.topjohnwu.magisk.core.ktx.toTime
|
import com.topjohnwu.magisk.core.ktx.toTime
|
||||||
import com.topjohnwu.magisk.core.tasks.RunAction
|
|
||||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||||
import com.topjohnwu.magisk.databinding.set
|
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.ui.flash.ConsoleItem
|
import com.topjohnwu.magisk.ui.flash.ConsoleItem
|
||||||
import com.topjohnwu.superuser.CallbackList
|
import com.topjohnwu.superuser.CallbackList
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
class ActionViewModel : BaseViewModel() {
|
class ActionViewModel : BaseViewModel() {
|
||||||
|
|
||||||
@@ -32,7 +30,6 @@ class ActionViewModel : BaseViewModel() {
|
|||||||
|
|
||||||
private val _state = MutableLiveData(State.RUNNING)
|
private val _state = MutableLiveData(State.RUNNING)
|
||||||
val state: LiveData<State> get() = _state
|
val state: LiveData<State> get() = _state
|
||||||
val running = state.map { it == State.RUNNING }
|
|
||||||
|
|
||||||
val items = ObservableArrayList<ConsoleItem>()
|
val items = ObservableArrayList<ConsoleItem>()
|
||||||
lateinit var args: ActionFragmentArgs
|
lateinit var args: ActionFragmentArgs
|
||||||
@@ -46,10 +43,17 @@ class ActionViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startRunAction() {
|
fun startRunAction() = viewModelScope.launch {
|
||||||
viewModelScope.launch {
|
onResult(withContext(Dispatchers.IO) {
|
||||||
onResult(RunAction(args.id, outItems, logItems).exec())
|
try {
|
||||||
}
|
Shell.cmd("run_action \'${args.id}\'")
|
||||||
|
.to(outItems, logItems)
|
||||||
|
.exec().isSuccess
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Timber.e(e)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onResult(success: Boolean) {
|
private fun onResult(success: Boolean) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.topjohnwu.magisk.BR
|
|||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
import com.topjohnwu.magisk.core.AppContext
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
import com.topjohnwu.magisk.core.BuildConfig
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.R
|
import com.topjohnwu.magisk.core.R
|
||||||
@@ -92,7 +93,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
DownloadPath -> withExternalRW(doAction)
|
DownloadPath -> withExternalRW(doAction)
|
||||||
UpdateChecker -> withPostNotificationPermission(doAction)
|
UpdateChecker -> withPostNotificationPermission(doAction)
|
||||||
Authentication -> AuthEvent(doAction).publish()
|
Authentication -> AuthEvent(doAction).publish()
|
||||||
Hide, Restore -> withInstallPermission(doAction)
|
AutomaticResponse -> if (Config.suAuth) AuthEvent(doAction).publish() else doAction()
|
||||||
else -> doAction()
|
else -> doAction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.provider.Settings
|
||||||
|
|
||||||
|
class AccessibilityUtils {
|
||||||
|
companion object {
|
||||||
|
fun isAnimationEnabled(cr: ContentResolver): Boolean {
|
||||||
|
return !(Settings.Global.getFloat(cr, Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f) == 0.0f
|
||||||
|
&& Settings.Global.getFloat(cr, Settings.Global.TRANSITION_ANIMATION_SCALE, 1.0f) == 0.0f
|
||||||
|
&& Settings.Global.getFloat(cr, Settings.Global.WINDOW_ANIMATION_SCALE, 1.0f) == 0.0f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
|
android:id="@+id/log_scroll_magisk"
|
||||||
gone="@{viewModel.loading}"
|
gone="@{viewModel.loading}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
tasks.register("clean") {
|
plugins {
|
||||||
|
id("MagiskPlugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("clean", Delete::class) {
|
||||||
|
delete(rootProject.layout.buildDirectory)
|
||||||
|
|
||||||
subprojects.forEach {
|
subprojects.forEach {
|
||||||
dependsOn(":app:${it.name}:clean")
|
dependsOn(":${it.name}:clean")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
@@ -18,9 +18,9 @@ gradlePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile>().configureEach {
|
kotlin {
|
||||||
kotlinOptions {
|
compilerOptions {
|
||||||
languageVersion = "2.0"
|
languageVersion = KotlinVersion.KOTLIN_2_0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
122
app/buildSrc/src/main/java/DesugarClassVisitorFactory.kt
Normal file
122
app/buildSrc/src/main/java/DesugarClassVisitorFactory.kt
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import com.android.build.api.instrumentation.AsmClassVisitorFactory
|
||||||
|
import com.android.build.api.instrumentation.ClassContext
|
||||||
|
import com.android.build.api.instrumentation.ClassData
|
||||||
|
import com.android.build.api.instrumentation.InstrumentationParameters
|
||||||
|
import org.objectweb.asm.ClassVisitor
|
||||||
|
import org.objectweb.asm.MethodVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import org.objectweb.asm.Opcodes.ASM9
|
||||||
|
|
||||||
|
private const val DESUGAR_CLASS_NAME = "com.topjohnwu.magisk.core.utils.Desugar"
|
||||||
|
private const val ZIP_ENTRY_CLASS_NAME = "java.util.zip.ZipEntry"
|
||||||
|
private const val ZIP_OUT_STREAM_CLASS_NAME = "org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream"
|
||||||
|
private const val ZIP_UTIL_CLASS_NAME = "org/apache/commons/compress/archivers/zip/ZipUtil"
|
||||||
|
private const val ZIP_ENTRY_GET_TIME_DESC = "()Ljava/nio/file/attribute/FileTime;"
|
||||||
|
private const val DESUGAR_GET_TIME_DESC =
|
||||||
|
"(Ljava/util/zip/ZipEntry;)Ljava/nio/file/attribute/FileTime;"
|
||||||
|
|
||||||
|
private fun ClassData.isTypeOf(name: String) = className == name || superClasses.contains(name)
|
||||||
|
|
||||||
|
abstract class DesugarClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> {
|
||||||
|
override fun createClassVisitor(
|
||||||
|
classContext: ClassContext,
|
||||||
|
nextClassVisitor: ClassVisitor
|
||||||
|
): ClassVisitor {
|
||||||
|
return if (classContext.currentClassData.className == ZIP_OUT_STREAM_CLASS_NAME) {
|
||||||
|
ZipEntryPatcher(classContext, ZipOutputStreamPatcher(nextClassVisitor))
|
||||||
|
} else {
|
||||||
|
ZipEntryPatcher(classContext, nextClassVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isInstrumentable(classData: ClassData) = classData.className != DESUGAR_CLASS_NAME
|
||||||
|
|
||||||
|
// Patch ALL references to ZipEntry#getXXXTime
|
||||||
|
class ZipEntryPatcher(
|
||||||
|
private val classContext: ClassContext,
|
||||||
|
cv: ClassVisitor
|
||||||
|
) : ClassVisitor(ASM9, cv) {
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
name: String?,
|
||||||
|
descriptor: String?,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<out String>?
|
||||||
|
) = MethodPatcher(super.visitMethod(access, name, descriptor, signature, exceptions))
|
||||||
|
|
||||||
|
inner class MethodPatcher(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
|
||||||
|
override fun visitMethodInsn(
|
||||||
|
opcode: Int,
|
||||||
|
owner: String,
|
||||||
|
name: String,
|
||||||
|
descriptor: String,
|
||||||
|
isInterface: Boolean
|
||||||
|
) {
|
||||||
|
if (!process(owner, name, descriptor)) {
|
||||||
|
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun process(owner: String, name: String, descriptor: String): Boolean {
|
||||||
|
val classData = classContext.loadClassData(owner.replace("/", ".")) ?: return false
|
||||||
|
if (!classData.isTypeOf(ZIP_ENTRY_CLASS_NAME))
|
||||||
|
return false
|
||||||
|
if (descriptor != ZIP_ENTRY_GET_TIME_DESC)
|
||||||
|
return false
|
||||||
|
return when (name) {
|
||||||
|
"getLastModifiedTime", "getLastAccessTime", "getCreationTime" -> {
|
||||||
|
mv.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESTATIC,
|
||||||
|
DESUGAR_CLASS_NAME.replace('.', '/'),
|
||||||
|
name,
|
||||||
|
DESUGAR_GET_TIME_DESC,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch ZipArchiveOutputStream#copyFromZipInputStream
|
||||||
|
class ZipOutputStreamPatcher(cv: ClassVisitor) : ClassVisitor(ASM9, cv) {
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
name: String,
|
||||||
|
descriptor: String,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<out String?>?
|
||||||
|
): MethodVisitor? {
|
||||||
|
return if (name == "copyFromZipInputStream") {
|
||||||
|
MethodPatcher(super.visitMethod(access, name, descriptor, signature, exceptions))
|
||||||
|
} else {
|
||||||
|
super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MethodPatcher(mv: MethodVisitor?) : MethodVisitor(ASM9, mv) {
|
||||||
|
override fun visitMethodInsn(
|
||||||
|
opcode: Int,
|
||||||
|
owner: String,
|
||||||
|
name: String,
|
||||||
|
descriptor: String?,
|
||||||
|
isInterface: Boolean
|
||||||
|
) {
|
||||||
|
if (owner == ZIP_UTIL_CLASS_NAME && name == "checkRequestedFeatures") {
|
||||||
|
// Redirect
|
||||||
|
mv.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESTATIC,
|
||||||
|
DESUGAR_CLASS_NAME.replace('.', '/'),
|
||||||
|
name,
|
||||||
|
descriptor,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ private val defaultAbis = setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64")
|
|||||||
object Config {
|
object Config {
|
||||||
operator fun get(key: String): String? {
|
operator fun get(key: String): String? {
|
||||||
val v = props[key] as? String ?: return null
|
val v = props[key] as? String ?: return null
|
||||||
return if (v.isBlank()) null else v
|
return v.ifBlank { null }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contains(key: String) = get(key) != null
|
fun contains(key: String) = get(key) != null
|
||||||
@@ -28,19 +28,21 @@ object Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Project.baseDir: File get() = rootProject.file("..")
|
||||||
|
|
||||||
class MagiskPlugin : Plugin<Project> {
|
class MagiskPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project) = project.applyPlugin()
|
override fun apply(project: Project) = project.applyPlugin()
|
||||||
|
|
||||||
private fun Project.applyPlugin() {
|
private fun Project.applyPlugin() {
|
||||||
initRandom(rootProject.file("app/dict.txt"))
|
initRandom(rootProject.file("dict.txt"))
|
||||||
props.clear()
|
props.clear()
|
||||||
rootProject.file("gradle.properties").inputStream().use { props.load(it) }
|
rootProject.file("gradle.properties").inputStream().use { props.load(it) }
|
||||||
val configPath: String? by this
|
val configPath: String? by this
|
||||||
val config = configPath?.let { File(it) } ?: rootProject.file("config.prop")
|
val config = configPath?.let { File(it) } ?: File(baseDir, "config.prop")
|
||||||
if (config.exists())
|
if (config.exists())
|
||||||
config.inputStream().use { props.load(it) }
|
config.inputStream().use { props.load(it) }
|
||||||
|
|
||||||
val repo = FileRepository(rootProject.file(".git"))
|
val repo = FileRepository(File(baseDir, ".git"))
|
||||||
val refId = repo.refDatabase.exactRef("HEAD").objectId
|
val refId = repo.refDatabase.exactRef("HEAD").objectId
|
||||||
commitHash = repo.newObjectReader().abbreviate(refId, 8).name()
|
commitHash = repo.newObjectReader().abbreviate(refId, 8).name()
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import com.android.build.api.artifact.ArtifactTransformationRequest
|
import com.android.build.api.artifact.ArtifactTransformationRequest
|
||||||
import com.android.build.api.artifact.SingleArtifact
|
import com.android.build.api.artifact.SingleArtifact
|
||||||
import com.android.build.api.dsl.ApkSigningConfig
|
import com.android.build.api.dsl.ApkSigningConfig
|
||||||
|
import com.android.build.api.instrumentation.FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
|
||||||
|
import com.android.build.api.instrumentation.InstrumentationScope
|
||||||
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
||||||
import com.android.build.gradle.BaseExtension
|
import com.android.build.gradle.BaseExtension
|
||||||
import com.android.build.gradle.LibraryExtension
|
import com.android.build.gradle.LibraryExtension
|
||||||
@@ -69,10 +71,10 @@ private val Project.androidComponents
|
|||||||
|
|
||||||
fun Project.setupCommon() {
|
fun Project.setupCommon() {
|
||||||
androidBase {
|
androidBase {
|
||||||
compileSdkVersion(35)
|
compileSdkVersion(36)
|
||||||
buildToolsVersion = "34.0.0"
|
buildToolsVersion = "36.0.0"
|
||||||
ndkPath = "$sdkDirectory/ndk/magisk"
|
ndkPath = "$sdkDirectory/ndk/magisk"
|
||||||
ndkVersion = "27.0.12077973"
|
ndkVersion = "29.0.13113456"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
@@ -87,6 +89,7 @@ fun Project.setupCommon() {
|
|||||||
resources {
|
resources {
|
||||||
excludes += arrayOf(
|
excludes += arrayOf(
|
||||||
"/META-INF/*",
|
"/META-INF/*",
|
||||||
|
"/META-INF/androidx/**",
|
||||||
"/META-INF/versions/**",
|
"/META-INF/versions/**",
|
||||||
"/org/bouncycastle/**",
|
"/org/bouncycastle/**",
|
||||||
"/org/apache/commons/**",
|
"/org/apache/commons/**",
|
||||||
@@ -113,6 +116,27 @@ fun Project.setupCommon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Project.downloadFile(url: String, checksum: String): File {
|
||||||
|
val file = layout.buildDirectory.file(checksum).get().asFile
|
||||||
|
if (file.exists()) {
|
||||||
|
val md = MessageDigest.getInstance("SHA-256")
|
||||||
|
file.inputStream().use { md.update(it.readAllBytes()) }
|
||||||
|
val hash = HexFormat.of().formatHex(md.digest())
|
||||||
|
if (hash != checksum) {
|
||||||
|
file.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.parentFile.mkdirs()
|
||||||
|
URI(url).toURL().openStream().use { dl ->
|
||||||
|
file.outputStream().use {
|
||||||
|
dl.copyTo(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
const val BUSYBOX_DOWNLOAD_URL =
|
const val BUSYBOX_DOWNLOAD_URL =
|
||||||
"https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.1.zip"
|
"https://github.com/topjohnwu/magisk-files/releases/download/files/busybox-1.36.1.1.zip"
|
||||||
const val BUSYBOX_ZIP_CHECKSUM =
|
const val BUSYBOX_ZIP_CHECKSUM =
|
||||||
@@ -127,7 +151,7 @@ fun Project.setupCoreLib() {
|
|||||||
into("src/main/jniLibs")
|
into("src/main/jniLibs")
|
||||||
for (abi in abiList) {
|
for (abi in abiList) {
|
||||||
into(abi) {
|
into(abi) {
|
||||||
from(rootProject.file("native/out/$abi")) {
|
from(File(baseDir, "native/out/$abi")) {
|
||||||
include("magiskboot", "magiskinit", "magiskpolicy", "magisk", "libinit-ld.so")
|
include("magiskboot", "magiskinit", "magiskpolicy", "magisk", "libinit-ld.so")
|
||||||
rename { if (it.endsWith(".so")) it else "lib$it.so" }
|
rename { if (it.endsWith(".so")) it else "lib$it.so" }
|
||||||
}
|
}
|
||||||
@@ -142,34 +166,17 @@ fun Project.setupCoreLib() {
|
|||||||
|
|
||||||
val downloadBusybox by tasks.registering(Copy::class) {
|
val downloadBusybox by tasks.registering(Copy::class) {
|
||||||
dependsOn(syncLibs)
|
dependsOn(syncLibs)
|
||||||
val bb = layout.buildDirectory.file(BUSYBOX_ZIP_CHECKSUM).get().asFile
|
from(zipTree(downloadFile(BUSYBOX_DOWNLOAD_URL, BUSYBOX_ZIP_CHECKSUM)))
|
||||||
if (bb.exists()) {
|
|
||||||
val md = MessageDigest.getInstance("SHA-256")
|
|
||||||
bb.inputStream().use { md.update(it.readAllBytes()) }
|
|
||||||
val hash = HexFormat.of().formatHex(md.digest())
|
|
||||||
if (hash != BUSYBOX_ZIP_CHECKSUM) {
|
|
||||||
bb.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!bb.exists()) {
|
|
||||||
bb.parentFile.mkdirs()
|
|
||||||
URI(BUSYBOX_DOWNLOAD_URL).toURL().openStream().use { dl ->
|
|
||||||
bb.outputStream().use {
|
|
||||||
dl.copyTo(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
from(zipTree(bb))
|
|
||||||
include(abiList.map { "$it/libbusybox.so" })
|
include(abiList.map { "$it/libbusybox.so" })
|
||||||
into("src/main/jniLibs")
|
into("src/main/jniLibs")
|
||||||
}
|
}
|
||||||
|
|
||||||
val syncResources by tasks.registering(Sync::class) {
|
val syncResources by tasks.registering(Sync::class) {
|
||||||
into("src/main/resources/META-INF/com/google/android")
|
into("src/main/resources/META-INF/com/google/android")
|
||||||
from(rootProject.file("scripts/update_binary.sh")) {
|
from(File(baseDir, "scripts/update_binary.sh")) {
|
||||||
rename { "update-binary" }
|
rename { "update-binary" }
|
||||||
}
|
}
|
||||||
from(rootProject.file("scripts/flash_script.sh")) {
|
from(File(baseDir, "scripts/flash_script.sh")) {
|
||||||
rename { "updater-script" }
|
rename { "updater-script" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +187,7 @@ fun Project.setupCoreLib() {
|
|||||||
tasks.getByPath("merge${variantCapped}JniLibFolders").dependsOn(downloadBusybox)
|
tasks.getByPath("merge${variantCapped}JniLibFolders").dependsOn(downloadBusybox)
|
||||||
processJavaResourcesProvider.configure { dependsOn(syncResources) }
|
processJavaResourcesProvider.configure { dependsOn(syncResources) }
|
||||||
|
|
||||||
val stubTask = tasks.getByPath(":app:stub:comment$variantCapped")
|
val stubTask = tasks.getByPath(":stub:comment$variantCapped")
|
||||||
val stubApk = stubTask.outputs.files.asFileTree.filter {
|
val stubApk = stubTask.outputs.files.asFileTree.filter {
|
||||||
it.name.endsWith(".apk")
|
it.name.endsWith(".apk")
|
||||||
}
|
}
|
||||||
@@ -190,14 +197,14 @@ fun Project.setupCoreLib() {
|
|||||||
inputs.property("version", Config.version)
|
inputs.property("version", Config.version)
|
||||||
inputs.property("versionCode", Config.versionCode)
|
inputs.property("versionCode", Config.versionCode)
|
||||||
into("src/${this@all.name}/assets")
|
into("src/${this@all.name}/assets")
|
||||||
from(rootProject.file("scripts")) {
|
from(File(baseDir, "scripts")) {
|
||||||
include("util_functions.sh", "boot_patch.sh", "addon.d.sh",
|
include("util_functions.sh", "boot_patch.sh", "addon.d.sh",
|
||||||
"app_functions.sh", "uninstaller.sh", "module_installer.sh")
|
"app_functions.sh", "uninstaller.sh", "module_installer.sh")
|
||||||
}
|
}
|
||||||
from(rootProject.file("tools/bootctl"))
|
from(File(baseDir, "tools/bootctl"))
|
||||||
into("chromeos") {
|
into("chromeos") {
|
||||||
from(rootProject.file("tools/futility"))
|
from(File(baseDir, "tools/futility"))
|
||||||
from(rootProject.file("tools/keys")) {
|
from(File(baseDir, "tools/keys")) {
|
||||||
include("kernel_data_key.vbprivk", "kernel.keyblock")
|
include("kernel_data_key.vbprivk", "kernel.keyblock")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,7 +294,7 @@ fun Project.setupAppCommon() {
|
|||||||
signingConfigs {
|
signingConfigs {
|
||||||
create("config") {
|
create("config") {
|
||||||
Config["keyStore"]?.also {
|
Config["keyStore"]?.also {
|
||||||
storeFile = rootProject.file(it)
|
storeFile = File(baseDir, it)
|
||||||
storePassword = Config["keyStorePass"]
|
storePassword = Config["keyStorePass"]
|
||||||
keyAlias = Config["keyAlias"]
|
keyAlias = Config["keyAlias"]
|
||||||
keyPassword = Config["keyPass"]
|
keyPassword = Config["keyPass"]
|
||||||
@@ -296,7 +303,10 @@ fun Project.setupAppCommon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
targetSdk = 35
|
targetSdk = 36
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -348,7 +358,34 @@ fun Project.setupAppCommon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Project.setupStub() {
|
fun Project.setupMainApk() {
|
||||||
|
setupAppCommon()
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
androidComponents.onVariants { variant ->
|
||||||
|
variant.instrumentation.apply {
|
||||||
|
setAsmFramesComputationMode(COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS)
|
||||||
|
transformClassesWith(
|
||||||
|
DesugarClassVisitorFactory::class.java, InstrumentationScope.ALL) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.setupStubApk() {
|
||||||
setupAppCommon()
|
setupAppCommon()
|
||||||
|
|
||||||
androidComponents.onVariants { variant ->
|
androidComponents.onVariants { variant ->
|
||||||
@@ -430,3 +467,31 @@ fun Project.setupStub() {
|
|||||||
delete.addAll(listOf("src/debug/AndroidManifest.xml", "src/release/AndroidManifest.xml"))
|
delete.addAll(listOf("src/debug/AndroidManifest.xml", "src/release/AndroidManifest.xml"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val LSPOSED_DOWNLOAD_URL =
|
||||||
|
"https://github.com/LSPosed/LSPosed/releases/download/v1.9.2/LSPosed-v1.9.2-7024-zygisk-release.zip"
|
||||||
|
const val LSPOSED_CHECKSUM =
|
||||||
|
"0ebc6bcb465d1c4b44b7220ab5f0252e6b4eb7fe43da74650476d2798bb29622"
|
||||||
|
|
||||||
|
const val SHAMIKO_DOWNLOAD_URL =
|
||||||
|
"https://github.com/LSPosed/LSPosed.github.io/releases/download/shamiko-383/Shamiko-v1.2.1-383-release.zip"
|
||||||
|
const val SHAMIKO_CHECKSUM =
|
||||||
|
"93754a038c2d8f0e985bad45c7303b96f70a93d8335060e50146f028d3a9b13f"
|
||||||
|
|
||||||
|
fun Project.setupTestApk() {
|
||||||
|
setupAppCommon()
|
||||||
|
|
||||||
|
androidApp.applicationVariants.all {
|
||||||
|
val variantCapped = name.replaceFirstChar { it.uppercase() }
|
||||||
|
val dlTask by tasks.register("download${variantCapped}Lsposed", Sync::class) {
|
||||||
|
from(downloadFile(LSPOSED_DOWNLOAD_URL, LSPOSED_CHECKSUM)) {
|
||||||
|
rename { "lsposed.zip" }
|
||||||
|
}
|
||||||
|
from(downloadFile(SHAMIKO_DOWNLOAD_URL, SHAMIKO_CHECKSUM)) {
|
||||||
|
rename { "shamiko.zip" }
|
||||||
|
}
|
||||||
|
into("src/${this@all.name}/assets")
|
||||||
|
}
|
||||||
|
mergeAssetsProvider.configure { dependsOn(dlTask) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ android {
|
|||||||
buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}")
|
buildConfigField("int", "APP_VERSION_CODE", "${Config.versionCode}")
|
||||||
buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"")
|
buildConfigField("String", "APP_VERSION_NAME", "\"${Config.version}\"")
|
||||||
buildConfigField("int", "STUB_VERSION", Config.stubVersion)
|
buildConfigField("int", "STUB_VERSION", Config.stubVersion)
|
||||||
|
consumerProguardFile("proguard-rules.pro")
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
@@ -28,7 +29,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":app:shared"))
|
api(project(":shared"))
|
||||||
|
|
||||||
api(libs.timber)
|
api(libs.timber)
|
||||||
api(libs.markwon.core)
|
api(libs.markwon.core)
|
||||||
@@ -59,5 +60,10 @@ dependencies {
|
|||||||
implementation(libs.activity)
|
implementation(libs.activity)
|
||||||
implementation(libs.collection.ktx)
|
implementation(libs.collection.ktx)
|
||||||
implementation(libs.profileinstaller)
|
implementation(libs.profileinstaller)
|
||||||
implementation(libs.lifecycle.process)
|
|
||||||
|
// We also implement all our tests in this module.
|
||||||
|
// However, we don't want to bundle test dependencies.
|
||||||
|
// That's why we make it compileOnly.
|
||||||
|
compileOnly(libs.test.junit)
|
||||||
|
compileOnly(libs.test.uiautomator)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,42 +22,19 @@
|
|||||||
int mActivityHandlesConfigFlags;
|
int mActivityHandlesConfigFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
# main
|
|
||||||
-keep,allowoptimization public class com.topjohnwu.magisk.signing.SignBoot {
|
|
||||||
public static void main(java.lang.String[]);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Strip Timber verbose and debug logging
|
# Strip Timber verbose and debug logging
|
||||||
-assumenosideeffects class timber.log.Timber$Tree {
|
-assumenosideeffects class timber.log.Timber$Tree {
|
||||||
public void v(**);
|
public void v(**);
|
||||||
public void d(**);
|
public void d(**);
|
||||||
}
|
}
|
||||||
|
|
||||||
# https://github.com/square/retrofit/issues/3751#issuecomment-1192043644
|
|
||||||
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
|
|
||||||
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
|
|
||||||
-keep,allowobfuscation,allowshrinking class retrofit2.Response
|
|
||||||
|
|
||||||
# With R8 full mode generic signatures are stripped for classes that are not
|
# With R8 full mode generic signatures are stripped for classes that are not
|
||||||
# kept. Suspend functions are wrapped in continuations where the type argument
|
# kept. Suspend functions are wrapped in continuations where the type argument
|
||||||
# is used.
|
# is used.
|
||||||
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
|
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
|
||||||
|
|
||||||
|
|
||||||
# Excessive obfuscation
|
# Excessive obfuscation
|
||||||
-repackageclasses 'a'
|
-flattenpackagehierarchy
|
||||||
-allowaccessmodification
|
-allowaccessmodification
|
||||||
|
|
||||||
-obfuscationdictionary ../dict.txt
|
-dontwarn org.junit.**
|
||||||
-classobfuscationdictionary ../dict.txt
|
|
||||||
-packageobfuscationdictionary ../dict.txt
|
|
||||||
|
|
||||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
|
|
||||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
|
||||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
|
|
||||||
-dontwarn org.commonmark.ext.gfm.strikethrough.Strikethrough
|
|
||||||
-dontwarn org.conscrypt.Conscrypt*
|
|
||||||
-dontwarn org.conscrypt.ConscryptHostnameVerifier
|
|
||||||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
|
|
||||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
|
||||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:multiArch="true"
|
|
||||||
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"
|
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"
|
||||||
tools:remove="android:appComponentFactory">
|
tools:remove="android:appComponentFactory">
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import com.topjohnwu.magisk.StubApk
|
|||||||
import com.topjohnwu.magisk.core.base.UntrackedActivity
|
import com.topjohnwu.magisk.core.base.UntrackedActivity
|
||||||
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
import com.topjohnwu.magisk.core.utils.NetworkObserver
|
import com.topjohnwu.magisk.core.utils.NetworkObserver
|
||||||
import com.topjohnwu.magisk.core.utils.ProcessLifecycle
|
|
||||||
import com.topjohnwu.magisk.core.utils.RootUtils
|
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||||
import com.topjohnwu.magisk.core.utils.ShellInit
|
import com.topjohnwu.magisk.core.utils.ShellInit
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@@ -40,6 +39,7 @@ object AppContext : ContextWrapper(null),
|
|||||||
|
|
||||||
private var ref = WeakReference<Activity>(null)
|
private var ref = WeakReference<Activity>(null)
|
||||||
private lateinit var application: Application
|
private lateinit var application: Application
|
||||||
|
private lateinit var networkObserver: NetworkObserver
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Always log full stack trace with Timber
|
// Always log full stack trace with Timber
|
||||||
@@ -56,6 +56,10 @@ object AppContext : ContextWrapper(null),
|
|||||||
LocaleSetting.instance.updateResource(resources)
|
LocaleSetting.instance.updateResource(resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityStarted(activity: Activity) {
|
||||||
|
networkObserver.postCurrentState()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onActivityResumed(activity: Activity) {
|
override fun onActivityResumed(activity: Activity) {
|
||||||
if (activity is UntrackedActivity) return
|
if (activity is UntrackedActivity) return
|
||||||
ref = WeakReference(activity)
|
ref = WeakReference(activity)
|
||||||
@@ -102,8 +106,7 @@ object AppContext : ContextWrapper(null),
|
|||||||
val lm = getSystemService(LocaleManager::class.java)
|
val lm = getSystemService(LocaleManager::class.java)
|
||||||
lm.overrideLocaleConfig = LocaleSetting.localeConfig
|
lm.overrideLocaleConfig = LocaleSetting.localeConfig
|
||||||
}
|
}
|
||||||
ProcessLifecycle.init(this)
|
networkObserver = NetworkObserver.init(this)
|
||||||
NetworkObserver.init(this)
|
|
||||||
if (!BuildConfig.DEBUG && !isRunningAsStub) {
|
if (!BuildConfig.DEBUG && !isRunningAsStub) {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
ProfileInstaller.writeProfile(this@AppContext)
|
ProfileInstaller.writeProfile(this@AppContext)
|
||||||
@@ -120,7 +123,6 @@ object AppContext : ContextWrapper(null),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
|
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
|
||||||
override fun onActivityStarted(activity: Activity) {}
|
|
||||||
override fun onActivityStopped(activity: Activity) {}
|
override fun onActivityStopped(activity: Activity) {}
|
||||||
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}
|
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {}
|
||||||
override fun onActivityDestroyed(activity: Activity) {}
|
override fun onActivityDestroyed(activity: Activity) {}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ object Config : PreferenceConfig, DBConfig {
|
|||||||
const val SU_AUTO_ALLOW = 2
|
const val SU_AUTO_ALLOW = 2
|
||||||
|
|
||||||
// su timeout
|
// su timeout
|
||||||
val TIMEOUT_LIST = intArrayOf(0, -1, 10, 20, 30, 60)
|
val TIMEOUT_LIST = longArrayOf(0, -1, 10, 20, 30, 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val defaultChannel =
|
private val defaultChannel =
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ object Const {
|
|||||||
else Build.SUPPORTED_32_BIT_ABIS.firstOrNull()
|
else Build.SUPPORTED_32_BIT_ABIS.firstOrNull()
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
const val MAGISK_PATH = "/data/adb/modules"
|
const val MODULE_PATH = "/data/adb/modules"
|
||||||
const val TMPDIR = "/dev/tmp"
|
const val TMPDIR = "/dev/tmp"
|
||||||
const val MAGISK_LOG = "/cache/magisk.log"
|
const val MAGISK_LOG = "/cache/magisk.log"
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ object Const {
|
|||||||
|
|
||||||
fun atLeast_24_0() = Info.env.versionCode >= 24000 || isCanary()
|
fun atLeast_24_0() = Info.env.versionCode >= 24000 || isCanary()
|
||||||
fun atLeast_25_0() = Info.env.versionCode >= 25000 || isCanary()
|
fun atLeast_25_0() = Info.env.versionCode >= 25000 || isCanary()
|
||||||
|
fun atLeast_28_0() = Info.env.versionCode >= 28000 || isCanary()
|
||||||
fun isCanary() = isCanary(Info.env.versionCode)
|
fun isCanary() = isCanary(Info.env.versionCode)
|
||||||
|
|
||||||
fun isCanary(ver: Int) = ver > 0 && ver % 100 != 0
|
fun isCanary(ver: Int) = ver > 0 && ver % 100 != 0
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user