You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1b1a9e627 | ||
|
|
6159cea2f7 | ||
|
|
2e56870e77 | ||
|
|
10f7d5cf50 | ||
|
|
0c883ddfd6 | ||
|
|
3921175e4c | ||
|
|
84fdcf8bf5 | ||
|
|
886cfd5a33 | ||
|
|
aea384bdd4 | ||
|
|
84695cea71 | ||
|
|
f91afe6c46 | ||
|
|
3f7e731df6 | ||
|
|
582662dce9 | ||
|
|
f3b49723e8 | ||
|
|
c4deee1e49 | ||
|
|
6a6fc07cd4 | ||
|
|
d8cb7ef772 | ||
|
|
dddf2f06a0 | ||
|
|
e7e935aeb2 | ||
|
|
cb146200aa | ||
|
|
609926bff1 | ||
|
|
8803058521 | ||
|
|
c74805b12b | ||
|
|
43870237fc | ||
|
|
ca24085b5b | ||
|
|
93191c2b8b | ||
|
|
ebc3ded2b2 | ||
|
|
d9d1c874ab | ||
|
|
08477fc361 | ||
|
|
11836b876f | ||
|
|
bf20965c46 | ||
|
|
22a48e52eb | ||
|
|
15b703b5f2 | ||
|
|
18f0eb8a36 | ||
|
|
32cdcc6fbe | ||
|
|
437c4b9bc5 | ||
|
|
0a42dbf5ba | ||
|
|
ea4f319898 | ||
|
|
7b6b944106 | ||
|
|
59c966771e | ||
|
|
a83c20b667 | ||
|
|
d5c4f85d73 | ||
|
|
36f683a299 | ||
|
|
652e9719ed | ||
|
|
011b658422 | ||
|
|
5fa1050e1b | ||
|
|
39617497ca | ||
|
|
44ad960da7 | ||
|
|
db223a1e92 | ||
|
|
ea4b8f51c2 | ||
|
|
407826396b | ||
|
|
124547c9c5 | ||
|
|
db7a9df880 | ||
|
|
29725214f7 | ||
|
|
9189de4db1 | ||
|
|
fec0032883 | ||
|
|
1ee737b1aa | ||
|
|
2a32e1d746 | ||
|
|
bdaf50ab0f | ||
|
|
37a129080a | ||
|
|
024b6ce292 | ||
|
|
b13a12e3d5 | ||
|
|
9d9738eed0 | ||
|
|
135fe1e5d4 | ||
|
|
2d033b6b87 | ||
|
|
9048ffbdab | ||
|
|
d43fdd3cb4 | ||
|
|
14d16eff46 | ||
|
|
1a603c2b48 | ||
|
|
2092161fe0 | ||
|
|
a8b92f50cc | ||
|
|
4556c9a5d1 | ||
|
|
e6fcae4f02 | ||
|
|
74ab5488e1 | ||
|
|
5cdec242eb | ||
|
|
e938a499f6 | ||
|
|
84b5915eea | ||
|
|
540ce1d2c3 | ||
|
|
b40f2af0f0 | ||
|
|
324d09a61e | ||
|
|
d5dfecefea | ||
|
|
ce37e17c87 | ||
|
|
3b1d5f15f4 | ||
|
|
714ec4695b | ||
|
|
3795d92d7a | ||
|
|
eed685507a | ||
|
|
26d3ec14a6 | ||
|
|
96d475407a | ||
|
|
27d8bc458f | ||
|
|
519f86c47e | ||
|
|
980f71c1bd | ||
|
|
7692665428 | ||
|
|
aaca0b5283 | ||
|
|
e5a495489d | ||
|
|
e07a6fb3ff | ||
|
|
b8c2660996 | ||
|
|
ec2ecdcacb | ||
|
|
3c3ab77f65 | ||
|
|
ffb2c89c36 | ||
|
|
bda62cc8a1 | ||
|
|
a052af4180 | ||
|
|
8835c37536 | ||
|
|
69f3c9f6ab | ||
|
|
af3e0bd6a5 | ||
|
|
5b14512323 | ||
|
|
6f176ad1c4 | ||
|
|
bc9d720a3c | ||
|
|
93c5013251 | ||
|
|
bc5c993093 | ||
|
|
759b3c5baf | ||
|
|
e1303d13a3 | ||
|
|
8824115697 | ||
|
|
a78a1e7d2e | ||
|
|
9e150b2c44 | ||
|
|
217d230b61 | ||
|
|
ba1b3c4fc7 | ||
|
|
5f871cd713 | ||
|
|
4a37422af5 | ||
|
|
a081fc87c9 | ||
|
|
0e8286e195 | ||
|
|
e9d53c4084 | ||
|
|
697a0ac9fc | ||
|
|
7f12e1c19a | ||
|
|
bf99cb50fd | ||
|
|
1333f0113f | ||
|
|
1b544bd22d | ||
|
|
24f514c949 | ||
|
|
8eed26e0a1 | ||
|
|
3c5b3f0a49 | ||
|
|
1d23b4bb67 | ||
|
|
48e533f660 | ||
|
|
86fbed60eb | ||
|
|
164341b543 | ||
|
|
94942fe488 | ||
|
|
ca64f6c8ac | ||
|
|
e8ef483098 | ||
|
|
85faf43fdd | ||
|
|
09620c269e | ||
|
|
0c05a4c375 | ||
|
|
298aa7960e | ||
|
|
b112513df0 | ||
|
|
f19b5a453a | ||
|
|
72e54653a2 | ||
|
|
5696d72a3f | ||
|
|
757d20166a | ||
|
|
1336996129 | ||
|
|
4f35240203 | ||
|
|
5565a6b3f8 | ||
|
|
9dbe135e66 | ||
|
|
fe5c031701 | ||
|
|
0511a90640 | ||
|
|
2c87dfbb35 | ||
|
|
9b4d07008d | ||
|
|
c40218a919 | ||
|
|
0c410b87ec | ||
|
|
114a07a440 | ||
|
|
babae3b2ad | ||
|
|
a7a9f86a71 | ||
|
|
c65fcd5133 | ||
|
|
b298b4203a | ||
|
|
250310fc9f | ||
|
|
89cf05d3a4 |
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Feature Request
|
- name: Feature Request
|
||||||
url: https://t.me/ksunext_group
|
url: https://t.me/ksunext/578
|
||||||
about: "We accept external Feature Requests, see this link for more details."
|
about: "We do not accept external Feature Requests anymore, check the link for more details."
|
||||||
|
|||||||
26
.github/workflows/build-debug-kernel.yml
vendored
26
.github/workflows/build-debug-kernel.yml
vendored
@@ -7,9 +7,9 @@ jobs:
|
|||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android12-5.10
|
version: android12-5.10
|
||||||
version_name: android12-5.10.226
|
version_name: android12-5.10.233
|
||||||
tag: android12-5.10-2024-11
|
tag: android12-5.10-2025-02
|
||||||
os_patch_level: 2024-11
|
os_patch_level: 2025-02
|
||||||
patch_path: "5.10"
|
patch_path: "5.10"
|
||||||
debug: true
|
debug: true
|
||||||
build-debug-kernel-a13:
|
build-debug-kernel-a13:
|
||||||
@@ -17,11 +17,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "5.10"
|
- version: "5.10"
|
||||||
sub_level: 228
|
sub_level: 234
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android13-${{ matrix.version }}
|
version: android13-${{ matrix.version }}
|
||||||
@@ -34,11 +34,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "6.1"
|
- version: "6.1"
|
||||||
sub_level: 118
|
sub_level: 129
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android14-${{ matrix.version }}
|
version: android14-${{ matrix.version }}
|
||||||
@@ -51,8 +51,8 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "6.6"
|
- version: "6.6"
|
||||||
sub_level: 58
|
sub_level: 82
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android15-${{ matrix.version }}
|
version: android15-${{ matrix.version }}
|
||||||
|
|||||||
14
.github/workflows/build-kernel-a13.yml
vendored
14
.github/workflows/build-kernel-a13.yml
vendored
@@ -39,6 +39,9 @@ jobs:
|
|||||||
- version: "5.10"
|
- version: "5.10"
|
||||||
sub_level: 228
|
sub_level: 228
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-01
|
||||||
|
- version: "5.10"
|
||||||
|
sub_level: 234
|
||||||
|
os_patch_level: 2025-03
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 148
|
sub_level: 148
|
||||||
os_patch_level: 2024-05
|
os_patch_level: 2024-05
|
||||||
@@ -57,6 +60,9 @@ jobs:
|
|||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 170
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-01
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 178
|
||||||
|
os_patch_level: 2025-03
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -143,11 +149,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "5.10"
|
- version: "5.10"
|
||||||
sub_level: 228
|
sub_level: 234
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android13-${{ matrix.version }}
|
version: android13-${{ matrix.version }}
|
||||||
|
|||||||
17
.github/workflows/build-kernel-a14.yml
vendored
17
.github/workflows/build-kernel-a14.yml
vendored
@@ -42,6 +42,9 @@ jobs:
|
|||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 170
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-01
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 178
|
||||||
|
os_patch_level: 2025-03
|
||||||
- version: "6.1"
|
- version: "6.1"
|
||||||
sub_level: 75
|
sub_level: 75
|
||||||
os_patch_level: 2024-05
|
os_patch_level: 2024-05
|
||||||
@@ -72,6 +75,12 @@ jobs:
|
|||||||
- version: "6.1"
|
- version: "6.1"
|
||||||
sub_level: 124
|
sub_level: 124
|
||||||
os_patch_level: 2025-02
|
os_patch_level: 2025-02
|
||||||
|
- version: "6.1"
|
||||||
|
sub_level: 128
|
||||||
|
os_patch_level: 2025-03
|
||||||
|
- version: "6.1"
|
||||||
|
sub_level: 129
|
||||||
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -158,11 +167,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "6.1"
|
- version: "6.1"
|
||||||
sub_level: 118
|
sub_level: 129
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android14-${{ matrix.version }}
|
version: android14-${{ matrix.version }}
|
||||||
|
|||||||
10
.github/workflows/build-kernel-a15.yml
vendored
10
.github/workflows/build-kernel-a15.yml
vendored
@@ -42,6 +42,12 @@ jobs:
|
|||||||
- version: "6.6"
|
- version: "6.6"
|
||||||
sub_level: 66
|
sub_level: 66
|
||||||
os_patch_level: 2025-02
|
os_patch_level: 2025-02
|
||||||
|
- version: "6.6"
|
||||||
|
sub_level: 77
|
||||||
|
os_patch_level: 2025-03
|
||||||
|
- version: "6.6"
|
||||||
|
sub_level: 82
|
||||||
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -128,8 +134,8 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "6.6"
|
- version: "6.6"
|
||||||
sub_level: 58
|
sub_level: 82
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android15-${{ matrix.version }}
|
version: android15-${{ matrix.version }}
|
||||||
|
|||||||
38
.github/workflows/build-kernel-wsa.yml
vendored
Normal file
38
.github/workflows/build-kernel-wsa.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: Build Kernel - WSA
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["next"]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/build-kernel-wsa.yml"
|
||||||
|
- ".github/workflows/wsa-kernel.yml"
|
||||||
|
- "kernel/**"
|
||||||
|
pull_request:
|
||||||
|
branches: ["next"]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/build-kernel-wsa.yml"
|
||||||
|
- ".github/workflows/wsa-kernel.yml"
|
||||||
|
- "kernel/**"
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: [x86_64, arm64]
|
||||||
|
version: ["5.15.94.2", "5.15.104.1", "5.15.104.2", "5.15.104.3", "5.15.104.4"]
|
||||||
|
uses: ./.github/workflows/wsa-kernel.yml
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.arch }}
|
||||||
|
version: ${{ matrix.version }}
|
||||||
|
|
||||||
|
check_build:
|
||||||
|
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
|
||||||
|
uses: ./.github/workflows/wsa-kernel.yml
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: [x86_64, arm64]
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.arch }}
|
||||||
|
version: "5.15.104.4"
|
||||||
20
.github/workflows/build-lkm.yml
vendored
20
.github/workflows/build-lkm.yml
vendored
@@ -18,20 +18,20 @@ jobs:
|
|||||||
sub_level: 233
|
sub_level: 233
|
||||||
os_patch_level: 2025-02
|
os_patch_level: 2025-02
|
||||||
- version: "android13-5.10"
|
- version: "android13-5.10"
|
||||||
sub_level: 228
|
sub_level: 234
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "android13-5.15"
|
- version: "android13-5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "android14-5.15"
|
- version: "android14-5.15"
|
||||||
sub_level: 170
|
sub_level: 178
|
||||||
os_patch_level: 2025-01
|
os_patch_level: 2025-03
|
||||||
- version: "android14-6.1"
|
- version: "android14-6.1"
|
||||||
sub_level: 124
|
sub_level: 129
|
||||||
os_patch_level: 2025-02
|
os_patch_level: 2025-04
|
||||||
- version: "android15-6.6"
|
- version: "android15-6.6"
|
||||||
sub_level: 66
|
sub_level: 82
|
||||||
os_patch_level: 2025-02
|
os_patch_level: 2025-04
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: ${{ matrix.version }}
|
version: ${{ matrix.version }}
|
||||||
|
|||||||
65
.github/workflows/build-manager-ci.yml
vendored
65
.github/workflows/build-manager-ci.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Build Manager
|
name: Build Manager CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -28,11 +28,9 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- target: aarch64-linux-android
|
- os: ubuntu-latest
|
||||||
os: ubuntu-latest
|
|
||||||
uses: ./.github/workflows/susfsd.yml
|
uses: ./.github/workflows/susfsd.yml
|
||||||
with:
|
with:
|
||||||
target: ${{ matrix.target }}
|
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
build-ksud:
|
build-ksud:
|
||||||
@@ -42,6 +40,10 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- target: aarch64-linux-android
|
- target: aarch64-linux-android
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
- target: armv7-linux-androideabi
|
||||||
|
os: ubuntu-latest
|
||||||
|
- target: x86_64-linux-android
|
||||||
|
os: ubuntu-latest
|
||||||
uses: ./.github/workflows/ksud.yml
|
uses: ./.github/workflows/ksud.yml
|
||||||
with:
|
with:
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
@@ -90,10 +92,10 @@ jobs:
|
|||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Download arm64 susfsd
|
- name: Download susfsd
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: susfsd-aarch64-linux-android
|
name: susfsd-linux-android
|
||||||
path: .
|
path: .
|
||||||
|
|
||||||
- name: Copy susfsd to app jniLibs
|
- name: Copy susfsd to app jniLibs
|
||||||
@@ -101,26 +103,77 @@ jobs:
|
|||||||
mkdir -p app/src/main/jniLibs/arm64-v8a
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/armeabi-v7a
|
||||||
|
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/x86_64
|
||||||
|
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
|
||||||
|
|
||||||
|
|
||||||
- name: Download arm64 ksud_overlayfs
|
- name: Download arm64 ksud_overlayfs
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud_overlayfs-aarch64-linux-android
|
name: ksud_overlayfs-aarch64-linux-android
|
||||||
path: ksud_overlayfs
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download arm ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-armv7-linux-androideabi
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-x86_64-linux-android
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
- name: Copy ksud_overlayfs to app jniLibs
|
- name: Copy ksud_overlayfs to app jniLibs
|
||||||
run: |
|
run: |
|
||||||
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/armeabi-v7a
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/x86_64
|
||||||
|
|
||||||
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
|
||||||
|
|
||||||
- name: Download arm64 ksud_magic
|
- name: Download arm64 ksud_magic
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud_magic-aarch64-linux-android
|
name: ksud_magic-aarch64-linux-android
|
||||||
path: ksud_magic
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download arm ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-armv7-linux-androideabi
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-x86_64-linux-android
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
- name: Copy ksud_magic to app jniLibs
|
- name: Copy ksud_magic to app jniLibs
|
||||||
run: |
|
run: |
|
||||||
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/armeabi-v7a
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/x86_64
|
||||||
|
|
||||||
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: |
|
run: |
|
||||||
{
|
{
|
||||||
|
|||||||
222
.github/workflows/build-manager-spoofed.yml
vendored
Normal file
222
.github/workflows/build-manager-spoofed.yml
vendored
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
name: Build Manager Spoofed
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "next" ]
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/build-manager-ci.yml'
|
||||||
|
- 'manager/**'
|
||||||
|
- 'kernel/**'
|
||||||
|
- 'userspace/ksud_overlayfs**'
|
||||||
|
- 'userspace/ksud_magic/**'
|
||||||
|
- 'userspace/susfsd/**'
|
||||||
|
pull_request:
|
||||||
|
branches: [ "next" ]
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/build-manager-ci.yml'
|
||||||
|
- 'manager/**'
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 12 * * *" # 6 PM UTC+6 | 12 PM UTC
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-lkm:
|
||||||
|
uses: ./.github/workflows/build-lkm.yml
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
build-susfsd:
|
||||||
|
needs: build-lkm
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
uses: ./.github/workflows/susfsd.yml
|
||||||
|
with:
|
||||||
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
|
build-ksud:
|
||||||
|
needs: build-susfsd
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: aarch64-linux-android
|
||||||
|
os: ubuntu-latest
|
||||||
|
- target: armv7-linux-androideabi
|
||||||
|
os: ubuntu-latest
|
||||||
|
- target: x86_64-linux-android
|
||||||
|
os: ubuntu-latest
|
||||||
|
uses: ./.github/workflows/ksud.yml
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
|
build-manager:
|
||||||
|
needs: build-ksud
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./manager
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Spoof Package ID
|
||||||
|
run: |
|
||||||
|
chmod +x spoof
|
||||||
|
./spoof
|
||||||
|
|
||||||
|
- name: Setup need_upload
|
||||||
|
id: need_upload
|
||||||
|
run: |
|
||||||
|
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
|
echo "UPLOAD=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "UPLOAD=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Write Key
|
||||||
|
run: |
|
||||||
|
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
|
||||||
|
{
|
||||||
|
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
|
||||||
|
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
|
||||||
|
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
|
||||||
|
echo KEYSTORE_FILE='key.jks'
|
||||||
|
} >> gradle.properties
|
||||||
|
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 21
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Download susfsd
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: susfsd-linux-android
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Copy susfsd to app jniLibs
|
||||||
|
run: |
|
||||||
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
|
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/armeabi-v7a
|
||||||
|
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/x86_64
|
||||||
|
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
|
||||||
|
|
||||||
|
|
||||||
|
- name: Download arm64 ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-aarch64-linux-android
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download arm ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-armv7-linux-androideabi
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-x86_64-linux-android
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Copy ksud_overlayfs to app jniLibs
|
||||||
|
run: |
|
||||||
|
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
|
||||||
|
|
||||||
|
- name: Download arm64 ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-aarch64-linux-android
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download arm ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-armv7-linux-androideabi
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-x86_64-linux-android
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Copy ksud_magic to app jniLibs
|
||||||
|
run: |
|
||||||
|
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: |
|
||||||
|
{
|
||||||
|
echo 'org.gradle.parallel=true'
|
||||||
|
echo 'org.gradle.vfs.watch=true'
|
||||||
|
echo 'org.gradle.jvmargs=-Xmx2048m'
|
||||||
|
echo 'android.native.buildOutput=verbose'
|
||||||
|
} >> gradle.properties
|
||||||
|
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
|
||||||
|
chmod +x gradlew
|
||||||
|
./gradlew clean assembleRelease
|
||||||
|
|
||||||
|
- name: Upload Build Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Manager
|
||||||
|
path: manager/app/build/outputs/apk/release/*.apk
|
||||||
|
|
||||||
|
- name: Upload Mappings
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Mappings
|
||||||
|
path: manager/app/build/outputs/mapping/release/
|
||||||
|
|
||||||
|
- name: Bot Session Cache
|
||||||
|
if: steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: scripts/ksunextbot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
|
- name: Upload to Telegram
|
||||||
|
if: steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
|
env:
|
||||||
|
API_ID: ${{ secrets.API_ID }}
|
||||||
|
API_HASH: ${{ secrets.API_HASH }}
|
||||||
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
|
COMMIT_URL: ${{ github.event.head_commit.url }}
|
||||||
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
|
TITLE: CI Manager (SPOOFED BUILD)
|
||||||
|
run: |
|
||||||
|
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
|
export VERSION=$(git rev-list --count HEAD)
|
||||||
|
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
|
||||||
|
pip3 install telethon
|
||||||
|
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
|
||||||
|
fi
|
||||||
72
.github/workflows/build-manager.yml
vendored
72
.github/workflows/build-manager.yml
vendored
@@ -28,13 +28,22 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- target: aarch64-linux-android
|
- os: ubuntu-latest
|
||||||
os: ubuntu-latest
|
|
||||||
uses: ./.github/workflows/susfsd.yml
|
uses: ./.github/workflows/susfsd.yml
|
||||||
with:
|
with:
|
||||||
target: ${{ matrix.target }}
|
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
|
build-kpmmgr:
|
||||||
|
needs: build-lkm
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: aarch64-linux-android
|
||||||
|
os: ubuntu-latest
|
||||||
|
uses: ./.github/workflows/kpmmgr.yml
|
||||||
|
with:
|
||||||
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
build-ksud:
|
build-ksud:
|
||||||
needs: build-susfsd
|
needs: build-susfsd
|
||||||
strategy:
|
strategy:
|
||||||
@@ -42,6 +51,10 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- target: aarch64-linux-android
|
- target: aarch64-linux-android
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
- target: armv7-linux-androideabi
|
||||||
|
os: ubuntu-latest
|
||||||
|
- target: x86_64-linux-android
|
||||||
|
os: ubuntu-latest
|
||||||
uses: ./.github/workflows/ksud.yml
|
uses: ./.github/workflows/ksud.yml
|
||||||
with:
|
with:
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
@@ -90,10 +103,10 @@ jobs:
|
|||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Download arm64 susfsd
|
- name: Download susfsd
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: susfsd-aarch64-linux-android
|
name: susfsd-linux-android
|
||||||
path: .
|
path: .
|
||||||
|
|
||||||
- name: Copy susfsd to app jniLibs
|
- name: Copy susfsd to app jniLibs
|
||||||
@@ -101,26 +114,75 @@ jobs:
|
|||||||
mkdir -p app/src/main/jniLibs/arm64-v8a
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/armeabi-v7a
|
||||||
|
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
|
||||||
|
|
||||||
|
mkdir -p app/src/main/jniLibs/x86_64
|
||||||
|
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
|
||||||
|
|
||||||
|
- name: Download arm64 kpmmgr
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kpmmgr-aarch64-linux-android
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Copy kpmmgr to app jniLibs
|
||||||
|
run: |
|
||||||
|
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||||
|
cp -f ../arm64-v8a/kpmmgr ../manager/app/src/main/jniLibs/arm64-v8a/libkpmmgr.so
|
||||||
|
|
||||||
- name: Download arm64 ksud_overlayfs
|
- name: Download arm64 ksud_overlayfs
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud_overlayfs-aarch64-linux-android
|
name: ksud_overlayfs-aarch64-linux-android
|
||||||
path: ksud_overlayfs
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download arm ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-armv7-linux-androideabi
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_overlayfs
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_overlayfs-x86_64-linux-android
|
||||||
|
path: ksud_overlayfs
|
||||||
|
|
||||||
- name: Copy ksud_overlayfs to app jniLibs
|
- name: Copy ksud_overlayfs to app jniLibs
|
||||||
run: |
|
run: |
|
||||||
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
|
||||||
|
|
||||||
|
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
|
||||||
|
|
||||||
- name: Download arm64 ksud_magic
|
- name: Download arm64 ksud_magic
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud_magic-aarch64-linux-android
|
name: ksud_magic-aarch64-linux-android
|
||||||
path: ksud_magic
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download arm ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-armv7-linux-androideabi
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
|
- name: Download x86_64 ksud_magic
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ksud_magic-x86_64-linux-android
|
||||||
|
path: ksud_magic
|
||||||
|
|
||||||
- name: Copy ksud_magic to app jniLibs
|
- name: Copy ksud_magic to app jniLibs
|
||||||
run: |
|
run: |
|
||||||
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
|
||||||
|
|
||||||
|
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: |
|
run: |
|
||||||
{
|
{
|
||||||
|
|||||||
10
.github/workflows/clippy.yml
vendored
10
.github/workflows/clippy.yml
vendored
@@ -3,14 +3,14 @@ name: Clippy check
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- next
|
- x86
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/clippy.yml'
|
- '.github/workflows/clippy.yml'
|
||||||
- 'userspace/ksud_magic/**'
|
- 'userspace/ksud_magic/**'
|
||||||
- 'userspace/ksud_overlayfs/**'
|
- 'userspace/ksud_overlayfs/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- next
|
- x86
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/clippy.yml'
|
- '.github/workflows/clippy.yml'
|
||||||
- 'userspace/ksud_magic/**'
|
- 'userspace/ksud_magic/**'
|
||||||
@@ -46,3 +46,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target aarch64-linux-android --release
|
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target aarch64-linux-android --release
|
||||||
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target aarch64-linux-android --release
|
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target aarch64-linux-android --release
|
||||||
|
|
||||||
|
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target armv7-linux-androideabi --release
|
||||||
|
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target armv7-linux-androideabi --release
|
||||||
|
|
||||||
|
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target x86_64-linux-android --release
|
||||||
|
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target x86_64-linux-android --release
|
||||||
3
.github/workflows/gki-kernel.yml
vendored
3
.github/workflows/gki-kernel.yml
vendored
@@ -198,6 +198,9 @@ jobs:
|
|||||||
- name: Make working directory clean to avoid dirty
|
- name: Make working directory clean to avoid dirty
|
||||||
working-directory: android-kernel
|
working-directory: android-kernel
|
||||||
run: |
|
run: |
|
||||||
|
if [ -f ./common/BUILD.bazel ]; then
|
||||||
|
sed -i '/^[[:space:]]*"protected_exports_list"[[:space:]]*:[[:space:]]*"android\/abi_gki_protected_exports_aarch64",$/d' ./common/BUILD.bazel
|
||||||
|
fi
|
||||||
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
|
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
|
||||||
git config --global user.email "bot@kernelsu.org"
|
git config --global user.email "bot@kernelsu.org"
|
||||||
git config --global user.name "KernelSU-NextBot"
|
git config --global user.name "KernelSU-NextBot"
|
||||||
|
|||||||
40
.github/workflows/kpmmgr.yml
vendored
Normal file
40
.github/workflows/kpmmgr.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Build kpmmgr
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "mian" ]
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/kpmmgr.yml'
|
||||||
|
- 'userspace/kpmmgr/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
target:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
os:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: self-hosted
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-susfs:
|
||||||
|
name: Build userspace kpmmgr
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Build kpmmgr
|
||||||
|
working-directory: ./userspace/kpmmgr
|
||||||
|
run: |
|
||||||
|
$ANDROID_NDK_HOME/ndk-build
|
||||||
|
|
||||||
|
- name: Upload a Build Artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kpmmgr-aarch64-linux-android
|
||||||
|
path: ./userspace/kpmmgr/libs
|
||||||
9
.github/workflows/ksud.yml
vendored
9
.github/workflows/ksud.yml
vendored
@@ -37,12 +37,17 @@ jobs:
|
|||||||
|
|
||||||
- name: Import susfsd Libraries
|
- name: Import susfsd Libraries
|
||||||
run: |
|
run: |
|
||||||
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/
|
cp susfsd-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/
|
||||||
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/
|
cp susfsd-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/
|
||||||
|
cp susfsd-linux-android/armeabi-v7a/susfsd ./userspace/ksud_overlayfs/bin/arm/
|
||||||
|
cp susfsd-linux-android/armeabi-v7a/susfsd ./userspace/ksud_magic/bin/arm/
|
||||||
|
cp susfsd-linux-android/x86_64/susfsd ./userspace/ksud_overlayfs/bin/x86_64/
|
||||||
|
cp susfsd-linux-android/x86_64/susfsd ./userspace/ksud_magic/bin/x86_64/
|
||||||
|
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
run: |
|
run: |
|
||||||
rustup update stable
|
rustup update stable
|
||||||
|
rustup target add x86_64-apple-darwin
|
||||||
rustup target add aarch64-apple-darwin
|
rustup target add aarch64-apple-darwin
|
||||||
|
|
||||||
- name: Cache ksud_overlayfs
|
- name: Cache ksud_overlayfs
|
||||||
|
|||||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -28,6 +28,7 @@ jobs:
|
|||||||
- build-a13-kernel
|
- build-a13-kernel
|
||||||
- build-a14-kernel
|
- build-a14-kernel
|
||||||
- build-a15-kernel
|
- build-a15-kernel
|
||||||
|
- build-wsa-kernel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
@@ -52,6 +53,7 @@ jobs:
|
|||||||
android*-lkm/*_kernelsu.ko
|
android*-lkm/*_kernelsu.ko
|
||||||
AnyKernel3-*.zip
|
AnyKernel3-*.zip
|
||||||
boot-images-*/Image-*/*.img.gz
|
boot-images-*/Image-*/*.img.gz
|
||||||
ksud_magic/ksud_magic-*
|
kernel-WSA*.zip
|
||||||
ksud_overlayfs/ksud_overlayfs-*
|
ksud_magic*.zip
|
||||||
susfsd/susfsd-*
|
ksud_overlayfs*.zip
|
||||||
|
susfsd*.zip
|
||||||
|
|||||||
9
.github/workflows/susfsd.yml
vendored
9
.github/workflows/susfsd.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Build susfsd
|
name: Build susfsd aarch64
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "next" ]
|
branches: [ "next" ]
|
||||||
@@ -8,9 +8,6 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
target:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
os:
|
os:
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -26,9 +23,9 @@ jobs:
|
|||||||
- name: Build susfsd
|
- name: Build susfsd
|
||||||
working-directory: ./userspace/susfsd
|
working-directory: ./userspace/susfsd
|
||||||
run: $ANDROID_NDK/ndk-build
|
run: $ANDROID_NDK/ndk-build
|
||||||
- name: Upload a Build Artifact
|
- name: Upload Build Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: susfsd-aarch64-linux-android
|
name: susfsd-linux-android
|
||||||
path: ./userspace/susfsd/libs
|
path: ./userspace/susfsd/libs
|
||||||
|
|
||||||
|
|||||||
106
.github/workflows/wsa-kernel.yml
vendored
Normal file
106
.github/workflows/wsa-kernel.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
name: Build Kernel - WSA
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
arch:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: >
|
||||||
|
Build arch: x86_64 / arm64
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: >
|
||||||
|
Build version
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build WSA-Kernel-${{ inputs.version }}-${{ inputs.arch }}
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
|
||||||
|
CCACHE_NOHASHDIR: "true"
|
||||||
|
CCACHE_HARDLINK: "true"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install Build Tools
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@v1
|
||||||
|
with:
|
||||||
|
packages: bc bison build-essential flex libelf-dev binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu gzip ccache
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
- name: Cache LLVM
|
||||||
|
id: cache-llvm
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ./llvm
|
||||||
|
key: llvm-12.0.1
|
||||||
|
|
||||||
|
- name: Setup LLVM
|
||||||
|
uses: KyleMayes/install-llvm-action@v1
|
||||||
|
with:
|
||||||
|
version: "12.0.1"
|
||||||
|
force-version: true
|
||||||
|
ubuntu-version: "16.04"
|
||||||
|
cached: ${{ steps.cache-llvm.outputs.cache-hit }}
|
||||||
|
|
||||||
|
- name: Checkout KernelSU
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: KernelSU
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup kernel source
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: microsoft/WSA-Linux-Kernel
|
||||||
|
ref: android-lts/latte-2/${{ inputs.version }}
|
||||||
|
path: WSA-Linux-Kernel
|
||||||
|
|
||||||
|
- name: Setup Ccache
|
||||||
|
uses: hendrikmuhs/ccache-action@v1
|
||||||
|
with:
|
||||||
|
key: WSA-Kernel-${{ inputs.version }}-${{ inputs.arch }}
|
||||||
|
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||||
|
max-size: 2G
|
||||||
|
|
||||||
|
- name: Setup KernelSU
|
||||||
|
working-directory: WSA-Linux-Kernel
|
||||||
|
run: |
|
||||||
|
echo "[+] KernelSU setup"
|
||||||
|
KERNEL_ROOT=$GITHUB_WORKSPACE/WSA-Linux-Kernel
|
||||||
|
echo "[+] KERNEL_ROOT: $KERNEL_ROOT"
|
||||||
|
echo "[+] Copy KernelSU driver to $KERNEL_ROOT/drivers"
|
||||||
|
ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $KERNEL_ROOT/drivers/kernelsu
|
||||||
|
echo "[+] Add KernelSU driver to Makefile"
|
||||||
|
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
|
||||||
|
DRIVER_KCONFIG=$KERNEL_ROOT/drivers/Kconfig
|
||||||
|
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
|
||||||
|
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
|
||||||
|
echo "[+] Apply KernelSU patches"
|
||||||
|
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.15/*.patch || echo "[-] No patch found"
|
||||||
|
echo "[+] KernelSU setup done."
|
||||||
|
cd $GITHUB_WORKSPACE/KernelSU
|
||||||
|
VERSION=$(($(git rev-list --count HEAD) + 10200))
|
||||||
|
echo "VERSION: $VERSION"
|
||||||
|
echo "kernelsu_version=$VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build Kernel
|
||||||
|
working-directory: WSA-Linux-Kernel
|
||||||
|
run: |
|
||||||
|
if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
|
||||||
|
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
|
||||||
|
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
|
||||||
|
fi
|
||||||
|
declare -A ARCH_MAP=(["x86_64"]="x64" ["arm64"]="arm64")
|
||||||
|
cp configs/wsa/config-wsa-${ARCH_MAP[${{ inputs.arch }}]} .config
|
||||||
|
make olddefconfig
|
||||||
|
declare -A FILE_NAME=(["x86_64"]="bzImage" ["arm64"]="Image")
|
||||||
|
make -j`nproc` LLVM=1 ARCH=${{ inputs.arch }} $(if [ "${{ inputs.arch }}" == "arm64" ]; then echo CROSS_COMPILE=aarch64-linux-gnu; fi) ${FILE_NAME[${{ inputs.arch }}]} CCACHE="/usr/bin/ccache"
|
||||||
|
declare -A ARCH_MAP_FILE=(["x86_64"]="x86" ["arm64"]="arm64")
|
||||||
|
echo "file_path=WSA-Linux-Kernel/arch/${ARCH_MAP_FILE[${{ inputs.arch }}]}/boot/${FILE_NAME[${{ inputs.arch }}]}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Upload kernel-${{ inputs.arch }}-${{ inputs.version }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: kernel-WSA-${{ inputs.arch }}-${{ inputs.version }}
|
||||||
|
path: "${{ env.file_path }}"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
**English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
**English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md) | [Українська](README_UA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ KernelSU Next officially supports most Android kernels starting from 4.4 up to 6
|
|||||||
- GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver.
|
- GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver.
|
||||||
- EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports).
|
- EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports).
|
||||||
|
|
||||||
Currently, only the `arm64-v8a` architecture is supported.
|
Currently, only the `arm64-v8a`, `armeabi-v7a` & `x86_64` architecture is supported.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | **Български**
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | **Български** | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ KernelSU Next официално поддържа повечето Android яд
|
|||||||
- Ядра GKI 1.0 (4.19 - 5.4) изискват прекомпилиране с драйвера на KernelSU
|
- Ядра GKI 1.0 (4.19 - 5.4) изискват прекомпилиране с драйвера на KernelSU
|
||||||
- Остарели ядра (<4.14) също изискват прекомпилиране (3.18+ е експериментална поддръжка)
|
- Остарели ядра (<4.14) също изискват прекомпилиране (3.18+ е експериментална поддръжка)
|
||||||
|
|
||||||
В момента се поддържа само архитектурата `arm64-v8a`.
|
В момента се поддържа само архитектурата `arm64-v8a`, `armeabi-v7a` & `x86_64`.
|
||||||
|
|
||||||
## Инсталация
|
## Инсталация
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | **简体中文** | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | **简体中文** | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next 支持从 4.4 到 6.6 的大多数安卓内核
|
|||||||
- GKI 1.0(4.19 - 5.4)内核需要使用 KernelSU 内核驱动重新编译
|
- GKI 1.0(4.19 - 5.4)内核需要使用 KernelSU 内核驱动重新编译
|
||||||
- EOL (<4.14) 内核也需要使用 KernelSU 内核驱动重新编译 (3.18+ 的版本处于试验阶段,可能需要移植一些功能)
|
- EOL (<4.14) 内核也需要使用 KernelSU 内核驱动重新编译 (3.18+ 的版本处于试验阶段,可能需要移植一些功能)
|
||||||
|
|
||||||
目前只支持 `arm64-v8a` 架构
|
目前只支持 `arm64-v8a`, `armeabi-v7a` & `x86_64` 架构
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
|
|
||||||
- [安装说明](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [安装说明](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## 安全性
|
## 安全性
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | **Français** | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | **Français** | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next prend officiellement en charge la plupart des noyaux Android de la
|
|||||||
- Les noyaux GKI 1.0 (4.19 - 5.4) doivent être reconstruits avec le pilote KernelSU.
|
- Les noyaux GKI 1.0 (4.19 - 5.4) doivent être reconstruits avec le pilote KernelSU.
|
||||||
- Les noyaux EOL (<4.14) doivent également être reconstruits avec le pilote KernelSU (3.18+ est expérimental et peut nécessiter des rétroportages fonctionnels).
|
- Les noyaux EOL (<4.14) doivent également être reconstruits avec le pilote KernelSU (3.18+ est expérimental et peut nécessiter des rétroportages fonctionnels).
|
||||||
|
|
||||||
Actuellement, seul `arm64-v8a` est pris en charge.
|
Actuellement, seul `arm64-v8a`, `armeabi-v7a` & `x86_64` est pris en charge.
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
|
|
||||||
- [Instructions d'installation](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Instructions d'installation](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Sécurité
|
## Sécurité
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | **Bahasa Indonesia** | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | **Bahasa Indonesia** | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next secara resmi mendukung sebagian besar kernel Android mulai dari 4.
|
|||||||
- Kernel GKI 1.0 (4.19 - 5.4) perlu dibangun ulang dengan driver KernelSU.
|
- Kernel GKI 1.0 (4.19 - 5.4) perlu dibangun ulang dengan driver KernelSU.
|
||||||
- Kernel EOL (<4.14) juga perlu dibangun ulang dengan driver KernelSU (3.18+ bersifat eksperimental dan mungkin memerlukan beberapa backport fungsi).
|
- Kernel EOL (<4.14) juga perlu dibangun ulang dengan driver KernelSU (3.18+ bersifat eksperimental dan mungkin memerlukan beberapa backport fungsi).
|
||||||
|
|
||||||
Saat ini, hanya `arm64-v8a` yang didukung.
|
Saat ini, hanya `arm64-v8a`, `armeabi-v7a` & `x86_64` yang didukung.
|
||||||
|
|
||||||
## Penggunaan
|
## Penggunaan
|
||||||
|
|
||||||
- [Petunjuk instalasi](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Petunjuk instalasi](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Keamanan
|
## Keamanan
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | **Italiano** | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | **Italiano** | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next supporta ufficialmente la maggior parte dei kernel Android dalla v
|
|||||||
- I kernel GKI 1.0 (4.19 - 5.4) devono essere ricostruiti con il driver KernelSU.
|
- I kernel GKI 1.0 (4.19 - 5.4) devono essere ricostruiti con il driver KernelSU.
|
||||||
- Anche i kernel EOL (<4.14) devono essere ricostruiti con il driver KernelSU (la versione 3.18+ è sperimentale e potrebbe richiedere alcuni backport di funzioni).
|
- Anche i kernel EOL (<4.14) devono essere ricostruiti con il driver KernelSU (la versione 3.18+ è sperimentale e potrebbe richiedere alcuni backport di funzioni).
|
||||||
|
|
||||||
Attualmente è supportata solo l'architettura `arm64-v8a`.
|
Attualmente è supportata solo l'architettura `arm64-v8a`, `armeabi-v7a` & `x86_64`.
|
||||||
|
|
||||||
## Utilizzo
|
## Utilizzo
|
||||||
|
|
||||||
- [Istruzioni per l'installazione](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Istruzioni per l'installazione](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
|
|||||||
63
docs/README_JA.md
Normal file
63
docs/README_JA.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | **日本語**
|
||||||
|
|
||||||
|
# KernelSU Next
|
||||||
|
|
||||||
|
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
|
Android デバイス用のカーネルベースな root ソリューション。
|
||||||
|
|
||||||
|
[](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
|
||||||
|
[](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
|
## 機能
|
||||||
|
|
||||||
|
1. カーネルベースの `su` および root アクセスの管理。
|
||||||
|
2. 動的マウントシステム [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) をベースとしたモジュールシステム。
|
||||||
|
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージに閉じ込めます。
|
||||||
|
|
||||||
|
## 互換性の状態
|
||||||
|
|
||||||
|
KernelSU Next は 4.4 から 6.6 までのほとんどの Android カーネルを公式でサポートしています。
|
||||||
|
- GKI 2.0 (5.10 以降) のカーネルはビルド済みイメージで LKM/KMI を実行できます。
|
||||||
|
- GKI 1.0 (4.19 - 5.4) のカーネルは、KernelSU ドライバを使用してビルドする必要があります。
|
||||||
|
- EOL (4.14 未満) のカーネルも KernelSU ドライバを使用して再ビルドする必要があります (3.18 以降は実験中の段階であり、一部の関数のバックポートが必要になる場合があります)。
|
||||||
|
|
||||||
|
現在 `arm64-v8a`, `armeabi-v7a` & `x86_64` アーキテクチャのみをサポートしています。
|
||||||
|
|
||||||
|
## 使い方
|
||||||
|
|
||||||
|
- [インストール手順](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
|
## セキュリティ
|
||||||
|
|
||||||
|
KernelSU のセキュリティ脆弱性の報告については [SECURITY.md](/SECURITY.md) を参照してください。
|
||||||
|
|
||||||
|
## ライセンス
|
||||||
|
|
||||||
|
- `kernel` ディレクトリ内のファイルは [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.ja.html) のみライセンス下にあります。
|
||||||
|
- `kernel` ディレクトリを除くその他すべての部分は [GPL-3.0 またはそれ以降](https://www.gnu.org/licenses/gpl-3.0.html) のライセンス下にあります。
|
||||||
|
|
||||||
|
## 寄付
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
|
||||||
|
|
||||||
|
- TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
|
||||||
|
|
||||||
|
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
|
||||||
|
|
||||||
|
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
|
||||||
|
|
||||||
|
## クレジット
|
||||||
|
|
||||||
|
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU のアイデアを考案。
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): パワフルな root ツール。
|
||||||
|
- [genuine](https://github.com/brevent/genuine/): APK v2 署名認証。
|
||||||
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): いくつかの rootkit スキル。
|
||||||
|
- [KernelSU](https://github.com/tiann/KernelSU): tiann に感謝を申し上げます。これが存在しなければ KernelSU Next は存在しませんでした。
|
||||||
|
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff へ KernelSU を救ってくれてありがとう!
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | **한국어** | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | **한국어** | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next는 공식적으로 대부분의 4.4부터 6.6의 안드로이드
|
|||||||
- GKI 1.0 (4.19 - 5.4) 커널은 KernelSU 드라이버로 다시 빌드해야 합니다.
|
- GKI 1.0 (4.19 - 5.4) 커널은 KernelSU 드라이버로 다시 빌드해야 합니다.
|
||||||
- EOL (<4.14) 커널도 역시 KernelSU 드라이버로 다시 빌드해야 합니다.(3.18+는 실험적이며 일부 함수의 이식이 필요할 수 있습니다.).
|
- EOL (<4.14) 커널도 역시 KernelSU 드라이버로 다시 빌드해야 합니다.(3.18+는 실험적이며 일부 함수의 이식이 필요할 수 있습니다.).
|
||||||
|
|
||||||
현재는, `arm64-v8a`만 지원됩니다.
|
현재는, `arm64-v8a`, `armeabi-v7a` & `x86_64` 만 지원됩니다.
|
||||||
|
|
||||||
## 사용 방법
|
## 사용 방법
|
||||||
|
|
||||||
- [설치 방법](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [설치 방법](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## 보안
|
## 보안
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | **Polski** | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | **Polski** | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next oficjalnie obsługuje większość jąder Androida od wersji 4.4 d
|
|||||||
- Jądra GKI 1.0 (4.19 - 5.4) muszą zostać zrekompilowane z dodatkiem sterownika KernelSU.
|
- Jądra GKI 1.0 (4.19 - 5.4) muszą zostać zrekompilowane z dodatkiem sterownika KernelSU.
|
||||||
- Jądra EOL (<4.14) również muszą zostać zrekompilowane z dodatkiem sterownika KernelSU (obsługa 3.18+ jest eksperymentalna i może wymagać backportu pewnych funkcji).
|
- Jądra EOL (<4.14) również muszą zostać zrekompilowane z dodatkiem sterownika KernelSU (obsługa 3.18+ jest eksperymentalna i może wymagać backportu pewnych funkcji).
|
||||||
|
|
||||||
Obecnie obsługiwana jest tylko architektura `arm64-v8a`.
|
Obecnie obsługiwana jest tylko architektura `arm64-v8a`, `armeabi-v7a` & `x86_64`
|
||||||
|
|
||||||
## Użycie
|
## Użycie
|
||||||
|
|
||||||
- [Instrukcja instalacji](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Instrukcja instalacji](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Bezpieczeństwo
|
## Bezpieczeństwo
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | **Português (Brasil)** | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | **Português (Brasil)** | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next suporta oficialmente a maioria dos kernels Android a partir de 4.4
|
|||||||
- Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU.
|
- Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU.
|
||||||
- Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções).
|
- Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções).
|
||||||
|
|
||||||
Atualmente, apenas a arquitetura `arm64-v8a` é compatível.
|
Atualmente, apenas a arquitetura `arm64-v8a`, `armeabi-v7a` & `x86_64` é compatível.
|
||||||
|
|
||||||
## Uso
|
## Uso
|
||||||
|
|
||||||
- [Instruções de instalação](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Instruções de instalação](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Segurança
|
## Segurança
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | **Русский** | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | **Русский** | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next работает с большинством ядер Android (4.4
|
|||||||
- GKI 1.0 (4.19 - 5.4) требуют пересборки с драйвером KernelSU.
|
- GKI 1.0 (4.19 - 5.4) требуют пересборки с драйвером KernelSU.
|
||||||
- EOL (<4.14) также требуют пересборки с драйвером KernelSU (версии 3.18+ экспериментальные и могут потребовать некоторые функции бэкпортов).
|
- EOL (<4.14) также требуют пересборки с драйвером KernelSU (версии 3.18+ экспериментальные и могут потребовать некоторые функции бэкпортов).
|
||||||
|
|
||||||
Сейчас поддерживается только `arm64-v8a`.
|
Сейчас поддерживается только `arm64-v8a`, `armeabi-v7a` & `x86_64`.
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
- [Инструкция по установке](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Инструкция по установке](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Безопасность
|
## Безопасность
|
||||||
|
|
||||||
@@ -59,5 +59,5 @@ KernelSU Next работает с большинством ядер Android (4.4
|
|||||||
- [Magisk](https://github.com/topjohnwu/Magisk): Топовый инструмент для root.
|
- [Magisk](https://github.com/topjohnwu/Magisk): Топовый инструмент для root.
|
||||||
- [genuine](https://github.com/brevent/genuine/): Валидация подписи APK v2.
|
- [genuine](https://github.com/brevent/genuine/): Валидация подписи APK v2.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): Некоторые навыки rootkit.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): Некоторые навыки rootkit.
|
||||||
- [KernelSU](https://github.com/tiann/KernelSU): Спасибо tiann, без него KernelSU Next не релизнулся бы.
|
- [KernelSU](https://github.com/tiann/KernelSU): Спасибо tiann, без него KernelSU Next даже не существовал бы.
|
||||||
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff за сохранение KernelSU!
|
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff за сохранение KernelSU!
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | **ภาษาไทย** | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | **ภาษาไทย** | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next รองรับแบบเป็นทางการตั้
|
|||||||
- GKI 1.0 (4.19 - 5.4) เคอร์เนลจะต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU
|
- GKI 1.0 (4.19 - 5.4) เคอร์เนลจะต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU
|
||||||
- EOL (<4.14) เคอร์เนลก็ต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU เช่นกัน (3.18+ ยังเป็นเวอร์ชั่นทดลอง และยังต้องเขียนฟังก์ชั่นหลังบ้านเพิ่มเติม)
|
- EOL (<4.14) เคอร์เนลก็ต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU เช่นกัน (3.18+ ยังเป็นเวอร์ชั่นทดลอง และยังต้องเขียนฟังก์ชั่นหลังบ้านเพิ่มเติม)
|
||||||
|
|
||||||
ในขณะนี้, มีแค่สถาปัตยกรรม `arm64-v8a` ที่รองรับเท่านั้น
|
ในขณะนี้, มีแค่สถาปัตยกรรม `arm64-v8a`, `armeabi-v7a` & `x86_64` ที่รองรับเท่านั้น
|
||||||
|
|
||||||
## การใช้งาน
|
## การใช้งาน
|
||||||
|
|
||||||
- [คำแนะนำในการติดตั้ง](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [คำแนะนำในการติดตั้ง](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## ความปลอดภัย
|
## ความปลอดภัย
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +1,63 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **Türkçe** | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **Türkçe** | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
|
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Android cihazlar için Kernel tabanlı bir root çözümü.
|
Android cihazlar için çekirdek tabanlı root çözümü.
|
||||||
|
|
||||||
[](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
|
[](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
|
||||||
[](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
|
[](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
|
||||||
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
[](/LICENSE)
|
[](/LICENSE)
|
||||||
|
|
||||||
## Özellikler
|
## Özellikler
|
||||||
|
|
||||||
1. Çekirdek tabanlı `su` ve kök erişim yönetimi.
|
1. Çekirdek tabanlı `su` ve root erişimi yönetimi.
|
||||||
2. Dinamik montaj sistemine dayalı modül sistemi [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
2. Dinamik bağlama sistemi [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) tabanlı modül sistemi.
|
||||||
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Kök gücünü bir kafese kilitleyin.
|
3. [Uygulama Profili](https://kernelsu.org/guide/app-profile.html): Root yetkisini bir kafese kilitleyin.
|
||||||
|
|
||||||
## Uyumluluk Durumu
|
## Uyumluluk Durumu
|
||||||
|
|
||||||
KernelSU Next, 4.4'dan başlayarak 6.6'ya kadar çoğu Android çekirdeğini resmi olarak desteklemektedir.
|
KernelSU Next, resmi olarak Android çekirdeklerinin çoğunu 4.4 sürümünden 6.6 sürümüne kadar destekler.
|
||||||
- GKI 2.0 (5.10+) çekirdekleri önceden oluşturulmuş görüntüleri ve LKM/KMI'yi çalıştırabilir.
|
- GKI 2.0 (5.10+) çekirdekleri, hazır imajları ve LKM/KMI desteğini çalıştırabilir.
|
||||||
- GKI 1.0 (4.19 - 5.4) çekirdeklerinin KernelSU sürücüsü ile yeniden oluşturulması gerekir.
|
- GKI 1.0 (4.19 - 5.4) çekirdeklerinin KernelSU sürücüsü ile yeniden derlenmesi gerekir.
|
||||||
- EOL (<4.14) çekirdeklerinin de KernelSU sürücüsü ile yeniden oluşturulması gerekir. (3.18+ deneyseldir ve bazı fonksiyon geri yüklemelerine ihtiyaç duyulabilir.)
|
- EOL (<4.14) çekirdekler de KernelSU sürücüsüyle yeniden derlenmelidir (3.18+ deneysel olup bazı fonksiyonların geri aktarımı gerekebilir).
|
||||||
|
|
||||||
Şu anda sadece `arm64-v8a` desteklenmektedir.
|
Şu anda yalnızca `arm64-v8a`, `armeabi-v7a` & `x86_64` mimarisi desteklenmektedir.
|
||||||
|
|
||||||
## Kullanım
|
## Kullanım
|
||||||
|
|
||||||
- [Kurulum Talimatı](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Kurulum Talimatları](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Güvenlik
|
## Güvenlik
|
||||||
|
|
||||||
KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için [SECURITY.md](/SECURITY.md) bölümüne bakın.
|
KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için bkz: [SECURITY.md](/SECURITY.md)
|
||||||
|
|
||||||
## Lisans
|
## Lisans
|
||||||
|
|
||||||
- `kernel` dizini altındaki dosyalar sadece [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansına tabiidir.
|
- `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisanslıdır.
|
||||||
- `kernel` dizini dışındaki diğer tüm kısımlar [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html) ya da daha sonraki bir sürüm lisansa tabiidir.
|
- `kernel` dizini dışındaki tüm diğer bölümler [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır.
|
||||||
|
|
||||||
## Krediler
|
## Bağışlar
|
||||||
|
|
||||||
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri.
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): Güçlü kök aracı.
|
|
||||||
|
- TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
|
||||||
|
|
||||||
|
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
|
||||||
|
|
||||||
|
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
|
||||||
|
|
||||||
|
## Katkıda Bulunanlar
|
||||||
|
|
||||||
|
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikrinin temeli.
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): Güçlü root aracı.
|
||||||
- [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama.
|
- [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit becerileri.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit teknikleri.
|
||||||
- [KernelSU](https://github.com/tiann/KernelSU): tiann'a teşekkürler, yoksa KernelSU Next var olamazdı bile.
|
- [KernelSU](https://github.com/tiann/KernelSU): tiann'a teşekkürler, KernelSU Next onun sayesinde var.
|
||||||
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff KernelSU'yu kurtardığınız için!
|
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 KernelSU'yu kurtardığı için 5ec1cff'e teşekkürler!
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | **繁體中文** | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | **繁體中文** | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next 正式支持大多數從 4.4 到 6.6 的 Android 內核
|
|||||||
- GKI 1.0 (4.19 - 5.4) 內核需要重新編譯 KernelSU 驅動程序
|
- GKI 1.0 (4.19 - 5.4) 內核需要重新編譯 KernelSU 驅動程序
|
||||||
- EOL (<4.14) 內核也需要重新編譯 KernelSU 驅動程序(3.18+ 是實驗性的,可能需要移植一些功能)
|
- EOL (<4.14) 內核也需要重新編譯 KernelSU 驅動程序(3.18+ 是實驗性的,可能需要移植一些功能)
|
||||||
|
|
||||||
目前僅支持 `arm64-v8a`
|
目前僅支持 `arm64-v8a`, `armeabi-v7a` & `x86_64`
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
|
|
||||||
- [安裝說明](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [安裝說明](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## 安全性
|
## 安全性
|
||||||
|
|
||||||
|
|||||||
63
docs/README_UA.md
Normal file
63
docs/README_UA.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md) | **Українська**
|
||||||
|
|
||||||
|
# KernelSU Next
|
||||||
|
|
||||||
|
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
|
Рут-рішення на основі ядра для пристроїв Android.
|
||||||
|
|
||||||
|
[](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
|
||||||
|
[](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
|
## Можливості
|
||||||
|
|
||||||
|
1. `su` на основі ядра та можливість контролювати дозволи руту.
|
||||||
|
2. Module system based on dynamic mount system [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
|
3. [Профілі додатків](https://kernelsu.org/guide/app-profile.html): Обмеж права руту для додатків.
|
||||||
|
|
||||||
|
## Compatibility state
|
||||||
|
|
||||||
|
KernelSU Next офіційно підтримує більшість Android ядер починаючи з 4.4 і до 6.6.
|
||||||
|
- Користувачі GKI 2.0 (5.10+) ядра можуть використовувати готові образи та LKM/KMI.
|
||||||
|
- Користувачі GKI 1.0 (4.19 - 5.4) ядра мають бути перезібрані з драйвером KernelSU.
|
||||||
|
- Користувачі EOL (<4.14) ядра також мають бути перезібрані з драйвером KernelSU (Підтримка 3.18+ експерементальна і потребує бекпортів деяких функцій в ядрі).
|
||||||
|
|
||||||
|
На даний момент підтримується лише архітектура `arm64-v8a`, `armeabi-v7a` & `x86_64`.
|
||||||
|
|
||||||
|
## Спосіб використання
|
||||||
|
|
||||||
|
- [Інструкція для встановлення/інтеграції](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
|
## Безпека
|
||||||
|
|
||||||
|
Для інформації зв'язаною з безпекою дивіться [SECURITY.md](/SECURITY.md).
|
||||||
|
|
||||||
|
## Ліцензія
|
||||||
|
|
||||||
|
- Всі файли в директорії `kernel` мають ліцензію [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
|
- Всі інші файли виключаючи директорію `kernel` мають ліцензію [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
|
## Підтримка розробника
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
|
||||||
|
|
||||||
|
- TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
|
||||||
|
|
||||||
|
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
|
||||||
|
|
||||||
|
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
|
||||||
|
|
||||||
|
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
|
||||||
|
|
||||||
|
## Подяки
|
||||||
|
|
||||||
|
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): Ідея KernelSU.
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): Потужний засіб руту.
|
||||||
|
- [genuine](https://github.com/brevent/genuine/): Перевірка підпису APK v2.
|
||||||
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): Деякі руткіт скіли.
|
||||||
|
- [KernelSU](https://github.com/tiann/KernelSU): Дякую tiann, інакше KernelSU Next ніколи б не існував.
|
||||||
|
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): Дякую 💜 5ec1cff за збереження KernelSU!
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | **Tiếng Việt** | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md)
|
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | **Tiếng Việt** | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
|
||||||
|
|
||||||
# KernelSU Next
|
# KernelSU Next
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ KernelSU Next hỗ trợ chính thức các kernel Android từ phiên bản 4.4
|
|||||||
- GKI 1.0 (4.19 - 5.4) kernels cần dược build lại với các nhân KernelSU Next
|
- GKI 1.0 (4.19 - 5.4) kernels cần dược build lại với các nhân KernelSU Next
|
||||||
- EOL (<4.14) kernels cần dược build lại với các nhân KernelSU Next (các kernels 3.18+ đang dược thử nghiệm và có thể cần backports 1 vài thứ ).
|
- EOL (<4.14) kernels cần dược build lại với các nhân KernelSU Next (các kernels 3.18+ đang dược thử nghiệm và có thể cần backports 1 vài thứ ).
|
||||||
|
|
||||||
Hiện tại kernelSU Next chỉ hỗ trợ những cpu có `arm64-v8a`
|
Hiện tại kernelSU Next chỉ hỗ trợ những cpu có `arm64-v8a`, `armeabi-v7a` & `x86_64`
|
||||||
|
|
||||||
## Sử dụng
|
## Sử dụng
|
||||||
|
|
||||||
- [Hướng dẫn vá KernelSU Next vào Kernel của bạn (yêu cầu kernel source)](https://KernelSU-Next.github.io/KernelSU-Next/)
|
- [Hướng dẫn vá KernelSU Next vào Kernel của bạn (yêu cầu kernel source)](https://ksunext.org/pages/installation.html)
|
||||||
|
|
||||||
## Bảo mật
|
## Bảo mật
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ config KSU
|
|||||||
To compile as a module, choose M here: the
|
To compile as a module, choose M here: the
|
||||||
module will be called kernelsu.
|
module will be called kernelsu.
|
||||||
|
|
||||||
config KSU_WITH_KPROBES
|
config KSU_KPROBES_HOOK
|
||||||
bool "Use kprobes for kernelsu"
|
bool "Use kprobes for kernelsu"
|
||||||
depends on KSU
|
depends on KSU
|
||||||
depends on KPROBES
|
depends on KPROBES
|
||||||
@@ -32,4 +32,21 @@ config KSU_ALLOWLIST_WORKAROUND
|
|||||||
Enable session keyring init workaround for problematic devices.
|
Enable session keyring init workaround for problematic devices.
|
||||||
Useful for situations where the SU allowlist is not kept after a reboot.
|
Useful for situations where the SU allowlist is not kept after a reboot.
|
||||||
|
|
||||||
|
config KSU_LSM_SECURITY_HOOKS
|
||||||
|
bool "use lsm security hooks"
|
||||||
|
depends on KSU
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Disabling this is mostly only useful for kernel 4.1 and older.
|
||||||
|
Make sure to implement manual hooks on security/security.c.
|
||||||
|
|
||||||
|
config KPM
|
||||||
|
bool "Enable SukiSU KPM"
|
||||||
|
depends on KSU && 64BIT
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enabling this option will activate the KPM feature of SukiSU.
|
||||||
|
This option is suitable for scenarios where you need to force KPM to be enabled.
|
||||||
|
but it may affect system stability.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-
|
|||||||
|
|
||||||
obj-$(CONFIG_KSU) += kernelsu.o
|
obj-$(CONFIG_KSU) += kernelsu.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_KPM) += kpm/
|
||||||
|
|
||||||
# .git is a text file while the module is imported by 'git submodule add'.
|
# .git is a text file while the module is imported by 'git submodule add'.
|
||||||
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
|
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
|
||||||
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
|
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
|
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
|
||||||
#include <linux/lsm_hooks.h>
|
#include <linux/lsm_hooks.h>
|
||||||
|
#endif
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
#include <linux/path.h>
|
#include <linux/path.h>
|
||||||
@@ -45,6 +47,8 @@
|
|||||||
#include "throne_tracker.h"
|
#include "throne_tracker.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
|
||||||
|
#include "kpm/kpm.h"
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_COMPAT_GET_CRED_RCU)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_COMPAT_GET_CRED_RCU)
|
||||||
#define KSU_GET_CRED_RCU
|
#define KSU_GET_CRED_RCU
|
||||||
#endif
|
#endif
|
||||||
@@ -337,6 +341,18 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg2 == CMD_HOOK_MODE) {
|
||||||
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
|
const char *mode = "Kprobes";
|
||||||
|
#else
|
||||||
|
const char *mode = "Manual";
|
||||||
|
#endif
|
||||||
|
if (copy_to_user((void __user *)arg3, mode, strlen(mode) + 1)) {
|
||||||
|
pr_info("hook: copy_to_user() failed\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (arg2 == CMD_REPORT_EVENT) {
|
if (arg2 == CMD_REPORT_EVENT) {
|
||||||
if (!from_root) {
|
if (!from_root) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -436,6 +452,26 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KPM
|
||||||
|
// KPM Control
|
||||||
|
if(sukisu_is_kpm_control_code(arg2)) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
pr_info("KPM: calling before arg2=%d\n", (int) arg2);
|
||||||
|
|
||||||
|
res = sukisu_handle_kpm(arg2, arg3, arg4, arg5);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// KPM info
|
||||||
|
if (arg2 == CMD_ENABLE_KPM) {
|
||||||
|
bool KPM_Enabled = IS_ENABLED(CONFIG_KPM);
|
||||||
|
if (copy_to_user((void __user *)arg3, &KPM_Enabled, sizeof(KPM_Enabled)))
|
||||||
|
pr_info("KPM: copy_to_user() failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// all other cmds are for 'root manager'
|
// all other cmds are for 'root manager'
|
||||||
if (!from_manager) {
|
if (!from_manager) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -634,6 +670,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
|||||||
|
|
||||||
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
|
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
|
||||||
// filter the mountpoint whose target is `/data/adb`
|
// filter the mountpoint whose target is `/data/adb`
|
||||||
|
try_umount("/odm", true, 0);
|
||||||
try_umount("/system", true, 0);
|
try_umount("/system", true, 0);
|
||||||
try_umount("/system_ext", true, 0);
|
try_umount("/system_ext", true, 0);
|
||||||
try_umount("/vendor", true, 0);
|
try_umount("/vendor", true, 0);
|
||||||
@@ -723,15 +760,22 @@ __maybe_unused int ksu_kprobe_exit(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
extern int ksu_handle_devpts(struct inode *inode); // sucompat.c
|
||||||
unsigned long arg4, unsigned long arg5)
|
|
||||||
|
static int ksu_inode_permission(struct inode *inode, int mask)
|
||||||
{
|
{
|
||||||
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
|
if (unlikely(inode->i_sb && inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) {
|
||||||
return -ENOSYS;
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
|
pr_info("%s: devpts inode accessed with mask: %x\n", __func__, mask);
|
||||||
|
#endif
|
||||||
|
ksu_handle_devpts(inode);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
// kernel 4.4 and 4.9
|
|
||||||
|
// kernel 4.9 and older
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
||||||
unsigned perm)
|
unsigned perm)
|
||||||
{
|
{
|
||||||
if (init_session_keyring != NULL) {
|
if (init_session_keyring != NULL) {
|
||||||
@@ -746,6 +790,15 @@ static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
|
||||||
|
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||||
|
unsigned long arg4, unsigned long arg5)
|
||||||
|
{
|
||||||
|
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
|
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
|
||||||
struct inode *new_inode, struct dentry *new_dentry)
|
struct inode *new_inode, struct dentry *new_dentry)
|
||||||
{
|
{
|
||||||
@@ -763,6 +816,7 @@ static struct security_hook_list ksu_hooks[] = {
|
|||||||
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
|
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
|
||||||
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
|
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
|
||||||
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
|
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
|
||||||
|
LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
|
||||||
LSM_HOOK_INIT(key_permission, ksu_key_permission)
|
LSM_HOOK_INIT(key_permission, ksu_key_permission)
|
||||||
#endif
|
#endif
|
||||||
@@ -944,16 +998,21 @@ void __init ksu_lsm_hook_init(void)
|
|||||||
}
|
}
|
||||||
smp_mb();
|
smp_mb();
|
||||||
}
|
}
|
||||||
#endif
|
#endif // MODULE
|
||||||
|
#endif // CONFIG_KSU_LSM_SECURITY_HOOKS
|
||||||
|
|
||||||
void __init ksu_core_init(void)
|
void __init ksu_core_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
|
||||||
ksu_lsm_hook_init();
|
ksu_lsm_hook_init();
|
||||||
|
#else
|
||||||
|
pr_info("ksu_core_init: LSM hooks not in use.\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_core_exit(void)
|
void ksu_core_exit(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
pr_info("ksu_core_kprobe_exit\n");
|
pr_info("ksu_core_kprobe_exit\n");
|
||||||
// we dont use this now
|
// we dont use this now
|
||||||
// ksu_kprobe_exit();
|
// ksu_kprobe_exit();
|
||||||
|
|||||||
6
kernel/kpm/Makefile
Normal file
6
kernel/kpm/Makefile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
obj-y += kpm.o
|
||||||
|
obj-y += compact.o
|
||||||
|
obj-y += super_access.o
|
||||||
|
|
||||||
|
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
|
||||||
|
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
|
||||||
102
kernel/kpm/compact.c
Normal file
102
kernel/kpm/compact.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/kernfs.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/set_memory.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include "kpm.h"
|
||||||
|
#include "compact.h"
|
||||||
|
#include "../allowlist.h"
|
||||||
|
#include "../manager.h"
|
||||||
|
|
||||||
|
unsigned long sukisu_compact_find_symbol(const char* name);
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// 兼容函数 for KPM
|
||||||
|
|
||||||
|
static
|
||||||
|
int sukisu_is_su_allow_uid(uid_t uid) {
|
||||||
|
return ksu_is_allow_uid(uid) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int sukisu_get_ap_mod_exclude(uid_t uid) {
|
||||||
|
// Not supported
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int sukisu_is_uid_should_umount(uid_t uid) {
|
||||||
|
return ksu_uid_should_umount(uid) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int sukisu_is_current_uid_manager() {
|
||||||
|
return is_manager();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
uid_t sukisu_get_manager_uid() {
|
||||||
|
return ksu_manager_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
|
||||||
|
struct CompactAddressSymbol {
|
||||||
|
const char* symbol_name;
|
||||||
|
void* addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct CompactAddressSymbol address_symbol [] = {
|
||||||
|
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
||||||
|
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
||||||
|
{ "is_run_in_sukisu_ultra", (void*)1 },
|
||||||
|
{ "is_su_allow_uid", &sukisu_is_su_allow_uid },
|
||||||
|
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
|
||||||
|
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
|
||||||
|
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
|
||||||
|
{ "get_manager_uid", &sukisu_get_manager_uid }
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned long sukisu_compact_find_symbol(const char* name) {
|
||||||
|
int i;
|
||||||
|
unsigned long addr;
|
||||||
|
|
||||||
|
// 先自己在地址表部分查出来
|
||||||
|
for(i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) {
|
||||||
|
struct CompactAddressSymbol* symbol = &address_symbol[i];
|
||||||
|
if(strcmp(name, symbol->symbol_name) == 0) {
|
||||||
|
return (unsigned long) symbol->addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过内核来查
|
||||||
|
addr = kallsyms_lookup_name(name);
|
||||||
|
if(addr) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
||||||
6
kernel/kpm/compact.h
Normal file
6
kernel/kpm/compact.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef ___SUKISU_KPM_COMPACT_H
|
||||||
|
#define ___SUKISU_KPM_COMPACT_H
|
||||||
|
|
||||||
|
unsigned long sukisu_compact_find_symbol(const char* name);
|
||||||
|
|
||||||
|
#endif
|
||||||
184
kernel/kpm/kpm.c
Normal file
184
kernel/kpm/kpm.c
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Liankong (xhsw.new@outlook.com). All Rights Reserved.
|
||||||
|
* 本代码由GPL-2授权
|
||||||
|
*
|
||||||
|
* 适配KernelSU的KPM 内核模块加载器兼容实现
|
||||||
|
*
|
||||||
|
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
|
||||||
|
* 并参照KernelPatch的标准KPM格式实现加载和控制
|
||||||
|
*/
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/kernfs.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/set_memory.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <asm/insn.h>
|
||||||
|
#include <linux/kprobes.h>
|
||||||
|
#include <linux/stacktrace.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
|
||||||
|
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES
|
||||||
|
#endif
|
||||||
|
#include "kpm.h"
|
||||||
|
#include "compact.h"
|
||||||
|
|
||||||
|
#ifndef NO_OPTIMIZE
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#define NO_OPTIMIZE __attribute__((optimize("O0")))
|
||||||
|
#elif defined(__clang__)
|
||||||
|
#define NO_OPTIMIZE __attribute__((optnone))
|
||||||
|
#else
|
||||||
|
#define NO_OPTIMIZE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ============================================================================================
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr, void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr);
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_unload_module(const char* name, void* ptr, void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr);
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_num(void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = 0;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_num).\n");
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_info(const char* name, void __user* out, void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out);
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_list(void __user* out, unsigned int bufferSize, void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize);
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_control(void __user* name, void __user* args, void __user* result) {
|
||||||
|
// This is a KPM module stub.
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args);
|
||||||
|
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
noinline
|
||||||
|
NO_OPTIMIZE
|
||||||
|
void sukisu_kpm_version(void __user* out, unsigned int bufferSize, void __user* result) {
|
||||||
|
int res = -1;
|
||||||
|
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize);
|
||||||
|
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_load_module_path);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_unload_module);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_num);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_info);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_list);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_version);
|
||||||
|
EXPORT_SYMBOL(sukisu_kpm_control);
|
||||||
|
|
||||||
|
noinline
|
||||||
|
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||||
|
{
|
||||||
|
if(arg2 == SUKISU_KPM_LOAD) {
|
||||||
|
char kernel_load_path[256] = { 0 };
|
||||||
|
char kernel_args_buffer[256] = { 0 };
|
||||||
|
|
||||||
|
if(arg3 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg3, 255);
|
||||||
|
if(arg4 != 0) {
|
||||||
|
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255);
|
||||||
|
}
|
||||||
|
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_UNLOAD) {
|
||||||
|
char kernel_name_buffer[256] = { 0 };
|
||||||
|
|
||||||
|
if(arg3 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
||||||
|
sukisu_kpm_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_NUM) {
|
||||||
|
sukisu_kpm_num((void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_INFO) {
|
||||||
|
char kernel_name_buffer[256] = { 0 };
|
||||||
|
|
||||||
|
if(arg3 == 0 || arg4 == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
||||||
|
sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg4, (void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_LIST) {
|
||||||
|
sukisu_kpm_list((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_VERSION) {
|
||||||
|
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
||||||
|
} else if(arg2 == SUKISU_KPM_CONTROL) {
|
||||||
|
sukisu_kpm_control((char __user*) arg3, (char __user*) arg4, (void __user*) arg5);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sukisu_is_kpm_control_code(unsigned long arg2) {
|
||||||
|
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(sukisu_handle_kpm);
|
||||||
44
kernel/kpm/kpm.h
Normal file
44
kernel/kpm/kpm.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef ___SUKISU_KPM_H
|
||||||
|
#define ___SUKISU_KPM_H
|
||||||
|
|
||||||
|
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
||||||
|
int sukisu_is_kpm_control_code(unsigned long arg2);
|
||||||
|
|
||||||
|
// KPM控制代码
|
||||||
|
#define CMD_KPM_CONTROL 28
|
||||||
|
#define CMD_KPM_CONTROL_MAX 35
|
||||||
|
|
||||||
|
// 控制代码
|
||||||
|
|
||||||
|
// prctl(xxx, 28, "PATH", "ARGS")
|
||||||
|
// success return 0, error return -N
|
||||||
|
#define SUKISU_KPM_LOAD 28
|
||||||
|
|
||||||
|
// prctl(xxx, 29, "NAME")
|
||||||
|
// success return 0, error return -N
|
||||||
|
#define SUKISU_KPM_UNLOAD 29
|
||||||
|
|
||||||
|
// num = prctl(xxx, 30)
|
||||||
|
// error return -N
|
||||||
|
// success return +num or 0
|
||||||
|
#define SUKISU_KPM_NUM 30
|
||||||
|
|
||||||
|
// prctl(xxx, 31, Buffer, BufferSize)
|
||||||
|
// success return +out, error return -N
|
||||||
|
#define SUKISU_KPM_LIST 31
|
||||||
|
|
||||||
|
// prctl(xxx, 32, "NAME", Buffer[256])
|
||||||
|
// success return +out, error return -N
|
||||||
|
#define SUKISU_KPM_INFO 32
|
||||||
|
|
||||||
|
// prctl(xxx, 33, "NAME", "ARGS")
|
||||||
|
// success return KPM's result value
|
||||||
|
// error return -N
|
||||||
|
#define SUKISU_KPM_CONTROL 33
|
||||||
|
|
||||||
|
// prctl(xxx, 34, buffer, bufferSize)
|
||||||
|
// success return KPM's result value
|
||||||
|
// error return -N
|
||||||
|
#define SUKISU_KPM_VERSION 34
|
||||||
|
|
||||||
|
#endif
|
||||||
289
kernel/kpm/super_access.c
Normal file
289
kernel/kpm/super_access.c
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/kernfs.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
|
#include <linux/kallsyms.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/set_memory.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include "kpm.h"
|
||||||
|
#include "compact.h"
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
|
||||||
|
// 结构体成员元数据
|
||||||
|
struct DynamicStructMember {
|
||||||
|
const char* name;
|
||||||
|
size_t size;
|
||||||
|
size_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 结构体元数据(包含总大小)
|
||||||
|
struct DynamicStructInfo {
|
||||||
|
const char* name;
|
||||||
|
size_t count;
|
||||||
|
size_t total_size;
|
||||||
|
struct DynamicStructMember* members;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 定义结构体元数据的宏(直接使用 struct 名称)
|
||||||
|
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
|
||||||
|
static struct DynamicStructMember struct_name##_members[] = {
|
||||||
|
|
||||||
|
#define DEFINE_MEMBER(struct_name, member) \
|
||||||
|
{ \
|
||||||
|
.name = #member, \
|
||||||
|
.size = sizeof(((struct struct_name*)0)->member), \
|
||||||
|
.offset = offsetof(struct struct_name, member) \
|
||||||
|
},
|
||||||
|
|
||||||
|
#define DYNAMIC_STRUCT_END(struct_name) \
|
||||||
|
}; \
|
||||||
|
static struct DynamicStructInfo struct_name##_info = { \
|
||||||
|
.name = #struct_name, \
|
||||||
|
.count = sizeof(struct_name##_members) / sizeof(struct DynamicStructMember), \
|
||||||
|
.total_size = sizeof(struct struct_name), \
|
||||||
|
.members = struct_name##_members \
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==================================================================================
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
#define KERNEL_VERSION_6_1 KERNEL_VERSION(6, 1, 0)
|
||||||
|
#define KERNEL_VERSION_5_15 KERNEL_VERSION(5, 15, 0)
|
||||||
|
|
||||||
|
#include <../fs/mount.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
|
|
||||||
|
// 定义元数据
|
||||||
|
DYNAMIC_STRUCT_BEGIN(mount)
|
||||||
|
DEFINE_MEMBER(mount, mnt_parent)
|
||||||
|
DEFINE_MEMBER(mount, mnt)
|
||||||
|
DEFINE_MEMBER(mount, mnt_id)
|
||||||
|
DEFINE_MEMBER(mount, mnt_group_id)
|
||||||
|
DEFINE_MEMBER(mount, mnt_expiry_mark)
|
||||||
|
DEFINE_MEMBER(mount, mnt_master)
|
||||||
|
DEFINE_MEMBER(mount, mnt_devname)
|
||||||
|
DYNAMIC_STRUCT_END(mount)
|
||||||
|
|
||||||
|
DYNAMIC_STRUCT_BEGIN(vfsmount)
|
||||||
|
DEFINE_MEMBER(vfsmount, mnt_root)
|
||||||
|
DEFINE_MEMBER(vfsmount, mnt_sb)
|
||||||
|
DEFINE_MEMBER(vfsmount, mnt_flags)
|
||||||
|
DYNAMIC_STRUCT_END(vfsmount)
|
||||||
|
|
||||||
|
DYNAMIC_STRUCT_BEGIN(mnt_namespace)
|
||||||
|
DEFINE_MEMBER(mnt_namespace, ns)
|
||||||
|
DEFINE_MEMBER(mnt_namespace, root)
|
||||||
|
DEFINE_MEMBER(mnt_namespace, seq)
|
||||||
|
DEFINE_MEMBER(mnt_namespace, mounts)
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||||
|
DEFINE_MEMBER(mnt_namespace, count)
|
||||||
|
#endif
|
||||||
|
DYNAMIC_STRUCT_END(mnt_namespace)
|
||||||
|
|
||||||
|
#include <linux/kprobes.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_KPROBES
|
||||||
|
DYNAMIC_STRUCT_BEGIN(kprobe)
|
||||||
|
DEFINE_MEMBER(kprobe, addr)
|
||||||
|
DEFINE_MEMBER(kprobe, symbol_name)
|
||||||
|
DEFINE_MEMBER(kprobe, offset)
|
||||||
|
DEFINE_MEMBER(kprobe, pre_handler)
|
||||||
|
DEFINE_MEMBER(kprobe, post_handler)
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||||
|
DEFINE_MEMBER(kprobe, fault_handler)
|
||||||
|
#endif
|
||||||
|
DEFINE_MEMBER(kprobe, flags)
|
||||||
|
DYNAMIC_STRUCT_END(kprobe)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/mm_types.h>
|
||||||
|
|
||||||
|
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_start)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_end)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_flags)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,anon_vma)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_pgoff)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_file)
|
||||||
|
DEFINE_MEMBER(vm_area_struct,vm_private_data)
|
||||||
|
#ifdef CONFIG_ANON_VMA_NAME
|
||||||
|
DEFINE_MEMBER(vm_area_struct, anon_name)
|
||||||
|
#endif
|
||||||
|
DEFINE_MEMBER(vm_area_struct, vm_ops)
|
||||||
|
DYNAMIC_STRUCT_END(vm_area_struct)
|
||||||
|
|
||||||
|
DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
|
||||||
|
DEFINE_MEMBER(vm_operations_struct, open)
|
||||||
|
DEFINE_MEMBER(vm_operations_struct, close)
|
||||||
|
DEFINE_MEMBER(vm_operations_struct, name)
|
||||||
|
DEFINE_MEMBER(vm_operations_struct, access)
|
||||||
|
DYNAMIC_STRUCT_END(vm_operations_struct)
|
||||||
|
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, groups)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, flags)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, input)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, bind)
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1
|
||||||
|
DEFINE_MEMBER(netlink_kernel_cfg, compare)
|
||||||
|
#endif
|
||||||
|
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
DYNAMIC_STRUCT_BEGIN(task_struct)
|
||||||
|
DEFINE_MEMBER(task_struct, pid)
|
||||||
|
DEFINE_MEMBER(task_struct, tgid)
|
||||||
|
DEFINE_MEMBER(task_struct, cred)
|
||||||
|
DEFINE_MEMBER(task_struct, real_cred)
|
||||||
|
DEFINE_MEMBER(task_struct, comm)
|
||||||
|
DEFINE_MEMBER(task_struct, parent)
|
||||||
|
DEFINE_MEMBER(task_struct, group_leader)
|
||||||
|
DEFINE_MEMBER(task_struct, mm)
|
||||||
|
DEFINE_MEMBER(task_struct, active_mm)
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||||
|
DEFINE_MEMBER(task_struct, pids[PIDTYPE_PID].pid)
|
||||||
|
#else
|
||||||
|
DEFINE_MEMBER(task_struct, thread_pid)
|
||||||
|
#endif
|
||||||
|
DEFINE_MEMBER(task_struct, files)
|
||||||
|
DEFINE_MEMBER(task_struct, seccomp)
|
||||||
|
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
||||||
|
DEFINE_MEMBER(task_struct, thread_info)
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CGROUPS
|
||||||
|
DEFINE_MEMBER(task_struct, cgroups)
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SECURITY
|
||||||
|
DEFINE_MEMBER(task_struct, security)
|
||||||
|
#endif
|
||||||
|
DEFINE_MEMBER(task_struct, thread)
|
||||||
|
DYNAMIC_STRUCT_END(task_struct)
|
||||||
|
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
#define STRUCT_INFO(name) &(name##_info)
|
||||||
|
|
||||||
|
static
|
||||||
|
struct DynamicStructInfo* dynamic_struct_infos[] = {
|
||||||
|
STRUCT_INFO(mount),
|
||||||
|
STRUCT_INFO(vfsmount),
|
||||||
|
STRUCT_INFO(mnt_namespace),
|
||||||
|
#ifdef CONFIG_KPROBES
|
||||||
|
STRUCT_INFO(kprobe),
|
||||||
|
#endif
|
||||||
|
STRUCT_INFO(vm_area_struct),
|
||||||
|
STRUCT_INFO(vm_operations_struct),
|
||||||
|
STRUCT_INFO(netlink_kernel_cfg),
|
||||||
|
STRUCT_INFO(task_struct)
|
||||||
|
};
|
||||||
|
|
||||||
|
// return 0 if successful
|
||||||
|
// return -1 if struct not defined
|
||||||
|
int sukisu_super_find_struct(
|
||||||
|
const char* struct_name,
|
||||||
|
size_t* out_size,
|
||||||
|
int* out_members
|
||||||
|
) {
|
||||||
|
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||||
|
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||||
|
if(strcmp(struct_name, info->name) == 0) {
|
||||||
|
if(out_size)
|
||||||
|
*out_size = info->total_size;
|
||||||
|
if(out_members)
|
||||||
|
*out_members = info->count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(sukisu_super_find_struct);
|
||||||
|
|
||||||
|
// Dynamic access struct
|
||||||
|
// return 0 if successful
|
||||||
|
// return -1 if struct not defined
|
||||||
|
// return -2 if member not defined
|
||||||
|
int sukisu_super_access (
|
||||||
|
const char* struct_name,
|
||||||
|
const char* member_name,
|
||||||
|
size_t* out_offset,
|
||||||
|
size_t* out_size
|
||||||
|
) {
|
||||||
|
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||||
|
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||||
|
if(strcmp(struct_name, info->name) == 0) {
|
||||||
|
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||||
|
if (strcmp(info->members[i1].name, member_name) == 0) {
|
||||||
|
if(out_offset)
|
||||||
|
*out_offset = info->members[i].offset;
|
||||||
|
if(out_size)
|
||||||
|
*out_size = info->members[i].size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(sukisu_super_access);
|
||||||
|
|
||||||
|
// 动态 container_of 宏
|
||||||
|
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \
|
||||||
|
(offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \
|
||||||
|
})
|
||||||
|
|
||||||
|
// Dynamic container_of
|
||||||
|
// return 0 if success
|
||||||
|
// return -1 if current struct not defined
|
||||||
|
// return -2 if target member not defined
|
||||||
|
int sukisu_super_container_of(
|
||||||
|
const char* struct_name,
|
||||||
|
const char* member_name,
|
||||||
|
void* ptr,
|
||||||
|
void** out_ptr
|
||||||
|
) {
|
||||||
|
if(ptr == NULL) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||||
|
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||||
|
if(strcmp(struct_name, info->name) == 0) {
|
||||||
|
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||||
|
if (strcmp(info->members[i1].name, member_name) == 0) {
|
||||||
|
*out_ptr = (void*) DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(sukisu_super_container_of);
|
||||||
39
kernel/kpm/super_access.h
Normal file
39
kernel/kpm/super_access.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __SUKISU_SUPER_ACCESS_H
|
||||||
|
#define __SUKISU_SUPER_ACCESS_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include "kpm.h"
|
||||||
|
#include "compact.h"
|
||||||
|
|
||||||
|
// return 0 if successful
|
||||||
|
// return -1 if struct not defined
|
||||||
|
int sukisu_super_find_struct(
|
||||||
|
const char* struct_name,
|
||||||
|
size_t* out_size,
|
||||||
|
int* out_members
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dynamic access struct
|
||||||
|
// return 0 if successful
|
||||||
|
// return -1 if struct not defined
|
||||||
|
// return -2 if member not defined
|
||||||
|
int sukisu_super_access (
|
||||||
|
const char* struct_name,
|
||||||
|
const char* member_name,
|
||||||
|
size_t* out_offset,
|
||||||
|
size_t* out_size
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dynamic container_of
|
||||||
|
// return 0 if success
|
||||||
|
// return -1 if current struct not defined
|
||||||
|
// return -2 if target member not defined
|
||||||
|
int sukisu_super_container_of(
|
||||||
|
const char* struct_name,
|
||||||
|
const char* member_name,
|
||||||
|
void* ptr,
|
||||||
|
void** out_ptr
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -57,7 +57,7 @@ int __init kernelsu_init(void)
|
|||||||
|
|
||||||
ksu_throne_tracker_init();
|
ksu_throne_tracker_init();
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
ksu_sucompat_init();
|
ksu_sucompat_init();
|
||||||
ksu_ksud_init();
|
ksu_ksud_init();
|
||||||
#else
|
#else
|
||||||
@@ -80,7 +80,7 @@ void kernelsu_exit(void)
|
|||||||
|
|
||||||
destroy_workqueue(ksu_workqueue);
|
destroy_workqueue(ksu_workqueue);
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
ksu_ksud_exit();
|
ksu_ksud_exit();
|
||||||
ksu_sucompat_exit();
|
ksu_sucompat_exit();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#define CMD_UID_SHOULD_UMOUNT 13
|
#define CMD_UID_SHOULD_UMOUNT 13
|
||||||
#define CMD_IS_SU_ENABLED 14
|
#define CMD_IS_SU_ENABLED 14
|
||||||
#define CMD_ENABLE_SU 15
|
#define CMD_ENABLE_SU 15
|
||||||
|
#define CMD_HOOK_MODE 16
|
||||||
|
|
||||||
|
// This is used to check if the kernel supports KPM
|
||||||
|
#define CMD_ENABLE_KPM 100
|
||||||
|
|
||||||
#define EVENT_POST_FS_DATA 1
|
#define EVENT_POST_FS_DATA 1
|
||||||
#define EVENT_BOOT_COMPLETED 2
|
#define EVENT_BOOT_COMPLETED 2
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ static void stop_vfs_read_hook();
|
|||||||
static void stop_execve_hook();
|
static void stop_execve_hook();
|
||||||
static void stop_input_hook();
|
static void stop_input_hook();
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
static struct work_struct stop_vfs_read_work;
|
static struct work_struct stop_vfs_read_work;
|
||||||
static struct work_struct stop_execve_hook_work;
|
static struct work_struct stop_execve_hook_work;
|
||||||
static struct work_struct stop_input_hook_work;
|
static struct work_struct stop_input_hook_work;
|
||||||
@@ -67,6 +67,10 @@ bool ksu_input_hook __read_mostly = true;
|
|||||||
|
|
||||||
u32 ksu_devpts_sid;
|
u32 ksu_devpts_sid;
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
bool ksu_is_compat __read_mostly = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
void on_post_fs_data(void)
|
void on_post_fs_data(void)
|
||||||
{
|
{
|
||||||
static bool done = false;
|
static bool done = false;
|
||||||
@@ -108,6 +112,7 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
|
|||||||
if (get_user(compat, argv.ptr.compat + nr))
|
if (get_user(compat, argv.ptr.compat + nr))
|
||||||
return ERR_PTR(-EFAULT);
|
return ERR_PTR(-EFAULT);
|
||||||
|
|
||||||
|
ksu_is_compat = true;
|
||||||
return compat_ptr(compat);
|
return compat_ptr(compat);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -158,7 +163,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
struct user_arg_ptr *argv,
|
struct user_arg_ptr *argv,
|
||||||
struct user_arg_ptr *envp, int *flags)
|
struct user_arg_ptr *envp, int *flags)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_execveat_hook) {
|
if (!ksu_execveat_hook) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -314,7 +319,7 @@ static ssize_t read_iter_proxy(struct kiocb *iocb, struct iov_iter *to)
|
|||||||
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
|
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
|
||||||
size_t *count_ptr, loff_t **pos)
|
size_t *count_ptr, loff_t **pos)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_vfs_read_hook) {
|
if (!ksu_vfs_read_hook) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -333,7 +338,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d_is_reg(file->f_path.dentry)) {
|
if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +432,7 @@ static bool is_volumedown_enough(unsigned int count)
|
|||||||
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
|
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
|
||||||
int *value)
|
int *value)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_input_hook) {
|
if (!ksu_input_hook) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -499,7 +504,7 @@ __maybe_unused int ksu_handle_execve_ksud(const char __user *filename_user,
|
|||||||
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL, NULL);
|
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
|
|
||||||
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
|
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
|
||||||
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||||
@@ -629,7 +634,7 @@ static void do_stop_input_hook(struct work_struct *work)
|
|||||||
|
|
||||||
static void stop_vfs_read_hook()
|
static void stop_vfs_read_hook()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
bool ret = schedule_work(&stop_vfs_read_work);
|
bool ret = schedule_work(&stop_vfs_read_work);
|
||||||
pr_info("unregister vfs_read kprobe: %d!\n", ret);
|
pr_info("unregister vfs_read kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
@@ -640,7 +645,7 @@ static void stop_vfs_read_hook()
|
|||||||
|
|
||||||
static void stop_execve_hook()
|
static void stop_execve_hook()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
bool ret = schedule_work(&stop_execve_hook_work);
|
bool ret = schedule_work(&stop_execve_hook_work);
|
||||||
pr_info("unregister execve kprobe: %d!\n", ret);
|
pr_info("unregister execve kprobe: %d!\n", ret);
|
||||||
#else
|
#else
|
||||||
@@ -651,7 +656,7 @@ static void stop_execve_hook()
|
|||||||
|
|
||||||
static void stop_input_hook()
|
static void stop_input_hook()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
static bool input_hook_stopped = false;
|
static bool input_hook_stopped = false;
|
||||||
if (input_hook_stopped) {
|
if (input_hook_stopped) {
|
||||||
return;
|
return;
|
||||||
@@ -669,7 +674,7 @@ static void stop_input_hook()
|
|||||||
// ksud: module support
|
// ksud: module support
|
||||||
void ksu_ksud_init()
|
void ksu_ksud_init()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = register_kprobe(&execve_kp);
|
ret = register_kprobe(&execve_kp);
|
||||||
@@ -689,7 +694,7 @@ void ksu_ksud_init()
|
|||||||
|
|
||||||
void ksu_ksud_exit()
|
void ksu_ksud_exit()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
unregister_kprobe(&execve_kp);
|
unregister_kprobe(&execve_kp);
|
||||||
// this should be done before unregister vfs_read_kp
|
// this should be done before unregister vfs_read_kp
|
||||||
// unregister_kprobe(&vfs_read_kp);
|
// unregister_kprobe(&vfs_read_kp);
|
||||||
|
|||||||
@@ -149,17 +149,45 @@ void apply_kernelsu_rules()
|
|||||||
#define CMD_TYPE_CHANGE 8
|
#define CMD_TYPE_CHANGE 8
|
||||||
#define CMD_GENFSCON 9
|
#define CMD_GENFSCON 9
|
||||||
|
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
struct sepol_data {
|
struct sepol_data {
|
||||||
u32 cmd;
|
u32 cmd;
|
||||||
u32 subcmd;
|
u32 subcmd;
|
||||||
char __user *sepol1;
|
u64 field_sepol1;
|
||||||
char __user *sepol2;
|
u64 field_sepol2;
|
||||||
char __user *sepol3;
|
u64 field_sepol3;
|
||||||
char __user *sepol4;
|
u64 field_sepol4;
|
||||||
char __user *sepol5;
|
u64 field_sepol5;
|
||||||
char __user *sepol6;
|
u64 field_sepol6;
|
||||||
char __user *sepol7;
|
u64 field_sepol7;
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
extern bool ksu_is_compat __read_mostly;
|
||||||
|
struct sepol_compat_data {
|
||||||
|
u32 cmd;
|
||||||
|
u32 subcmd;
|
||||||
|
u32 field_sepol1;
|
||||||
|
u32 field_sepol2;
|
||||||
|
u32 field_sepol3;
|
||||||
|
u32 field_sepol4;
|
||||||
|
u32 field_sepol5;
|
||||||
|
u32 field_sepol6;
|
||||||
|
u32 field_sepol7;
|
||||||
|
};
|
||||||
|
#endif // CONFIG_COMPAT
|
||||||
|
#else
|
||||||
|
struct sepol_data {
|
||||||
|
u32 cmd;
|
||||||
|
u32 subcmd;
|
||||||
|
u32 field_sepol1;
|
||||||
|
u32 field_sepol2;
|
||||||
|
u32 field_sepol3;
|
||||||
|
u32 field_sepol4;
|
||||||
|
u32 field_sepol5;
|
||||||
|
u32 field_sepol6;
|
||||||
|
u32 field_sepol7;
|
||||||
|
};
|
||||||
|
#endif // CONFIG_64BIT
|
||||||
|
|
||||||
static int get_object(char *buf, char __user *user_object, size_t buf_sz,
|
static int get_object(char *buf, char __user *user_object, size_t buf_sz,
|
||||||
char **object)
|
char **object)
|
||||||
@@ -205,14 +233,58 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
pr_info("SELinux permissive or disabled when handle policy!\n");
|
pr_info("SELinux permissive or disabled when handle policy!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 cmd, subcmd;
|
||||||
|
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
|
||||||
|
|
||||||
|
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
|
||||||
|
if (unlikely(ksu_is_compat)) {
|
||||||
|
struct sepol_compat_data compat_data;
|
||||||
|
if (copy_from_user(&compat_data, arg4, sizeof(struct sepol_compat_data))) {
|
||||||
|
pr_err("sepol: copy sepol_data failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sepol1 = compat_ptr(compat_data.field_sepol1);
|
||||||
|
sepol2 = compat_ptr(compat_data.field_sepol2);
|
||||||
|
sepol3 = compat_ptr(compat_data.field_sepol3);
|
||||||
|
sepol4 = compat_ptr(compat_data.field_sepol4);
|
||||||
|
sepol5 = compat_ptr(compat_data.field_sepol5);
|
||||||
|
sepol6 = compat_ptr(compat_data.field_sepol6);
|
||||||
|
sepol7 = compat_ptr(compat_data.field_sepol7);
|
||||||
|
cmd = compat_data.cmd;
|
||||||
|
subcmd = compat_data.subcmd;
|
||||||
|
} else {
|
||||||
|
struct sepol_data data;
|
||||||
|
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
|
||||||
|
pr_err("sepol: copy sepol_data failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sepol1 = data.field_sepol1;
|
||||||
|
sepol2 = data.field_sepol2;
|
||||||
|
sepol3 = data.field_sepol3;
|
||||||
|
sepol4 = data.field_sepol4;
|
||||||
|
sepol5 = data.field_sepol5;
|
||||||
|
sepol6 = data.field_sepol6;
|
||||||
|
sepol7 = data.field_sepol7;
|
||||||
|
cmd = data.cmd;
|
||||||
|
subcmd = data.subcmd;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// basically for full native, say (64BIT=y COMPAT=n) || (64BIT=n)
|
||||||
struct sepol_data data;
|
struct sepol_data data;
|
||||||
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
|
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
|
||||||
pr_err("sepol: copy sepol_data failed.\n");
|
pr_err("sepol: copy sepol_data failed.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
sepol1 = data.field_sepol1;
|
||||||
u32 cmd = data.cmd;
|
sepol2 = data.field_sepol2;
|
||||||
u32 subcmd = data.subcmd;
|
sepol3 = data.field_sepol3;
|
||||||
|
sepol4 = data.field_sepol4;
|
||||||
|
sepol5 = data.field_sepol5;
|
||||||
|
sepol6 = data.field_sepol6;
|
||||||
|
sepol7 = data.field_sepol7;
|
||||||
|
cmd = data.cmd;
|
||||||
|
subcmd = data.subcmd;
|
||||||
|
#endif
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
@@ -226,22 +298,22 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char perm_buf[MAX_SEPOL_LEN];
|
char perm_buf[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
char *s, *t, *c, *p;
|
char *s, *t, *c, *p;
|
||||||
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
|
if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
|
||||||
pr_err("sepol: copy src failed.\n");
|
pr_err("sepol: copy src failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
|
if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
|
||||||
pr_err("sepol: copy tgt failed.\n");
|
pr_err("sepol: copy tgt failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) {
|
if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
|
||||||
pr_err("sepol: copy cls failed.\n");
|
pr_err("sepol: copy cls failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) <
|
if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) <
|
||||||
0) {
|
0) {
|
||||||
pr_err("sepol: copy perm failed.\n");
|
pr_err("sepol: copy perm failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -271,24 +343,24 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char perm_set[MAX_SEPOL_LEN];
|
char perm_set[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
char *s, *t, *c;
|
char *s, *t, *c;
|
||||||
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) {
|
if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
|
||||||
pr_err("sepol: copy src failed.\n");
|
pr_err("sepol: copy src failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) {
|
if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
|
||||||
pr_err("sepol: copy tgt failed.\n");
|
pr_err("sepol: copy tgt failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) {
|
if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
|
||||||
pr_err("sepol: copy cls failed.\n");
|
pr_err("sepol: copy cls failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(operation, data.sepol4,
|
if (strncpy_from_user(operation, sepol4,
|
||||||
sizeof(operation)) < 0) {
|
sizeof(operation)) < 0) {
|
||||||
pr_err("sepol: copy operation failed.\n");
|
pr_err("sepol: copy operation failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(perm_set, data.sepol5, sizeof(perm_set)) <
|
if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
|
||||||
0) {
|
0) {
|
||||||
pr_err("sepol: copy perm_set failed.\n");
|
pr_err("sepol: copy perm_set failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -308,7 +380,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
} else if (cmd == CMD_TYPE_STATE) {
|
} else if (cmd == CMD_TYPE_STATE) {
|
||||||
char src[MAX_SEPOL_LEN];
|
char src[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
|
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
|
||||||
pr_err("sepol: copy src failed.\n");
|
pr_err("sepol: copy src failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -328,11 +400,11 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char type[MAX_SEPOL_LEN];
|
char type[MAX_SEPOL_LEN];
|
||||||
char attr[MAX_SEPOL_LEN];
|
char attr[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) {
|
if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) {
|
||||||
pr_err("sepol: copy type failed.\n");
|
pr_err("sepol: copy type failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(attr, data.sepol2, sizeof(attr)) < 0) {
|
if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) {
|
||||||
pr_err("sepol: copy attr failed.\n");
|
pr_err("sepol: copy attr failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -352,7 +424,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
} else if (cmd == CMD_ATTR) {
|
} else if (cmd == CMD_ATTR) {
|
||||||
char attr[MAX_SEPOL_LEN];
|
char attr[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) {
|
if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) {
|
||||||
pr_err("sepol: copy attr failed.\n");
|
pr_err("sepol: copy attr failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -369,28 +441,28 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char default_type[MAX_SEPOL_LEN];
|
char default_type[MAX_SEPOL_LEN];
|
||||||
char object[MAX_SEPOL_LEN];
|
char object[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
|
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
|
||||||
pr_err("sepol: copy src failed.\n");
|
pr_err("sepol: copy src failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
|
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
|
||||||
pr_err("sepol: copy tgt failed.\n");
|
pr_err("sepol: copy tgt failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
|
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
|
||||||
pr_err("sepol: copy cls failed.\n");
|
pr_err("sepol: copy cls failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(default_type, data.sepol4,
|
if (strncpy_from_user(default_type, sepol4,
|
||||||
sizeof(default_type)) < 0) {
|
sizeof(default_type)) < 0) {
|
||||||
pr_err("sepol: copy default_type failed.\n");
|
pr_err("sepol: copy default_type failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
char *real_object;
|
char *real_object;
|
||||||
if (data.sepol5 == NULL) {
|
if (sepol5 == NULL) {
|
||||||
real_object = NULL;
|
real_object = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (strncpy_from_user(object, data.sepol5,
|
if (strncpy_from_user(object, sepol5,
|
||||||
sizeof(object)) < 0) {
|
sizeof(object)) < 0) {
|
||||||
pr_err("sepol: copy object failed.\n");
|
pr_err("sepol: copy object failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -409,19 +481,19 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char cls[MAX_SEPOL_LEN];
|
char cls[MAX_SEPOL_LEN];
|
||||||
char default_type[MAX_SEPOL_LEN];
|
char default_type[MAX_SEPOL_LEN];
|
||||||
|
|
||||||
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) {
|
if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
|
||||||
pr_err("sepol: copy src failed.\n");
|
pr_err("sepol: copy src failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) {
|
if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
|
||||||
pr_err("sepol: copy tgt failed.\n");
|
pr_err("sepol: copy tgt failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) {
|
if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
|
||||||
pr_err("sepol: copy cls failed.\n");
|
pr_err("sepol: copy cls failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(default_type, data.sepol4,
|
if (strncpy_from_user(default_type, sepol4,
|
||||||
sizeof(default_type)) < 0) {
|
sizeof(default_type)) < 0) {
|
||||||
pr_err("sepol: copy default_type failed.\n");
|
pr_err("sepol: copy default_type failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -442,15 +514,15 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
|
|||||||
char name[MAX_SEPOL_LEN];
|
char name[MAX_SEPOL_LEN];
|
||||||
char path[MAX_SEPOL_LEN];
|
char path[MAX_SEPOL_LEN];
|
||||||
char context[MAX_SEPOL_LEN];
|
char context[MAX_SEPOL_LEN];
|
||||||
if (strncpy_from_user(name, data.sepol1, sizeof(name)) < 0) {
|
if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) {
|
||||||
pr_err("sepol: copy name failed.\n");
|
pr_err("sepol: copy name failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(path, data.sepol2, sizeof(path)) < 0) {
|
if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) {
|
||||||
pr_err("sepol: copy path failed.\n");
|
pr_err("sepol: copy path failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncpy_from_user(context, data.sepol3, sizeof(context)) <
|
if (strncpy_from_user(context, sepol3, sizeof(context)) <
|
||||||
0) {
|
0) {
|
||||||
pr_err("sepol: copy context failed.\n");
|
pr_err("sepol: copy context failed.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|||||||
@@ -24,11 +24,9 @@
|
|||||||
#define SU_PATH "/system/bin/su"
|
#define SU_PATH "/system/bin/su"
|
||||||
#define SH_PATH "/system/bin/sh"
|
#define SH_PATH "/system/bin/sh"
|
||||||
|
|
||||||
bool ksu_faccessat_hook __read_mostly = true;
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
bool ksu_stat_hook __read_mostly = true;
|
static bool ksu_sucompat_non_kp __read_mostly = true;
|
||||||
bool ksu_execve_sucompat_hook __read_mostly = true;
|
#endif
|
||||||
bool ksu_execveat_sucompat_hook __read_mostly = true;
|
|
||||||
bool ksu_devpts_hook __read_mostly = true;
|
|
||||||
|
|
||||||
extern void escape_to_root();
|
extern void escape_to_root();
|
||||||
|
|
||||||
@@ -60,8 +58,8 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
|
|||||||
{
|
{
|
||||||
const char su[] = SU_PATH;
|
const char su[] = SU_PATH;
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_faccessat_hook) {
|
if (!ksu_sucompat_non_kp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -87,8 +85,8 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
|
|||||||
// const char sh[] = SH_PATH;
|
// const char sh[] = SH_PATH;
|
||||||
const char su[] = SU_PATH;
|
const char su[] = SU_PATH;
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_stat_hook){
|
if (!ksu_sucompat_non_kp){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -137,8 +135,8 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
|
|||||||
const char sh[] = KSUD_PATH;
|
const char sh[] = KSUD_PATH;
|
||||||
const char su[] = SU_PATH;
|
const char su[] = SU_PATH;
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_execveat_sucompat_hook) {
|
if (!ksu_sucompat_non_kp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -172,8 +170,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
|||||||
const char su[] = SU_PATH;
|
const char su[] = SU_PATH;
|
||||||
char path[sizeof(su) + 1];
|
char path[sizeof(su) + 1];
|
||||||
|
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_execve_sucompat_hook) {
|
if (!ksu_sucompat_non_kp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -181,8 +179,23 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
|||||||
if (unlikely(!filename_user))
|
if (unlikely(!filename_user))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(path, 0, sizeof(path));
|
// nofault variant fails probably due to pagefault_disable
|
||||||
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
// some cpus dont really have that good speculative execution
|
||||||
|
// substitute set_fs, check if pointer is valid
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||||
|
if (!access_ok(VERIFY_READ, *filename_user, sizeof(path)))
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
if (!access_ok(*filename_user, sizeof(path)))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
// success = returns number of bytes and should be less than path
|
||||||
|
long len = strncpy_from_user(path, *filename_user, sizeof(path));
|
||||||
|
if (len <= 0 || len > sizeof(path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// strncpy_from_user_nofault does this too
|
||||||
|
path[sizeof(path) - 1] = '\0';
|
||||||
|
|
||||||
if (likely(memcmp(path, su, sizeof(su))))
|
if (likely(memcmp(path, su, sizeof(su))))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -200,8 +213,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
|
|||||||
|
|
||||||
int ksu_handle_devpts(struct inode *inode)
|
int ksu_handle_devpts(struct inode *inode)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_KSU_WITH_KPROBES
|
#ifndef CONFIG_KSU_KPROBES_HOOK
|
||||||
if (!ksu_devpts_hook) {
|
if (!ksu_sucompat_non_kp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -234,7 +247,7 @@ int ksu_handle_devpts(struct inode *inode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
|
|
||||||
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
@@ -317,33 +330,25 @@ static struct kprobe *su_kps[4];
|
|||||||
// sucompat: permited process can execute 'su' to gain root access.
|
// sucompat: permited process can execute 'su' to gain root access.
|
||||||
void ksu_sucompat_init()
|
void ksu_sucompat_init()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre);
|
su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre);
|
||||||
su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre);
|
su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre);
|
||||||
su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre);
|
su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre);
|
||||||
su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre);
|
su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre);
|
||||||
#else
|
#else
|
||||||
ksu_faccessat_hook = true;
|
ksu_sucompat_non_kp = true;
|
||||||
ksu_stat_hook = true;
|
|
||||||
ksu_execve_sucompat_hook = true;
|
|
||||||
ksu_execveat_sucompat_hook = true;
|
|
||||||
ksu_devpts_hook = true;
|
|
||||||
pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n");
|
pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_sucompat_exit()
|
void ksu_sucompat_exit()
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_KSU_WITH_KPROBES
|
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||||
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
|
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
|
||||||
destroy_kprobe(&su_kps[i]);
|
destroy_kprobe(&su_kps[i]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ksu_faccessat_hook = false;
|
ksu_sucompat_non_kp = false;
|
||||||
ksu_stat_hook = false;
|
|
||||||
ksu_execve_sucompat_hook = false;
|
|
||||||
ksu_execveat_sucompat_hook = false;
|
|
||||||
ksu_devpts_hook = false;
|
|
||||||
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
|
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
#include <linux/namei.h>
|
||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
@@ -13,9 +14,13 @@
|
|||||||
#include "throne_tracker.h"
|
#include "throne_tracker.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
||||||
|
|
||||||
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list.tmp"
|
static struct task_struct *throne_thread;
|
||||||
|
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
||||||
|
|
||||||
struct uid_data {
|
struct uid_data {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -115,6 +120,7 @@ struct my_dir_context {
|
|||||||
void *private_data;
|
void *private_data;
|
||||||
int depth;
|
int depth;
|
||||||
int *stop;
|
int *stop;
|
||||||
|
struct super_block* root_sb;
|
||||||
};
|
};
|
||||||
// https://docs.kernel.org/filesystems/porting.html
|
// https://docs.kernel.org/filesystems/porting.html
|
||||||
// filldir_t (readdir callbacks) calling conventions have changed. Instead of returning 0 or -E... it returns bool now. false means "no more" (as -E... used to) and true - "keep going" (as 0 in old calling conventions). Rationale: callers never looked at specific -E... values anyway. -> iterate_shared() instances require no changes at all, all filldir_t ones in the tree converted.
|
// filldir_t (readdir callbacks) calling conventions have changed. Instead of returning 0 or -E... it returns bool now. false means "no more" (as -E... used to) and true - "keep going" (as 0 in old calling conventions). Rationale: callers never looked at specific -E... values anyway. -> iterate_shared() instances require no changes at all, all filldir_t ones in the tree converted.
|
||||||
@@ -135,6 +141,8 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
struct my_dir_context *my_ctx =
|
struct my_dir_context *my_ctx =
|
||||||
container_of(ctx, struct my_dir_context, ctx);
|
container_of(ctx, struct my_dir_context, ctx);
|
||||||
char dirpath[DATA_PATH_LEN];
|
char dirpath[DATA_PATH_LEN];
|
||||||
|
int err;
|
||||||
|
struct path path;
|
||||||
|
|
||||||
if (!my_ctx) {
|
if (!my_ctx) {
|
||||||
pr_err("Invalid context\n");
|
pr_err("Invalid context\n");
|
||||||
@@ -161,6 +169,18 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
return FILLDIR_ACTOR_CONTINUE;
|
return FILLDIR_ACTOR_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = kern_path(dirpath, 0, &path);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
pr_err("get dirpath %s err: %d\n", dirpath, err);
|
||||||
|
return FILLDIR_ACTOR_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_ctx->root_sb != path.dentry->d_inode->i_sb) {
|
||||||
|
pr_info("skip cross fs: %s", dirpath);
|
||||||
|
return FILLDIR_ACTOR_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (d_type == DT_DIR && my_ctx->depth > 0 &&
|
if (d_type == DT_DIR && my_ctx->depth > 0 &&
|
||||||
(my_ctx->stop && !*my_ctx->stop)) {
|
(my_ctx->stop && !*my_ctx->stop)) {
|
||||||
struct data_path *data = kmalloc(sizeof(struct data_path), GFP_ATOMIC);
|
struct data_path *data = kmalloc(sizeof(struct data_path), GFP_ATOMIC);
|
||||||
@@ -170,7 +190,11 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
return FILLDIR_ACTOR_CONTINUE;
|
return FILLDIR_ACTOR_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
|
||||||
|
strlcpy(data->dirpath, dirpath, DATA_PATH_LEN);
|
||||||
|
#else
|
||||||
strscpy(data->dirpath, dirpath, DATA_PATH_LEN);
|
strscpy(data->dirpath, dirpath, DATA_PATH_LEN);
|
||||||
|
#endif
|
||||||
data->depth = my_ctx->depth - 1;
|
data->depth = my_ctx->depth - 1;
|
||||||
list_add_tail(&data->list, my_ctx->data_path_list);
|
list_add_tail(&data->list, my_ctx->data_path_list);
|
||||||
} else {
|
} else {
|
||||||
@@ -214,10 +238,19 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
|
|
||||||
void search_manager(const char *path, int depth, struct list_head *uid_data)
|
void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||||
{
|
{
|
||||||
int i, stop = 0;
|
int i, stop = 0, err;
|
||||||
struct list_head data_path_list;
|
struct list_head data_path_list;
|
||||||
|
struct path kpath;
|
||||||
|
struct super_block* root_sb;
|
||||||
INIT_LIST_HEAD(&data_path_list);
|
INIT_LIST_HEAD(&data_path_list);
|
||||||
|
|
||||||
|
err = kern_path(path, 0, &kpath);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
pr_err("get search root %s err: %d\n", path, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize APK cache list
|
// Initialize APK cache list
|
||||||
struct apk_path_hash *pos, *n;
|
struct apk_path_hash *pos, *n;
|
||||||
list_for_each_entry(pos, &apk_path_hash_list, list) {
|
list_for_each_entry(pos, &apk_path_hash_list, list) {
|
||||||
@@ -226,10 +259,16 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
|||||||
|
|
||||||
// First depth
|
// First depth
|
||||||
struct data_path data;
|
struct data_path data;
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
|
||||||
|
strlcpy(data.dirpath, path, DATA_PATH_LEN);
|
||||||
|
#else
|
||||||
strscpy(data.dirpath, path, DATA_PATH_LEN);
|
strscpy(data.dirpath, path, DATA_PATH_LEN);
|
||||||
|
#endif
|
||||||
data.depth = depth;
|
data.depth = depth;
|
||||||
list_add_tail(&data.list, &data_path_list);
|
list_add_tail(&data.list, &data_path_list);
|
||||||
|
|
||||||
|
root_sb = kpath.dentry->d_inode->i_sb;
|
||||||
|
|
||||||
for (i = depth; i >= 0; i--) {
|
for (i = depth; i >= 0; i--) {
|
||||||
struct data_path *pos, *n;
|
struct data_path *pos, *n;
|
||||||
|
|
||||||
@@ -239,7 +278,8 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
|||||||
.parent_dir = pos->dirpath,
|
.parent_dir = pos->dirpath,
|
||||||
.private_data = uid_data,
|
.private_data = uid_data,
|
||||||
.depth = pos->depth,
|
.depth = pos->depth,
|
||||||
.stop = &stop };
|
.stop = &stop,
|
||||||
|
.root_sb = root_sb };
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
if (!stop) {
|
if (!stop) {
|
||||||
@@ -284,7 +324,7 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
|
|||||||
return exist;
|
return exist;
|
||||||
}
|
}
|
||||||
|
|
||||||
void track_throne()
|
static void track_throne_function()
|
||||||
{
|
{
|
||||||
struct file *fp =
|
struct file *fp =
|
||||||
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
||||||
@@ -361,12 +401,14 @@ void track_throne()
|
|||||||
if (ksu_is_manager_uid_valid()) {
|
if (ksu_is_manager_uid_valid()) {
|
||||||
pr_info("manager is uninstalled, invalidate it!\n");
|
pr_info("manager is uninstalled, invalidate it!\n");
|
||||||
ksu_invalidate_manager_uid();
|
ksu_invalidate_manager_uid();
|
||||||
|
goto prune;
|
||||||
}
|
}
|
||||||
pr_info("Searching manager...\n");
|
pr_info("Searching manager...\n");
|
||||||
search_manager("/data/app", 2, &uid_list);
|
search_manager("/data/app", 2, &uid_list);
|
||||||
pr_info("Search manager finished\n");
|
pr_info("Search manager finished\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prune:
|
||||||
// then prune the allowlist
|
// then prune the allowlist
|
||||||
ksu_prune_allowlist(is_uid_exist, &uid_list);
|
ksu_prune_allowlist(is_uid_exist, &uid_list);
|
||||||
out:
|
out:
|
||||||
@@ -377,6 +419,23 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int throne_tracker_thread(void *data)
|
||||||
|
{
|
||||||
|
pr_info("%s: pid: %d started\n", __func__, current->pid);
|
||||||
|
track_throne_function();
|
||||||
|
throne_thread = NULL;
|
||||||
|
pr_info("%s: pid: %d exit!\n", __func__, current->pid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void track_throne()
|
||||||
|
{
|
||||||
|
throne_thread = kthread_run(throne_tracker_thread, NULL, "throne_tracker");
|
||||||
|
if (IS_ERR(throne_thread)) {
|
||||||
|
throne_thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ksu_throne_tracker_init()
|
void ksu_throne_tracker_init()
|
||||||
{
|
{
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
aidl = true
|
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
compose = true
|
compose = true
|
||||||
prefab = true
|
prefab = true
|
||||||
@@ -133,4 +132,9 @@ dependencies {
|
|||||||
implementation(libs.androidx.webkit)
|
implementation(libs.androidx.webkit)
|
||||||
|
|
||||||
implementation(libs.lsposed.cxx)
|
implementation(libs.lsposed.cxx)
|
||||||
|
|
||||||
|
implementation(libs.mmrl.platform)
|
||||||
|
compileOnly(libs.mmrl.hidden.api)
|
||||||
|
implementation(libs.mmrl.ui)
|
||||||
|
implementation(libs.mmrl.webui)
|
||||||
}
|
}
|
||||||
47
manager/app/proguard-rules.pro
vendored
47
manager/app/proguard-rules.pro
vendored
@@ -0,0 +1,47 @@
|
|||||||
|
-verbose
|
||||||
|
-optimizationpasses 5
|
||||||
|
|
||||||
|
-dontwarn org.conscrypt.**
|
||||||
|
-dontwarn kotlinx.serialization.**
|
||||||
|
|
||||||
|
# Please add these rules to your existing keep rules in order to suppress warnings.
|
||||||
|
# This is generated automatically by the Android Gradle plugin.
|
||||||
|
-dontwarn com.google.auto.service.AutoService
|
||||||
|
-dontwarn com.google.j2objc.annotations.RetainedWith
|
||||||
|
-dontwarn javax.lang.model.SourceVersion
|
||||||
|
-dontwarn javax.lang.model.element.AnnotationMirror
|
||||||
|
-dontwarn javax.lang.model.element.AnnotationValue
|
||||||
|
-dontwarn javax.lang.model.element.Element
|
||||||
|
-dontwarn javax.lang.model.element.ElementKind
|
||||||
|
-dontwarn javax.lang.model.element.ElementVisitor
|
||||||
|
-dontwarn javax.lang.model.element.ExecutableElement
|
||||||
|
-dontwarn javax.lang.model.element.Modifier
|
||||||
|
-dontwarn javax.lang.model.element.Name
|
||||||
|
-dontwarn javax.lang.model.element.PackageElement
|
||||||
|
-dontwarn javax.lang.model.element.TypeElement
|
||||||
|
-dontwarn javax.lang.model.element.TypeParameterElement
|
||||||
|
-dontwarn javax.lang.model.element.VariableElement
|
||||||
|
-dontwarn javax.lang.model.type.ArrayType
|
||||||
|
-dontwarn javax.lang.model.type.DeclaredType
|
||||||
|
-dontwarn javax.lang.model.type.ExecutableType
|
||||||
|
-dontwarn javax.lang.model.type.TypeKind
|
||||||
|
-dontwarn javax.lang.model.type.TypeMirror
|
||||||
|
-dontwarn javax.lang.model.type.TypeVariable
|
||||||
|
-dontwarn javax.lang.model.type.TypeVisitor
|
||||||
|
-dontwarn javax.lang.model.util.AbstractAnnotationValueVisitor8
|
||||||
|
-dontwarn javax.lang.model.util.AbstractTypeVisitor8
|
||||||
|
-dontwarn javax.lang.model.util.ElementFilter
|
||||||
|
-dontwarn javax.lang.model.util.Elements
|
||||||
|
-dontwarn javax.lang.model.util.SimpleElementVisitor8
|
||||||
|
-dontwarn javax.lang.model.util.SimpleTypeVisitor7
|
||||||
|
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
|
||||||
|
-dontwarn javax.lang.model.util.Types
|
||||||
|
-dontwarn javax.tools.Diagnostic$Kind
|
||||||
|
|
||||||
|
|
||||||
|
# MMRL:webui reflection
|
||||||
|
-keep class com.dergoogler.mmrl.webui.model.ModId { *; }
|
||||||
|
-keep class com.dergoogler.mmrl.webui.interfaces.** { *; }
|
||||||
|
-keep class com.rifsxd.ksunext.ui.webui.WebViewInterface { *; }
|
||||||
|
|
||||||
|
-keep,allowobfuscation class * extends com.dergoogler.mmrl.platform.content.IService { *; }
|
||||||
@@ -33,6 +33,13 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Theme.KernelSU.WebUI" />
|
android:theme="@style/Theme.KernelSU.WebUI" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.webui.WebUIXActivity"
|
||||||
|
android:autoRemoveFromRecents="true"
|
||||||
|
android:documentLaunchMode="intoExisting"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/Theme.KernelSU.WebUI" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
// IKsuInterface.aidl
|
|
||||||
package com.rifsxd.ksunext;
|
|
||||||
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import rikka.parcelablelist.ParcelableListSlice;
|
|
||||||
|
|
||||||
interface IKsuInterface {
|
|
||||||
ParcelableListSlice<PackageInfo> getPackages(int flags);
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,13 @@ Java_com_rifsxd_ksunext_Natives_getVersion(JNIEnv *env, jobject) {
|
|||||||
return get_version();
|
return get_version();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jstring JNICALL
|
||||||
|
Java_com_rifsxd_ksunext_Natives_getHookMode(JNIEnv *env, jobject) {
|
||||||
|
const char* mode = get_hook_mode();
|
||||||
|
return env->NewStringUTF(mode);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jintArray JNICALL
|
JNIEXPORT jintArray JNICALL
|
||||||
Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) {
|
Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) {
|
||||||
@@ -306,3 +313,8 @@ JNIEXPORT jboolean JNICALL
|
|||||||
Java_com_rifsxd_ksunext_Natives_setSuEnabled(JNIEnv *env, jobject thiz, jboolean enabled) {
|
Java_com_rifsxd_ksunext_Natives_setSuEnabled(JNIEnv *env, jobject thiz, jboolean enabled) {
|
||||||
return set_su_enabled(enabled);
|
return set_su_enabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_rifsxd_ksunext_Natives_isKPMEnabled(JNIEnv *env, jobject) {
|
||||||
|
return is_KPM_enable();
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#define CMD_IS_UID_SHOULD_UMOUNT 13
|
#define CMD_IS_UID_SHOULD_UMOUNT 13
|
||||||
#define CMD_IS_SU_ENABLED 14
|
#define CMD_IS_SU_ENABLED 14
|
||||||
#define CMD_ENABLE_SU 15
|
#define CMD_ENABLE_SU 15
|
||||||
|
#define CMD_HOOK_MODE 16
|
||||||
|
#define CMD_ENABLE_KPM 100
|
||||||
|
|
||||||
static bool ksuctl(int cmd, void* arg1, void* arg2) {
|
static bool ksuctl(int cmd, void* arg1, void* arg2) {
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
@@ -61,6 +63,12 @@ int get_version() {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* get_hook_mode() {
|
||||||
|
static char mode[16];
|
||||||
|
ksuctl(CMD_HOOK_MODE, mode, nullptr);
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
bool get_allow_list(int *uids, int *size) {
|
bool get_allow_list(int *uids, int *size) {
|
||||||
return ksuctl(CMD_GET_SU_LIST, uids, size);
|
return ksuctl(CMD_GET_SU_LIST, uids, size);
|
||||||
}
|
}
|
||||||
@@ -97,3 +105,8 @@ bool is_su_enabled() {
|
|||||||
ksuctl(CMD_IS_SU_ENABLED, &enabled, nullptr);
|
ksuctl(CMD_IS_SU_ENABLED, &enabled, nullptr);
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_KPM_enable() {
|
||||||
|
bool enabled = false;
|
||||||
|
return ksuctl(CMD_ENABLE_KPM, &enabled, nullptr), enabled;
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ bool become_manager(const char *);
|
|||||||
|
|
||||||
int get_version();
|
int get_version();
|
||||||
|
|
||||||
|
const char* get_hook_mode();
|
||||||
|
|
||||||
bool get_allow_list(int *uids, int *size);
|
bool get_allow_list(int *uids, int *size);
|
||||||
|
|
||||||
bool uid_should_umount(int uid);
|
bool uid_should_umount(int uid);
|
||||||
@@ -83,4 +85,6 @@ bool set_su_enabled(bool enabled);
|
|||||||
|
|
||||||
bool is_su_enabled();
|
bool is_su_enabled();
|
||||||
|
|
||||||
|
bool is_KPM_enable();
|
||||||
|
|
||||||
#endif //KERNELSU_KSU_H
|
#endif //KERNELSU_KSU_H
|
||||||
|
|||||||
@@ -4,12 +4,17 @@ import android.app.Application
|
|||||||
import android.system.Os
|
import android.system.Os
|
||||||
import coil.Coil
|
import coil.Coil
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
import me.zhanghai.android.appiconloader.coil.AppIconFetcher
|
import me.zhanghai.android.appiconloader.coil.AppIconFetcher
|
||||||
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
|
import me.zhanghai.android.appiconloader.coil.AppIconKeyer
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import com.rifsxd.ksunext.ui.webui.initPlatform
|
||||||
|
|
||||||
lateinit var ksuApp: KernelSUApplication
|
lateinit var ksuApp: KernelSUApplication
|
||||||
|
|
||||||
@@ -21,6 +26,11 @@ class KernelSUApplication : Application() {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
ksuApp = this
|
ksuApp = this
|
||||||
|
|
||||||
|
Platform.setHiddenApiExemptions()
|
||||||
|
|
||||||
|
// Pre-initialize WX Platform as early as possible
|
||||||
|
launchPlatformInit()
|
||||||
|
|
||||||
val context = this
|
val context = this
|
||||||
val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size)
|
val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size)
|
||||||
Coil.setImageLoader(
|
Coil.setImageLoader(
|
||||||
@@ -51,5 +61,11 @@ class KernelSUApplication : Application() {
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun launchPlatformInit() {
|
||||||
|
// Use a coroutine to avoid blocking the main thread
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
initPlatform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,19 @@ data class KernelVersion(val major: Int, val patchLevel: Int, val subLevel: Int)
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isULegacy(): Boolean {
|
||||||
|
return major == 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isLegacy(): Boolean {
|
||||||
|
return major == 4 && patchLevel in 1..18
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isGKI1(): Boolean {
|
||||||
|
return (major == 4 && patchLevel >= 19) || (major == 5 && patchLevel < 10)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseKernelVersion(version: String): KernelVersion {
|
fun parseKernelVersion(version: String): KernelVersion {
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ object Natives {
|
|||||||
|
|
||||||
// 12404: Support disable sucompat mode
|
// 12404: Support disable sucompat mode
|
||||||
const val MINIMAL_SUPPORTED_SU_COMPAT = 12404
|
const val MINIMAL_SUPPORTED_SU_COMPAT = 12404
|
||||||
|
|
||||||
|
// 12569: support get hook mode
|
||||||
|
const val MINIMAL_SUPPORTED_HOOK_MODE = 12569
|
||||||
|
|
||||||
const val KERNEL_SU_DOMAIN = "u:r:su:s0"
|
const val KERNEL_SU_DOMAIN = "u:r:su:s0"
|
||||||
|
|
||||||
const val ROOT_UID = 0
|
const val ROOT_UID = 0
|
||||||
@@ -50,6 +54,16 @@ object Natives {
|
|||||||
|
|
||||||
external fun uidShouldUmount(uid: Int): Boolean
|
external fun uidShouldUmount(uid: Int): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string indicating the SU hook mode enabled in kernel.
|
||||||
|
* The return values are:
|
||||||
|
* - "Manual": Manual hooks was enabled.
|
||||||
|
* - "Kprobes": Kprobes hooks was enabled (CONFIG_KSU_KPROBES_HOOK).
|
||||||
|
*
|
||||||
|
* @return return hook mode, or null if unavailable.
|
||||||
|
*/
|
||||||
|
external fun getHookMode(): String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the profile of the given package.
|
* Get the profile of the given package.
|
||||||
* @param key usually the package name
|
* @param key usually the package name
|
||||||
@@ -67,6 +81,12 @@ object Natives {
|
|||||||
external fun isSuEnabled(): Boolean
|
external fun isSuEnabled(): Boolean
|
||||||
external fun setSuEnabled(enabled: Boolean): Boolean
|
external fun setSuEnabled(enabled: Boolean): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the KPM (Kernel Package Manager) is enabled.
|
||||||
|
* @return true if KPM is enabled, false otherwise.
|
||||||
|
*/
|
||||||
|
external fun isKPMEnabled(): Boolean
|
||||||
|
|
||||||
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
|
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
|
||||||
private const val NOBODY_UID = 9999
|
private const val NOBODY_UID = 9999
|
||||||
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package com.rifsxd.ksunext.ui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.os.UserManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.topjohnwu.superuser.ipc.RootService;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.rifsxd.ksunext.IKsuInterface;
|
|
||||||
import rikka.parcelablelist.ParcelableListSlice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author weishu
|
|
||||||
* @date 2023/4/18.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class KsuService extends RootService {
|
|
||||||
|
|
||||||
private static final String TAG = "KsuService";
|
|
||||||
|
|
||||||
class Stub extends IKsuInterface.Stub {
|
|
||||||
@Override
|
|
||||||
public ParcelableListSlice<PackageInfo> getPackages(int flags) {
|
|
||||||
List<PackageInfo> list = getInstalledPackagesAll(flags);
|
|
||||||
Log.i(TAG, "getPackages: " + list.size());
|
|
||||||
return new ParcelableListSlice<>(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(@NonNull Intent intent) {
|
|
||||||
return new Stub();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Integer> getUserIds() {
|
|
||||||
List<Integer> result = new ArrayList<>();
|
|
||||||
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
|
|
||||||
List<UserHandle> userProfiles = um.getUserProfiles();
|
|
||||||
for (UserHandle userProfile : userProfiles) {
|
|
||||||
int userId = userProfile.hashCode();
|
|
||||||
result.add(userProfile.hashCode());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<PackageInfo> getInstalledPackagesAll(int flags) {
|
|
||||||
ArrayList<PackageInfo> packages = new ArrayList<>();
|
|
||||||
for (Integer userId : getUserIds()) {
|
|
||||||
Log.i(TAG, "getInstalledPackagesAll: " + userId);
|
|
||||||
packages.addAll(getInstalledPackagesAsUser(flags, userId));
|
|
||||||
}
|
|
||||||
return packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
|
|
||||||
try {
|
|
||||||
PackageManager pm = getPackageManager();
|
|
||||||
Method getInstalledPackagesAsUser = pm.getClass().getDeclaredMethod("getInstalledPackagesAsUser", int.class, int.class);
|
|
||||||
return (List<PackageInfo>) getInstalledPackagesAsUser.invoke(pm, flags, userId);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.e(TAG, "err", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.rifsxd.ksunext.ui
|
package com.rifsxd.ksunext.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
@@ -29,6 +30,7 @@ import androidx.compose.material3.SnackbarHostState
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -52,7 +54,6 @@ import com.rifsxd.ksunext.ui.theme.KernelSUTheme
|
|||||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||||
import com.rifsxd.ksunext.ui.util.rootAvailable
|
import com.rifsxd.ksunext.ui.util.rootAvailable
|
||||||
import com.rifsxd.ksunext.ui.util.install
|
import com.rifsxd.ksunext.ui.util.install
|
||||||
import com.rifsxd.ksunext.ui.util.*
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@@ -67,10 +68,16 @@ class MainActivity : ComponentActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
if (isManager) install()
|
if (isManager) install()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
KernelSUTheme {
|
// Read AMOLED mode preference
|
||||||
|
val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
val amoledMode = prefs.getBoolean("enable_amoled", false)
|
||||||
|
|
||||||
|
KernelSUTheme (
|
||||||
|
amoledMode = amoledMode
|
||||||
|
) {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val snackBarHostState = remember { SnackbarHostState() }
|
val snackBarHostState = remember { SnackbarHostState() }
|
||||||
val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination
|
val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination
|
||||||
|
|||||||
@@ -5,14 +5,18 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
|||||||
import androidx.compose.foundation.selection.toggleable
|
import androidx.compose.foundation.selection.toggleable
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.RadioButton
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import com.dergoogler.mmrl.ui.component.LabelItem
|
||||||
|
import com.dergoogler.mmrl.ui.component.text.TextRow
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SwitchItem(
|
fun SwitchItem(
|
||||||
@@ -21,9 +25,11 @@ fun SwitchItem(
|
|||||||
summary: String? = null,
|
summary: String? = null,
|
||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
onCheckedChange: (Boolean) -> Unit
|
beta: Boolean = false,
|
||||||
|
onCheckedChange: (Boolean) -> Unit,
|
||||||
) {
|
) {
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val stateAlpha = remember(checked, enabled) { Modifier.alpha(if (enabled) 1f else 0.5f) }
|
||||||
|
|
||||||
ListItem(
|
ListItem(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -36,10 +42,30 @@ fun SwitchItem(
|
|||||||
onValueChange = onCheckedChange
|
onValueChange = onCheckedChange
|
||||||
),
|
),
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(title)
|
TextRow(
|
||||||
|
leadingContent = if (beta) {
|
||||||
|
{
|
||||||
|
LabelItem(
|
||||||
|
modifier = Modifier.then(stateAlpha),
|
||||||
|
text = "Beta"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.then(stateAlpha),
|
||||||
|
text = title,
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
leadingContent = icon?.let {
|
leadingContent = icon?.let {
|
||||||
{ Icon(icon, title) }
|
{
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.then(stateAlpha),
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = title
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
Switch(
|
Switch(
|
||||||
@@ -51,7 +77,10 @@ fun SwitchItem(
|
|||||||
},
|
},
|
||||||
supportingContent = {
|
supportingContent = {
|
||||||
if (summary != null) {
|
if (summary != null) {
|
||||||
Text(summary)
|
Text(
|
||||||
|
modifier = Modifier.then(stateAlpha),
|
||||||
|
text = summary
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
package com.rifsxd.ksunext.ui.screen
|
package com.rifsxd.ksunext.ui.screen
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
@@ -25,7 +18,6 @@ import androidx.compose.material3.HorizontalDivider
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -37,54 +29,32 @@ import androidx.compose.material3.TopAppBarScrollBehavior
|
|||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.LineHeightStyle
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.lifecycle.compose.dropUnlessResumed
|
import androidx.lifecycle.compose.dropUnlessResumed
|
||||||
import com.maxkeppeker.sheets.core.models.base.Header
|
|
||||||
import com.maxkeppeker.sheets.core.models.base.IconSource
|
|
||||||
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
|
|
||||||
import com.maxkeppeler.sheets.list.ListDialog
|
|
||||||
import com.maxkeppeler.sheets.list.models.ListOption
|
|
||||||
import com.maxkeppeler.sheets.list.models.ListSelection
|
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import com.rifsxd.ksunext.BuildConfig
|
|
||||||
import com.rifsxd.ksunext.Natives
|
import com.rifsxd.ksunext.Natives
|
||||||
import com.rifsxd.ksunext.ksuApp
|
import com.rifsxd.ksunext.ksuApp
|
||||||
import com.rifsxd.ksunext.R
|
import com.rifsxd.ksunext.R
|
||||||
import com.rifsxd.ksunext.ui.component.AboutDialog
|
|
||||||
import com.rifsxd.ksunext.ui.component.ConfirmResult
|
import com.rifsxd.ksunext.ui.component.ConfirmResult
|
||||||
import com.rifsxd.ksunext.ui.component.DialogHandle
|
|
||||||
import com.rifsxd.ksunext.ui.component.SwitchItem
|
|
||||||
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
||||||
import com.rifsxd.ksunext.ui.component.rememberCustomDialog
|
|
||||||
import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
|
import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
|
||||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||||
import com.rifsxd.ksunext.ui.util.getBugreportFile
|
|
||||||
import com.rifsxd.ksunext.ui.util.*
|
import com.rifsxd.ksunext.ui.util.*
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author rifsxd
|
* @author rifsxd
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
package com.rifsxd.ksunext.ui.screen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.*
|
||||||
|
import androidx.compose.material.icons.filled.*
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SnackbarHost
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.lifecycle.compose.dropUnlessResumed
|
||||||
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
|
import com.rifsxd.ksunext.Natives
|
||||||
|
import com.rifsxd.ksunext.ksuApp
|
||||||
|
import com.rifsxd.ksunext.R
|
||||||
|
import com.rifsxd.ksunext.ui.component.SwitchItem
|
||||||
|
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||||
|
import com.rifsxd.ksunext.ui.util.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author rifsxd
|
||||||
|
* @date 2025/6/1.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Destination<RootGraph>
|
||||||
|
@Composable
|
||||||
|
fun CustomizationScreen(navigator: DestinationsNavigator) {
|
||||||
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
val snackBarHost = LocalSnackbarHost.current
|
||||||
|
|
||||||
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
|
val ksuVersion = if (isManager) Natives.version else null
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBar(
|
||||||
|
onBack = dropUnlessResumed {
|
||||||
|
navigator.popBackStack()
|
||||||
|
},
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
},
|
||||||
|
snackbarHost = { SnackbarHost(snackBarHost) },
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
|
) { paddingValues ->
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(paddingValues)
|
||||||
|
.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
var useLagacyUI by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getBoolean("use_legacyui", false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SwitchItem(
|
||||||
|
icon = Icons.Filled.Dashboard,
|
||||||
|
title = stringResource(id = R.string.settings_legacyui),
|
||||||
|
summary = stringResource(id = R.string.settings_legacyui_summary),
|
||||||
|
checked = useLagacyUI
|
||||||
|
) {
|
||||||
|
prefs.edit().putBoolean("use_legacyui", it).apply()
|
||||||
|
useLagacyUI = it
|
||||||
|
}
|
||||||
|
|
||||||
|
var useBanner by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getBoolean("use_banner", true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SwitchItem(
|
||||||
|
enabled = !useLagacyUI,
|
||||||
|
icon = Icons.Filled.ViewCarousel,
|
||||||
|
title = stringResource(id = R.string.settings_banner),
|
||||||
|
summary = stringResource(id = R.string.settings_banner_summary),
|
||||||
|
checked = useBanner
|
||||||
|
) {
|
||||||
|
prefs.edit().putBoolean("use_banner", it).apply()
|
||||||
|
useBanner = it
|
||||||
|
}
|
||||||
|
|
||||||
|
var enableAmoled by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getBoolean("enable_amoled", false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var showRestartDialog by remember { mutableStateOf(false) }
|
||||||
|
if (isSystemInDarkTheme()) {
|
||||||
|
SwitchItem(
|
||||||
|
icon = Icons.Filled.Contrast,
|
||||||
|
title = stringResource(id = R.string.settings_amoled_mode),
|
||||||
|
summary = stringResource(id = R.string.settings_amoled_mode_summary),
|
||||||
|
checked = enableAmoled
|
||||||
|
) { checked ->
|
||||||
|
prefs.edit().putBoolean("enable_amoled", checked).apply()
|
||||||
|
enableAmoled = checked
|
||||||
|
showRestartDialog = true
|
||||||
|
}
|
||||||
|
if (showRestartDialog) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { showRestartDialog = false },
|
||||||
|
title = { Text(stringResource(R.string.restart_required)) },
|
||||||
|
text = { Text(stringResource(R.string.restart_app_message)) },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = {
|
||||||
|
showRestartDialog = false
|
||||||
|
// Restart the app
|
||||||
|
val packageManager = context.packageManager
|
||||||
|
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
|
||||||
|
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
context.startActivity(intent)
|
||||||
|
Runtime.getRuntime().exit(0)
|
||||||
|
}) {
|
||||||
|
Text(stringResource(R.string.restart_app))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = { showRestartDialog = false }) {
|
||||||
|
Text(stringResource(R.string.later))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun TopBar(
|
||||||
|
onBack: () -> Unit = {},
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(stringResource(R.string.customization)) }, navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBack
|
||||||
|
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||||
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun CustomizationPreview() {
|
||||||
|
CustomizationScreen(EmptyDestinationsNavigator)
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.rifsxd.ksunext.ui.screen
|
package com.rifsxd.ksunext.ui.screen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -27,6 +28,7 @@ import androidx.compose.material3.SnackbarHost
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -34,8 +36,10 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.input.key.Key
|
import androidx.compose.ui.input.key.Key
|
||||||
import androidx.compose.ui.input.key.key
|
import androidx.compose.ui.input.key.key
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -67,6 +71,19 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String
|
|||||||
var actionResult: Boolean
|
var actionResult: Boolean
|
||||||
var isActionRunning by rememberSaveable { mutableStateOf(true) }
|
var isActionRunning by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
// Read developer options from SharedPreferences
|
||||||
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
|
||||||
|
|
||||||
|
val view = LocalView.current
|
||||||
|
DisposableEffect(isActionRunning) {
|
||||||
|
view.keepScreenOn = isActionRunning
|
||||||
|
onDispose {
|
||||||
|
view.keepScreenOn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BackHandler(enabled = isActionRunning) {
|
BackHandler(enabled = isActionRunning) {
|
||||||
// Disable back button if action is running
|
// Disable back button if action is running
|
||||||
}
|
}
|
||||||
@@ -148,7 +165,7 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String
|
|||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(8.dp),
|
modifier = Modifier.padding(8.dp),
|
||||||
text = text,
|
text = if (developerOptionsEnabled) logContent.toString() else text,
|
||||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.rifsxd.ksunext.ui.screen
|
package com.rifsxd.ksunext.ui.screen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
@@ -33,6 +34,7 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -44,6 +46,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.input.key.Key
|
import androidx.compose.ui.input.key.Key
|
||||||
import androidx.compose.ui.input.key.key
|
import androidx.compose.ui.input.key.key
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
@@ -117,6 +121,19 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
mutableStateOf(FlashingStatus.FLASHING)
|
mutableStateOf(FlashingStatus.FLASHING)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
|
||||||
|
|
||||||
|
val view = LocalView.current
|
||||||
|
DisposableEffect(flashing) {
|
||||||
|
view.keepScreenOn = flashing == FlashingStatus.FLASHING
|
||||||
|
onDispose {
|
||||||
|
view.keepScreenOn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BackHandler(enabled = flashing == FlashingStatus.FLASHING) {
|
BackHandler(enabled = flashing == FlashingStatus.FLASHING) {
|
||||||
// Disable back button if flashing is running
|
// Disable back button if flashing is running
|
||||||
}
|
}
|
||||||
@@ -199,14 +216,43 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flashIt is FlashIt.FlashBoot && (flashing == FlashingStatus.SUCCESS || flashing == FlashingStatus.FAILED)) {
|
if (flashIt is FlashIt.FlashBoot && (flashing == FlashingStatus.SUCCESS || flashing == FlashingStatus.FAILED)) {
|
||||||
// Close button for LKM flashing
|
val isLocalPatch = flashIt.boot != null && !flashIt.ota
|
||||||
ExtendedFloatingActionButton(
|
val isDirectOrOta = flashIt.boot == null || flashIt.ota
|
||||||
text = { Text(text = stringResource(R.string.close)) },
|
|
||||||
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
|
if (flashing == FlashingStatus.FAILED) {
|
||||||
onClick = {
|
// Always show close on failure
|
||||||
navigator.popBackStack()
|
ExtendedFloatingActionButton(
|
||||||
|
text = { Text(text = stringResource(R.string.close)) },
|
||||||
|
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
|
||||||
|
onClick = {
|
||||||
|
navigator.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if (flashing == FlashingStatus.SUCCESS) {
|
||||||
|
if (isLocalPatch) {
|
||||||
|
// Local patching: show only Close
|
||||||
|
ExtendedFloatingActionButton(
|
||||||
|
text = { Text(text = stringResource(R.string.close)) },
|
||||||
|
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
|
||||||
|
onClick = {
|
||||||
|
navigator.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if (isDirectOrOta) {
|
||||||
|
// Direct install or OTA inactive slot: show only Reboot
|
||||||
|
ExtendedFloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
scope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
reboot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon = { Icon(Icons.Filled.Refresh, contentDescription = stringResource(R.string.reboot)) },
|
||||||
|
text = { Text(text = stringResource(R.string.reboot)) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
contentWindowInsets = WindowInsets.safeDrawing,
|
contentWindowInsets = WindowInsets.safeDrawing,
|
||||||
@@ -227,7 +273,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(8.dp),
|
modifier = Modifier.padding(8.dp),
|
||||||
text = text,
|
text = if (developerOptionsEnabled) logContent.toString() else text,
|
||||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.os.PowerManager
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -29,9 +30,15 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.intl.Locale
|
||||||
|
import androidx.compose.ui.text.toUpperCase
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.dergoogler.mmrl.ui.component.LabelItem
|
||||||
|
import com.dergoogler.mmrl.ui.component.LabelItemDefaults
|
||||||
|
import com.dergoogler.mmrl.ui.component.text.TextRow
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
|
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
|
||||||
@@ -43,6 +50,8 @@ import com.rifsxd.ksunext.R
|
|||||||
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
||||||
import com.rifsxd.ksunext.ui.util.*
|
import com.rifsxd.ksunext.ui.util.*
|
||||||
import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo
|
import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo
|
||||||
|
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
|
||||||
|
import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -55,6 +64,10 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
val ksuVersion = if (isManager) Natives.version else null
|
val ksuVersion = if (isManager) Natives.version else null
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBar(
|
TopBar(
|
||||||
@@ -80,7 +93,25 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||||||
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null
|
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusCard(kernelVersion, ksuVersion, lkmMode) {
|
val superUserViewModel: SuperUserViewModel = viewModel()
|
||||||
|
|
||||||
|
val moduleViewModel: ModuleViewModel = viewModel()
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
if (superUserViewModel.appList.isEmpty()) {
|
||||||
|
superUserViewModel.fetchAppList()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moduleViewModel.moduleList.isEmpty()) {
|
||||||
|
moduleViewModel.fetchModuleList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val moduleUpdateCount = moduleViewModel.moduleList.count {
|
||||||
|
moduleViewModel.checkUpdate(it).first.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusCard(kernelVersion, ksuVersion, lkmMode, moduleUpdateCount) {
|
||||||
navigator.navigate(InstallScreenDestination)
|
navigator.navigate(InstallScreenDestination)
|
||||||
}
|
}
|
||||||
if (isManager && Natives.requireNewKernel()) {
|
if (isManager && Natives.requireNewKernel()) {
|
||||||
@@ -97,12 +128,12 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
val checkUpdate =
|
val checkUpdate =
|
||||||
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
.getBoolean("check_update", true)
|
.getBoolean("check_update", false)
|
||||||
if (checkUpdate) {
|
if (checkUpdate) {
|
||||||
UpdateCard()
|
UpdateCard()
|
||||||
}
|
}
|
||||||
//NextCard()
|
//NextCard()
|
||||||
InfoCard()
|
InfoCard(autoExpand = developerOptionsEnabled)
|
||||||
IssueReportCard()
|
IssueReportCard()
|
||||||
//EXperimentalCard()
|
//EXperimentalCard()
|
||||||
Spacer(Modifier)
|
Spacer(Modifier)
|
||||||
@@ -173,12 +204,14 @@ private fun TopBar(
|
|||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(stringResource(R.string.app_name)) },
|
title = { Text(stringResource(R.string.app_name)) },
|
||||||
actions = {
|
actions = {
|
||||||
if (kernelVersion.isGKI()) {
|
if (ksuVersion != null) {
|
||||||
IconButton(onClick = onInstallClick) {
|
if (kernelVersion.isGKI()) {
|
||||||
Icon(
|
IconButton(onClick = onInstallClick) {
|
||||||
imageVector = Icons.Filled.Archive,
|
Icon(
|
||||||
contentDescription = stringResource(id = R.string.install)
|
imageVector = Icons.Filled.Archive,
|
||||||
)
|
contentDescription = stringResource(id = R.string.install)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +221,7 @@ private fun TopBar(
|
|||||||
showDropdown = true
|
showDropdown = true
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.Refresh,
|
imageVector = Icons.Filled.PowerSettingsNew,
|
||||||
contentDescription = stringResource(id = R.string.reboot)
|
contentDescription = stringResource(id = R.string.reboot)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -197,7 +230,8 @@ private fun TopBar(
|
|||||||
}) {
|
}) {
|
||||||
RebootDropdownItem(id = R.string.reboot)
|
RebootDropdownItem(id = R.string.reboot)
|
||||||
|
|
||||||
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
val pm =
|
||||||
|
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
|
||||||
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
|
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
|
||||||
@@ -232,64 +266,113 @@ private fun StatusCard(
|
|||||||
kernelVersion: KernelVersion,
|
kernelVersion: KernelVersion,
|
||||||
ksuVersion: Int?,
|
ksuVersion: Int?,
|
||||||
lkmMode: Boolean?,
|
lkmMode: Boolean?,
|
||||||
|
moduleUpdateCount: Int = 0,
|
||||||
onClickInstall: () -> Unit = {}
|
onClickInstall: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var tapCount by remember { mutableStateOf(0) }
|
||||||
|
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
colors = CardDefaults.elevatedCardColors(containerColor = run {
|
colors = CardDefaults.elevatedCardColors(containerColor = run {
|
||||||
if (ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer
|
if (ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer
|
||||||
else MaterialTheme.colorScheme.errorContainer
|
else MaterialTheme.colorScheme.errorContainer
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
Row(modifier = Modifier
|
Row(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.clickable {
|
.fillMaxWidth()
|
||||||
if (kernelVersion.isGKI()) {
|
.clickable {
|
||||||
onClickInstall()
|
tapCount++
|
||||||
|
if (tapCount == 5) {
|
||||||
|
Toast.makeText(context, "What are you doing? 🤔", Toast.LENGTH_SHORT).show()
|
||||||
|
} else if (tapCount == 10) {
|
||||||
|
Toast.makeText(context, "Never gonna give you up! 💜", Toast.LENGTH_SHORT).show()
|
||||||
|
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||||
|
val intent = android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(url))
|
||||||
|
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
if (ksuVersion != null) {
|
||||||
|
context.startActivity(intent)
|
||||||
|
} else {
|
||||||
|
onClickInstall()
|
||||||
|
}
|
||||||
|
} else if (ksuVersion == null && kernelVersion.isGKI()) {
|
||||||
|
onClickInstall()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
when {
|
when {
|
||||||
ksuVersion != null -> {
|
ksuVersion != null -> {
|
||||||
val safeMode = when {
|
val workingMode = when {
|
||||||
Natives.isSafeMode -> " [${stringResource(id = R.string.safe_mode)}]"
|
lkmMode == true -> "LKM"
|
||||||
else -> ""
|
lkmMode == false || kernelVersion.isGKI() -> "GKI2"
|
||||||
|
lkmMode == null && kernelVersion.isULegacy() -> "U-LEGACY"
|
||||||
|
lkmMode == null && kernelVersion.isLegacy() -> "LEGACY"
|
||||||
|
lkmMode == null && kernelVersion.isGKI1() -> "GKI1"
|
||||||
|
else -> "NON-STANDARD"
|
||||||
}
|
}
|
||||||
|
|
||||||
val workingMode = when (lkmMode) {
|
|
||||||
null -> " <LTS>"
|
|
||||||
true -> " <LKM>"
|
|
||||||
else -> " <GKI>"
|
|
||||||
}
|
|
||||||
|
|
||||||
val workingText =
|
|
||||||
"${stringResource(id = R.string.home_working)}$workingMode$safeMode"
|
|
||||||
|
|
||||||
Icon(
|
Icon(
|
||||||
getSeasonalIcon(), // Use dynamic seasonal icon
|
getSeasonalIcon(), // Use dynamic seasonal icon
|
||||||
contentDescription = stringResource(R.string.home_working)
|
contentDescription = stringResource(R.string.home_working)
|
||||||
)
|
)
|
||||||
Column(Modifier.padding(start = 20.dp)) {
|
Column(
|
||||||
Text(
|
modifier = Modifier.padding(start = 20.dp),
|
||||||
text = workingText,
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
style = MaterialTheme.typography.titleMedium
|
) {
|
||||||
)
|
val labelStyle = LabelItemDefaults.style
|
||||||
Spacer(Modifier.height(4.dp))
|
TextRow(
|
||||||
|
trailingContent = {
|
||||||
|
LabelItem(
|
||||||
|
icon = if (Natives.isSafeMode) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
tint = labelStyle.contentColor,
|
||||||
|
imageVector = Icons.Filled.Security,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
text = workingMode,
|
||||||
|
style = labelStyle.textStyle.copy(color = labelStyle.contentColor),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.home_working),
|
||||||
|
style = MaterialTheme.typography.titleMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.home_working_version, ksuVersion),
|
text = stringResource(R.string.home_working_version, ksuVersion),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(
|
text = stringResource(
|
||||||
R.string.home_superuser_count, getSuperuserCount()
|
R.string.home_superuser_count, getSuperuserCount()
|
||||||
), style = MaterialTheme.typography.bodyMedium
|
), style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.home_module_count, getModuleCount()),
|
text = stringResource(R.string.home_module_count, getModuleCount()),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(4.dp))
|
|
||||||
|
if (moduleUpdateCount > 0) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_module_update_count, moduleUpdateCount),
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val suSFS = getSuSFS()
|
val suSFS = getSuSFS()
|
||||||
if (suSFS == "Supported") {
|
if (suSFS == "Supported") {
|
||||||
Text(
|
Text(
|
||||||
@@ -301,7 +384,7 @@ private fun StatusCard(
|
|||||||
}
|
}
|
||||||
|
|
||||||
kernelVersion.isGKI() -> {
|
kernelVersion.isGKI() -> {
|
||||||
Icon(Icons.Filled.AutoFixHigh, stringResource(R.string.home_not_installed))
|
Icon(Icons.Filled.Report, stringResource(R.string.home_not_installed))
|
||||||
Column(Modifier.padding(start = 20.dp)) {
|
Column(Modifier.padding(start = 20.dp)) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.home_not_installed),
|
text = stringResource(R.string.home_not_installed),
|
||||||
@@ -357,20 +440,20 @@ fun WarningCard(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun InfoCard() {
|
private fun InfoCard(autoExpand: Boolean = false) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
var useOverlayFs by rememberSaveable {
|
|
||||||
mutableStateOf(prefs.getBoolean("use_overlay_fs", false))
|
|
||||||
}
|
|
||||||
|
|
||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
val ksuVersion = if (isManager) Natives.version else null
|
val ksuVersion = if (isManager) Natives.version else null
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
useOverlayFs = prefs.getBoolean("use_overlay_fs", false)
|
|
||||||
|
LaunchedEffect(autoExpand) {
|
||||||
|
if (autoExpand) {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevatedCard {
|
ElevatedCard {
|
||||||
@@ -379,9 +462,6 @@ private fun InfoCard() {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp)
|
.padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp)
|
||||||
) {
|
) {
|
||||||
val contents = StringBuilder()
|
|
||||||
val uname = Os.uname()
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InfoCardItem(label: String, content: String, icon: Any? = null) {
|
fun InfoCardItem(label: String, content: String, icon: Any? = null) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
@@ -411,60 +491,103 @@ private fun InfoCard() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
InfoCardItem(
|
val managerVersion = getManagerVersion(context)
|
||||||
label = stringResource(R.string.home_kernel),
|
|
||||||
content = uname.release,
|
|
||||||
icon = painterResource(R.drawable.ic_linux),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
InfoCardItem(
|
|
||||||
label = stringResource(R.string.home_android),
|
|
||||||
content = "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})",
|
|
||||||
icon = Icons.Filled.Android,
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
val managerVersion = getManagerVersion(context)
|
|
||||||
InfoCardItem(
|
|
||||||
label = stringResource(R.string.home_manager_version),
|
|
||||||
content = "${managerVersion.first} (${managerVersion.second})",
|
|
||||||
icon = painterResource(R.drawable.ic_ksu_next),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
InfoCardItem(
|
|
||||||
label = stringResource(R.string.home_selinux_status),
|
|
||||||
content = getSELinuxStatus(),
|
|
||||||
icon = Icons.Filled.Security,
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
InfoCardItem(
|
|
||||||
label = stringResource(R.string.home_mount_system),
|
|
||||||
content = currentMountSystem().ifEmpty { stringResource(R.string.unavailable) },
|
|
||||||
icon = Icons.Filled.SettingsSuggest,
|
|
||||||
)
|
|
||||||
|
|
||||||
val suSFS = getSuSFS()
|
|
||||||
if (suSFS == "Supported") {
|
|
||||||
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
|
|
||||||
val susSUMode = if (isSUS_SU) {
|
|
||||||
val mode = susfsSUS_SU_Mode()
|
|
||||||
val modeString = if (mode == "2") stringResource(R.string.enabled) else stringResource(R.string.disabled)
|
|
||||||
"| SuS SU: $modeString"
|
|
||||||
} else ""
|
|
||||||
Spacer(Modifier.height(16.dp))
|
|
||||||
InfoCardItem(
|
InfoCardItem(
|
||||||
label = stringResource(R.string.home_susfs_version),
|
label = stringResource(R.string.home_manager_version),
|
||||||
content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
|
content = "${managerVersion.first} (${managerVersion.second})",
|
||||||
icon = painterResource(R.drawable.ic_sus),
|
icon = painterResource(R.drawable.ic_ksu_next),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (Natives.version >= Natives.MINIMAL_SUPPORTED_HOOK_MODE) {
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.hook_mode),
|
||||||
|
content = Natives.getHookMode() ?: stringResource(R.string.unavailable),
|
||||||
|
icon = Icons.Filled.Phishing,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ksuVersion != null) {
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_mount_system),
|
||||||
|
content = currentMountSystem().ifEmpty { stringResource(R.string.unavailable) },
|
||||||
|
icon = Icons.Filled.SettingsSuggest,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val suSFS = getSuSFS()
|
||||||
|
if (suSFS == "Supported") {
|
||||||
|
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
|
||||||
|
val susSUMode = if (isSUS_SU) {
|
||||||
|
val mode = susfsSUS_SU_Mode()
|
||||||
|
val modeString =
|
||||||
|
if (mode == "2") stringResource(R.string.enabled) else stringResource(R.string.disabled)
|
||||||
|
"| SuS SU: $modeString"
|
||||||
|
} else ""
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_susfs_version),
|
||||||
|
content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
|
||||||
|
icon = painterResource(R.drawable.ic_sus),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expanded) {
|
||||||
|
Spacer(Modifier.height(12.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { expanded = true },
|
||||||
|
modifier = Modifier.size(36.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.KeyboardArrowDown,
|
||||||
|
contentDescription = "Show more"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = expanded) {
|
||||||
|
val uname = Os.uname()
|
||||||
|
Column {
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_kernel),
|
||||||
|
content = "${uname.release} (${uname.machine})",
|
||||||
|
icon = painterResource(R.drawable.ic_linux),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_android),
|
||||||
|
content = "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})",
|
||||||
|
icon = Icons.Filled.Android,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_abi),
|
||||||
|
content = Build.SUPPORTED_ABIS.joinToString(", "),
|
||||||
|
icon = Icons.Filled.Memory,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
InfoCardItem(
|
||||||
|
label = stringResource(R.string.home_selinux_status),
|
||||||
|
content = getSELinuxStatus(),
|
||||||
|
icon = Icons.Filled.Security,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -477,12 +600,13 @@ fun NextCard() {
|
|||||||
|
|
||||||
ElevatedCard {
|
ElevatedCard {
|
||||||
|
|
||||||
Row(modifier = Modifier
|
Row(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.clickable {
|
.fillMaxWidth()
|
||||||
uriHandler.openUri(url)
|
.clickable {
|
||||||
}
|
uriHandler.openUri(url)
|
||||||
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
|
}
|
||||||
|
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
Column {
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.home_next_kernelsu),
|
text = stringResource(R.string.home_next_kernelsu),
|
||||||
@@ -506,13 +630,15 @@ fun EXperimentalCard() {
|
|||||||
|
|
||||||
ElevatedCard {
|
ElevatedCard {
|
||||||
|
|
||||||
Row(modifier = Modifier
|
Row(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
/*.clickable {
|
.fillMaxWidth()
|
||||||
uriHandler.openUri(url)
|
/*.clickable {
|
||||||
}
|
uriHandler.openUri(url)
|
||||||
*/
|
}
|
||||||
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
|
*/
|
||||||
|
.padding(24.dp), verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Column {
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.home_experimental_kernelsu),
|
text = stringResource(R.string.home_experimental_kernelsu),
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.FileUpload
|
import androidx.compose.material.icons.filled.FileUpload
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -30,6 +31,7 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.RadioButton
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
@@ -39,6 +41,7 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -77,6 +80,32 @@ import com.rifsxd.ksunext.ui.util.rootAvailable
|
|||||||
@Destination<RootGraph>
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun InstallScreen(navigator: DestinationsNavigator) {
|
fun InstallScreen(navigator: DestinationsNavigator) {
|
||||||
|
var showLkmWarning by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
|
if (showLkmWarning) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
showLkmWarning = false
|
||||||
|
navigator.popBackStack()
|
||||||
|
},
|
||||||
|
title = { Text(stringResource(R.string.warning)) },
|
||||||
|
text = { Text(stringResource(R.string.lkm_warning_message)) },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { showLkmWarning = false }) {
|
||||||
|
Text(stringResource(R.string.proceed))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = {
|
||||||
|
showLkmWarning = false
|
||||||
|
navigator.popBackStack()
|
||||||
|
}) {
|
||||||
|
Text(stringResource(R.string.cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
var installMethod by remember {
|
var installMethod by remember {
|
||||||
mutableStateOf<InstallMethod?>(null)
|
mutableStateOf<InstallMethod?>(null)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import android.widget.Toast
|
|||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -53,6 +54,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
import com.maxkeppeker.sheets.core.models.base.Header
|
import com.maxkeppeker.sheets.core.models.base.Header
|
||||||
import com.maxkeppeker.sheets.core.models.base.IconSource
|
import com.maxkeppeker.sheets.core.models.base.IconSource
|
||||||
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
|
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
|
||||||
@@ -64,6 +66,7 @@ import com.ramcosta.composedestinations.annotation.RootGraph
|
|||||||
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
|
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
|
||||||
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||||
import com.ramcosta.composedestinations.generated.destinations.BackupRestoreScreenDestination
|
import com.ramcosta.composedestinations.generated.destinations.BackupRestoreScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.CustomizationScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -228,7 +231,9 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
var showRebootDialog by remember { mutableStateOf(false) }
|
var showRebootDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (ksuVersion != null) {
|
val isOverlayAvailable = overlayFsAvailable()
|
||||||
|
|
||||||
|
if (ksuVersion != null && isOverlayAvailable) {
|
||||||
SwitchItem(
|
SwitchItem(
|
||||||
icon = Icons.Filled.Build,
|
icon = Icons.Filled.Build,
|
||||||
title = stringResource(id = R.string.use_overlay_fs),
|
title = stringResource(id = R.string.use_overlay_fs),
|
||||||
@@ -271,7 +276,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
var checkUpdate by rememberSaveable {
|
var checkUpdate by rememberSaveable {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
prefs.getBoolean("check_update", true)
|
prefs.getBoolean("check_update", false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SwitchItem(
|
SwitchItem(
|
||||||
@@ -319,23 +324,44 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ksuVersion != null) {
|
var useWebUIX by rememberSaveable {
|
||||||
val backupRestore = stringResource(id = R.string.backup_restore)
|
mutableStateOf(
|
||||||
ListItem(
|
prefs.getBoolean("use_webuix", true)
|
||||||
leadingContent = {
|
|
||||||
Icon(
|
|
||||||
Icons.Filled.Backup,
|
|
||||||
backupRestore
|
|
||||||
)
|
|
||||||
},
|
|
||||||
headlineContent = { Text(backupRestore) },
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
navigator.navigate(BackupRestoreScreenDestination)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (ksuVersion != null) {
|
||||||
|
SwitchItem(
|
||||||
|
beta = false,
|
||||||
|
enabled = Platform.isAlive,
|
||||||
|
icon = Icons.Filled.WebAsset,
|
||||||
|
title = stringResource(id = R.string.use_webuix),
|
||||||
|
summary = stringResource(id = R.string.use_webuix_summary),
|
||||||
|
checked = useWebUIX
|
||||||
|
) {
|
||||||
|
prefs.edit().putBoolean("use_webuix", it).apply()
|
||||||
|
useWebUIX = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var useWebUIXEruda by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getBoolean("use_webuix_eruda", false)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (ksuVersion != null) {
|
||||||
|
SwitchItem(
|
||||||
|
beta = false,
|
||||||
|
enabled = Platform.isAlive && useWebUIX && enableWebDebugging,
|
||||||
|
icon = Icons.Filled.FormatListNumbered,
|
||||||
|
title = stringResource(id = R.string.use_webuix_eruda),
|
||||||
|
summary = stringResource(id = R.string.use_webuix_eruda_summary),
|
||||||
|
checked = useWebUIXEruda
|
||||||
|
) {
|
||||||
|
prefs.edit().putBoolean("use_webuix_eruda", it).apply()
|
||||||
|
useWebUIXEruda = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (useOverlayFs) {
|
if (isOverlayAvailable && useOverlayFs) {
|
||||||
val shrink = stringResource(id = R.string.shrink_sparse_image)
|
val shrink = stringResource(id = R.string.shrink_sparse_image)
|
||||||
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
|
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
|
||||||
ListItem(
|
ListItem(
|
||||||
@@ -359,6 +385,35 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val customization = stringResource(id = R.string.customization)
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.Palette,
|
||||||
|
customization
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineContent = { Text(customization) },
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
navigator.navigate(CustomizationScreenDestination)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (ksuVersion != null) {
|
||||||
|
val backupRestore = stringResource(id = R.string.backup_restore)
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.Backup,
|
||||||
|
backupRestore
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineContent = { Text(backupRestore) },
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
navigator.navigate(BackupRestoreScreenDestination)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
|
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
|
||||||
if (lkmMode) {
|
if (lkmMode) {
|
||||||
@@ -496,7 +551,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
@Composable
|
@Composable
|
||||||
fun UninstallItem(
|
fun UninstallItem(
|
||||||
navigator: DestinationsNavigator,
|
navigator: DestinationsNavigator,
|
||||||
withLoading: suspend (suspend () -> Unit) -> Unit
|
withLoading: suspend (suspend () -> Unit) -> Unit,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -598,7 +653,7 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(
|
private fun TopBar(
|
||||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text(stringResource(R.string.settings)) },
|
title = { Text(stringResource(R.string.settings)) },
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import androidx.compose.material.icons.filled.MoreVert
|
|||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
@@ -24,6 +25,9 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
|
import com.dergoogler.mmrl.ui.component.LabelItem
|
||||||
|
import com.dergoogler.mmrl.ui.component.LabelItemDefaults
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination
|
import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination
|
||||||
@@ -43,7 +47,7 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
|
|||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
|
||||||
LaunchedEffect(key1 = navigator) {
|
LaunchedEffect(navigator) {
|
||||||
viewModel.search = ""
|
viewModel.search = ""
|
||||||
if (viewModel.appList.isEmpty()) {
|
if (viewModel.appList.isEmpty()) {
|
||||||
viewModel.fetchAppList()
|
viewModel.fetchAppList()
|
||||||
@@ -148,16 +152,35 @@ private fun AppItem(
|
|||||||
supportingContent = {
|
supportingContent = {
|
||||||
Column {
|
Column {
|
||||||
Text(app.packageName)
|
Text(app.packageName)
|
||||||
FlowRow {
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
FlowRow(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
if (app.allowSu) {
|
if (app.allowSu) {
|
||||||
LabelText(label = "ROOT")
|
LabelItem(
|
||||||
|
text = "ROOT",
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
if (Natives.uidShouldUmount(app.uid)) {
|
if (Natives.uidShouldUmount(app.uid)) {
|
||||||
LabelText(label = "UMOUNT")
|
LabelItem(
|
||||||
|
text = "UMOUNT",
|
||||||
|
style = LabelItemDefaults.style.copy(
|
||||||
|
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (app.hasCustomProfile) {
|
if (app.hasCustomProfile) {
|
||||||
LabelText(label = "CUSTOM")
|
LabelItem(
|
||||||
|
text = "CUSTOM",
|
||||||
|
style = LabelItemDefaults.style.copy(
|
||||||
|
containerColor = MaterialTheme.colorScheme.onTertiary,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ package com.rifsxd.ksunext.ui.theme
|
|||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
val YELLOW = Color(0xFFeed502)
|
val PRIMARY = Color(0xFF8AADF4) // Catppuccin Blue
|
||||||
val YELLOW_LIGHT = Color(0xFFffff52)
|
val PRIMARY_LIGHT = Color(0xFFB7BDF8) // Catppuccin Lavender
|
||||||
val SECONDARY_LIGHT = Color(0xffa9817f)
|
val SECONDARY_LIGHT = Color(0xFFA6DA95) // Catppuccin Green
|
||||||
|
|
||||||
val YELLOW_DARK = Color(0xFFb7a400)
|
val PRIMARY_DARK = Color(0xFF7DC4E4) // Catppuccin Sky
|
||||||
val SECONDARY_DARK = Color(0xFF4c2b2b)
|
val SECONDARY_DARK = Color(0xFFF5BDE6) // Catppuccin Pink
|
||||||
|
|
||||||
|
val AMOLED_BLACK = Color(0xFF000000) // Pure black for AMOLED
|
||||||
|
|
||||||
|
val DARK_PURPLE = Color(0xFF6E6CB6) // Catppuccin Mauve (dark purple)
|
||||||
|
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.rifsxd.ksunext.ui.theme
|
package com.rifsxd.ksunext.ui.theme
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.activity.SystemBarStyle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.darkColorScheme
|
import androidx.compose.material3.darkColorScheme
|
||||||
@@ -8,39 +11,112 @@ import androidx.compose.material3.dynamicDarkColorScheme
|
|||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
private val DarkColorScheme = darkColorScheme(
|
||||||
primary = YELLOW,
|
primary = PRIMARY,
|
||||||
secondary = YELLOW_DARK,
|
secondary = PRIMARY_DARK,
|
||||||
tertiary = SECONDARY_DARK
|
tertiary = SECONDARY_DARK
|
||||||
)
|
)
|
||||||
|
|
||||||
private val LightColorScheme = lightColorScheme(
|
private val LightColorScheme = lightColorScheme(
|
||||||
primary = YELLOW,
|
primary = PRIMARY,
|
||||||
secondary = YELLOW_LIGHT,
|
secondary = PRIMARY_LIGHT,
|
||||||
tertiary = SECONDARY_LIGHT
|
tertiary = SECONDARY_LIGHT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun Color.blend(other: Color, ratio: Float): Color {
|
||||||
|
val inverse = 1f - ratio
|
||||||
|
return Color(
|
||||||
|
red = red * inverse + other.red * ratio,
|
||||||
|
green = green * inverse + other.green * ratio,
|
||||||
|
blue = blue * inverse + other.blue * ratio,
|
||||||
|
alpha = alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun KernelSUTheme(
|
fun KernelSUTheme(
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
// Dynamic color is available on Android 12+
|
// Dynamic color is available on Android 12+
|
||||||
dynamicColor: Boolean = true,
|
dynamicColor: Boolean = true,
|
||||||
|
amoledMode: Boolean = false,
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val colorScheme = when {
|
val colorScheme = when {
|
||||||
|
amoledMode && darkTheme && dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dynamicScheme = dynamicDarkColorScheme(context)
|
||||||
|
dynamicScheme.copy(
|
||||||
|
background = AMOLED_BLACK,
|
||||||
|
surface = AMOLED_BLACK,
|
||||||
|
surfaceVariant = dynamicScheme.surfaceVariant.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
surfaceContainer = dynamicScheme.surfaceContainer.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
surfaceContainerLow = dynamicScheme.surfaceContainerLow.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
surfaceContainerLowest = dynamicScheme.surfaceContainerLowest.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
surfaceContainerHigh = dynamicScheme.surfaceContainerHigh.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
surfaceContainerHighest = dynamicScheme.surfaceContainerHighest.blend(AMOLED_BLACK, 0.6f),
|
||||||
|
)
|
||||||
|
}
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||||
}
|
}
|
||||||
|
amoledMode && darkTheme -> {
|
||||||
|
DarkColorScheme.copy(
|
||||||
|
background = AMOLED_BLACK,
|
||||||
|
surface = AMOLED_BLACK,
|
||||||
|
surfaceVariant = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
surfaceContainer = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
surfaceContainerLow = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
surfaceContainerLowest = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
surfaceContainerHigh = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
surfaceContainerHighest = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
|
||||||
|
)
|
||||||
|
}
|
||||||
darkTheme -> DarkColorScheme
|
darkTheme -> DarkColorScheme
|
||||||
else -> LightColorScheme
|
else -> LightColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemBarStyle(
|
||||||
|
darkMode = darkTheme
|
||||||
|
)
|
||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
typography = Typography,
|
typography = Typography,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SystemBarStyle(
|
||||||
|
darkMode: Boolean,
|
||||||
|
statusBarScrim: Color = Color.Transparent,
|
||||||
|
navigationBarScrim: Color = Color.Transparent,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val activity = context as ComponentActivity
|
||||||
|
|
||||||
|
SideEffect {
|
||||||
|
activity.enableEdgeToEdge(
|
||||||
|
statusBarStyle = SystemBarStyle.auto(
|
||||||
|
statusBarScrim.toArgb(),
|
||||||
|
statusBarScrim.toArgb(),
|
||||||
|
) { darkMode },
|
||||||
|
navigationBarStyle = when {
|
||||||
|
darkMode -> SystemBarStyle.dark(
|
||||||
|
navigationBarScrim.toArgb()
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> SystemBarStyle.light(
|
||||||
|
navigationBarScrim.toArgb(),
|
||||||
|
navigationBarScrim.toArgb(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,9 +97,9 @@ fun createRootShell(globalMnt: Boolean = false): Shell {
|
|||||||
Log.w(TAG, "ksu failed: ", e)
|
Log.w(TAG, "ksu failed: ", e)
|
||||||
try {
|
try {
|
||||||
if (globalMnt) {
|
if (globalMnt) {
|
||||||
builder.build("su")
|
|
||||||
} else {
|
|
||||||
builder.build("su", "-mm")
|
builder.build("su", "-mm")
|
||||||
|
} else {
|
||||||
|
builder.build("su")
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Log.e(TAG, "su failed: ", e)
|
Log.e(TAG, "su failed: ", e)
|
||||||
@@ -443,7 +443,7 @@ fun getFileName(context: Context, uri: Uri): String {
|
|||||||
|
|
||||||
fun moduleBackupDir(): String? {
|
fun moduleBackupDir(): String? {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val baseBackupDir = "/data/adb/ksu/modules_bak"
|
val baseBackupDir = "/sdcard/.ksunext/modules"
|
||||||
val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim()
|
val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim()
|
||||||
if (resultBase.isNotEmpty()) return null
|
if (resultBase.isNotEmpty()) return null
|
||||||
|
|
||||||
@@ -462,60 +462,42 @@ fun moduleBackup(): Boolean {
|
|||||||
|
|
||||||
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/modules)\" ]; then echo 'empty'; fi"
|
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/modules)\" ]; then echo 'empty'; fi"
|
||||||
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
|
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
|
||||||
|
|
||||||
if (resultCheckEmpty == "empty") {
|
if (resultCheckEmpty == "empty") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupDir = moduleBackupDir() ?: return false
|
val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
|
||||||
val command = "cp -rp /data/adb/modules/* $backupDir"
|
if (timestamp.isEmpty()) return false
|
||||||
val result = ShellUtils.fastCmd(shell, command).trim()
|
|
||||||
|
|
||||||
return result.isEmpty()
|
val tarName = "modules_backup_$timestamp.tar"
|
||||||
}
|
val tarPath = "/data/local/tmp/$tarName"
|
||||||
|
val internalBackupDir = "/sdcard/.ksunext/modules"
|
||||||
|
val internalBackupPath = "$internalBackupDir/$tarName"
|
||||||
|
|
||||||
fun moduleMigration(): Boolean {
|
val tarCmd = "tar -cpf $tarPath -C /data/adb/modules $(ls /data/adb/modules)"
|
||||||
val shell = getRootShell()
|
val tarResult = ShellUtils.fastCmd(shell, tarCmd).trim()
|
||||||
val command = "cp -rp /data/adb/modules/* /data/adb/modules_update"
|
if (tarResult.isNotEmpty()) return false
|
||||||
val result = ShellUtils.fastCmd(shell, command).trim()
|
|
||||||
|
|
||||||
return result.isEmpty()
|
ShellUtils.fastCmd(shell, "mkdir -p $internalBackupDir")
|
||||||
|
|
||||||
|
val cpResult = ShellUtils.fastCmd(shell, "cp $tarPath $internalBackupPath").trim()
|
||||||
|
if (cpResult.isNotEmpty()) return false
|
||||||
|
|
||||||
|
ShellUtils.fastCmd(shell, "rm -f $tarPath")
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moduleRestore(): Boolean {
|
fun moduleRestore(): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
|
|
||||||
val command = "ls -t /data/adb/ksu/modules_bak | head -n 1"
|
val findTarCmd = "ls -t /sdcard/.ksunext/modules/modules_backup_*.tar 2>/dev/null | head -n 1"
|
||||||
val latestBackupDir = ShellUtils.fastCmd(shell, command).trim()
|
val tarPath = ShellUtils.fastCmd(shell, findTarCmd).trim()
|
||||||
|
if (tarPath.isEmpty()) return false
|
||||||
|
|
||||||
if (latestBackupDir.isEmpty()) return false
|
val extractCmd = "tar -xpf $tarPath -C /data/adb/modules_update"
|
||||||
|
val extractResult = ShellUtils.fastCmd(shell, extractCmd).trim()
|
||||||
val sourceDir = "/data/adb/ksu/modules_bak/$latestBackupDir"
|
return extractResult.isEmpty()
|
||||||
val destinationDir = "/data/adb/modules_update"
|
|
||||||
|
|
||||||
val createDestDirCommand = "mkdir -p $destinationDir"
|
|
||||||
ShellUtils.fastCmd(shell, createDestDirCommand)
|
|
||||||
|
|
||||||
val moveCommand = "cp -rp $sourceDir/* $destinationDir"
|
|
||||||
val result = ShellUtils.fastCmd(shell, moveCommand).trim()
|
|
||||||
|
|
||||||
return result.isEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allowlistBackupDir(): String? {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val baseBackupDir = "/data/adb/ksu/allowlist_bak"
|
|
||||||
val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim()
|
|
||||||
if (resultBase.isNotEmpty()) return null
|
|
||||||
|
|
||||||
val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
|
|
||||||
if (timestamp.isEmpty()) return null
|
|
||||||
|
|
||||||
val newBackupDir = "$baseBackupDir/$timestamp"
|
|
||||||
val resultNewDir = ShellUtils.fastCmd(shell, "mkdir -p $newBackupDir").trim()
|
|
||||||
|
|
||||||
if (resultNewDir.isEmpty()) return newBackupDir
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allowlistBackup(): Boolean {
|
fun allowlistBackup(): Boolean {
|
||||||
@@ -523,34 +505,50 @@ fun allowlistBackup(): Boolean {
|
|||||||
|
|
||||||
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/ksu/.allowlist)\" ]; then echo 'empty'; fi"
|
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/ksu/.allowlist)\" ]; then echo 'empty'; fi"
|
||||||
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
|
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
|
||||||
|
|
||||||
if (resultCheckEmpty == "empty") {
|
if (resultCheckEmpty == "empty") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupDir = allowlistBackupDir() ?: return false
|
val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
|
||||||
val command = "cp -rp /data/adb/ksu/.allowlist $backupDir"
|
if (timestamp.isEmpty()) return false
|
||||||
val result = ShellUtils.fastCmd(shell, command).trim()
|
|
||||||
|
|
||||||
return result.isEmpty()
|
val tarName = "allowlist_backup_$timestamp.tar"
|
||||||
|
val tarPath = "/data/local/tmp/$tarName"
|
||||||
|
val internalBackupDir = "/sdcard/.ksunext/allowlist"
|
||||||
|
val internalBackupPath = "$internalBackupDir/$tarName"
|
||||||
|
|
||||||
|
val tarCmd = "tar -cpf $tarPath -C /data/adb/ksu .allowlist"
|
||||||
|
val tarResult = ShellUtils.fastCmd(shell, tarCmd).trim()
|
||||||
|
if (tarResult.isNotEmpty()) return false
|
||||||
|
|
||||||
|
ShellUtils.fastCmd(shell, "mkdir -p $internalBackupDir")
|
||||||
|
|
||||||
|
val cpResult = ShellUtils.fastCmd(shell, "cp $tarPath $internalBackupPath").trim()
|
||||||
|
if (cpResult.isNotEmpty()) return false
|
||||||
|
|
||||||
|
ShellUtils.fastCmd(shell, "rm -f $tarPath")
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allowlistRestore(): Boolean {
|
fun allowlistRestore(): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
|
|
||||||
val command = "ls -t /data/adb/ksu/allowlist_bak | head -n 1"
|
// Find the latest allowlist tar backup in /sdcard/.ksunext/allowlist
|
||||||
val latestBackupDir = ShellUtils.fastCmd(shell, command).trim()
|
val findTarCmd = "ls -t /sdcard/.ksunext/allowlist/allowlist_backup_*.tar 2>/dev/null | head -n 1"
|
||||||
|
val tarPath = ShellUtils.fastCmd(shell, findTarCmd).trim()
|
||||||
|
if (tarPath.isEmpty()) return false
|
||||||
|
|
||||||
if (latestBackupDir.isEmpty()) return false
|
// Extract the tar to /data/adb/ksu (restores .allowlist folder with permissions)
|
||||||
|
val extractCmd = "tar -xpf $tarPath -C /data/adb/ksu"
|
||||||
|
val extractResult = ShellUtils.fastCmd(shell, extractCmd).trim()
|
||||||
|
return extractResult.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
val sourceDir = "/data/adb/ksu/allowlist_bak/$latestBackupDir"
|
fun moduleMigration(): Boolean {
|
||||||
val destinationDir = "/data/adb/ksu/"
|
val shell = getRootShell()
|
||||||
|
val command = "cp -rp /data/adb/modules/* /data/adb/modules_update"
|
||||||
val createDestDirCommand = "mkdir -p $destinationDir"
|
val result = ShellUtils.fastCmd(shell, command).trim()
|
||||||
ShellUtils.fastCmd(shell, createDestDirCommand)
|
|
||||||
|
|
||||||
val moveCommand = "cp -rp $sourceDir/.allowlist $destinationDir"
|
|
||||||
val result = ShellUtils.fastCmd(shell, moveCommand).trim()
|
|
||||||
|
|
||||||
return result.isEmpty()
|
return result.isEmpty()
|
||||||
}
|
}
|
||||||
@@ -607,6 +605,13 @@ fun currentMountSystem(): String {
|
|||||||
return result.substringAfter(":").substringAfter(" ").trim()
|
return result.substringAfter(":").substringAfter(" ").trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getModuleSize(dir: File): Long {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "du -sb '${dir.absolutePath}' | awk '{print \$1}'"
|
||||||
|
val result = ShellUtils.fastCmd(shell, cmd).trim()
|
||||||
|
return result.toLongOrNull() ?: 0L
|
||||||
|
}
|
||||||
|
|
||||||
fun setAppProfileTemplate(id: String, template: String): Boolean {
|
fun setAppProfileTemplate(id: String, template: String): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val escapedTemplate = template.replace("\"", "\\\"")
|
val escapedTemplate = template.replace("\"", "\\\"")
|
||||||
@@ -641,3 +646,71 @@ fun restartApp(packageName: String) {
|
|||||||
forceStopApp(packageName)
|
forceStopApp(packageName)
|
||||||
launchApp(packageName)
|
launchApp(packageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getKpmmgrPath(): String {
|
||||||
|
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libkpmmgr.so"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun loadKpmModule(path: String, args: String? = null): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}"
|
||||||
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unloadKpmModule(name: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} unload $name"
|
||||||
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmModuleCount(): Int {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} num"
|
||||||
|
val result = ShellUtils.fastCmd(shell, cmd)
|
||||||
|
return result.trim().toIntOrNull() ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runCmd(shell : Shell, cmd : String) : String {
|
||||||
|
return shell.newJob()
|
||||||
|
.add(cmd)
|
||||||
|
.to(mutableListOf<String>(), null)
|
||||||
|
.exec().out
|
||||||
|
.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun listKpmModules(): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} list"
|
||||||
|
return try {
|
||||||
|
runCmd(shell, cmd).trim()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to list KPM modules", e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmModuleInfo(name: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} info $name"
|
||||||
|
return try {
|
||||||
|
runCmd(shell, cmd).trim()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to get KPM module info: $name", e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun controlKpmModule(name: String, args: String? = null): Int {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = """${getKpmmgrPath()} control $name "${args ?: ""}""""
|
||||||
|
val result = runCmd(shell, cmd)
|
||||||
|
return result.trim().toIntOrNull() ?: -1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmVersion(): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKpmmgrPath()} version"
|
||||||
|
val result = ShellUtils.fastCmd(shell, cmd)
|
||||||
|
return result.trim()
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,14 +8,20 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
|
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import java.io.File
|
||||||
import java.text.Collator
|
import java.text.Collator
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import com.rifsxd.ksunext.ksuApp
|
import com.rifsxd.ksunext.ksuApp
|
||||||
import com.rifsxd.ksunext.ui.util.HanziToPinyin
|
import com.rifsxd.ksunext.ui.util.HanziToPinyin
|
||||||
import com.rifsxd.ksunext.ui.util.listModules
|
import com.rifsxd.ksunext.ui.util.listModules
|
||||||
import com.rifsxd.ksunext.ui.util.overlayFsAvailable
|
import com.rifsxd.ksunext.ui.util.getModuleSize
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
@@ -39,7 +45,9 @@ class ModuleViewModel : ViewModel() {
|
|||||||
val updateJson: String,
|
val updateJson: String,
|
||||||
val hasWebUi: Boolean,
|
val hasWebUi: Boolean,
|
||||||
val hasActionScript: Boolean,
|
val hasActionScript: Boolean,
|
||||||
val dirId: String
|
val dirId: String,
|
||||||
|
val size: Long,
|
||||||
|
val banner: String
|
||||||
)
|
)
|
||||||
|
|
||||||
data class ModuleUpdateInfo(
|
data class ModuleUpdateInfo(
|
||||||
@@ -49,9 +57,6 @@ class ModuleViewModel : ViewModel() {
|
|||||||
val changelog: String,
|
val changelog: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
|
|
||||||
private set
|
|
||||||
|
|
||||||
var isRefreshing by mutableStateOf(false)
|
var isRefreshing by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@@ -59,11 +64,15 @@ class ModuleViewModel : ViewModel() {
|
|||||||
|
|
||||||
var sortAToZ by mutableStateOf(false)
|
var sortAToZ by mutableStateOf(false)
|
||||||
var sortZToA by mutableStateOf(false)
|
var sortZToA by mutableStateOf(false)
|
||||||
|
var sortSizeLowToHigh by mutableStateOf(false)
|
||||||
|
var sortSizeHighToLow by mutableStateOf(false)
|
||||||
|
|
||||||
val moduleList by derivedStateOf {
|
val moduleList by derivedStateOf {
|
||||||
val comparator = when {
|
val comparator = when {
|
||||||
sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() }
|
sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() }
|
||||||
sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() }
|
sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() }
|
||||||
|
sortSizeLowToHigh -> compareBy<ModuleInfo> { it.size }
|
||||||
|
sortSizeHighToLow -> compareByDescending<ModuleInfo> { it.size }
|
||||||
else -> compareBy<ModuleInfo> { it.dirId }
|
else -> compareBy<ModuleInfo> { it.dirId }
|
||||||
}.thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
|
}.thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
|
||||||
|
|
||||||
@@ -85,57 +94,80 @@ class ModuleViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun fetchModuleList() {
|
fun fetchModuleList() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
isRefreshing = true
|
|
||||||
|
|
||||||
val oldModuleList = modules
|
viewModelScope.launch {
|
||||||
|
|
||||||
val start = SystemClock.elapsedRealtime()
|
withContext(Dispatchers.Main) {
|
||||||
|
isRefreshing = true
|
||||||
kotlin.runCatching {
|
|
||||||
isOverlayAvailable = overlayFsAvailable()
|
|
||||||
|
|
||||||
val result = listModules()
|
|
||||||
|
|
||||||
Log.i(TAG, "result: $result")
|
|
||||||
|
|
||||||
val array = JSONArray(result)
|
|
||||||
modules = (0 until array.length())
|
|
||||||
.asSequence()
|
|
||||||
.map { array.getJSONObject(it) }
|
|
||||||
.map { obj ->
|
|
||||||
ModuleInfo(
|
|
||||||
obj.getString("id"),
|
|
||||||
obj.optString("name"),
|
|
||||||
obj.optString("author", "Unknown"),
|
|
||||||
obj.optString("version", "Unknown"),
|
|
||||||
obj.optInt("versionCode", 0),
|
|
||||||
obj.optString("description"),
|
|
||||||
obj.getBoolean("enabled"),
|
|
||||||
obj.getBoolean("update"),
|
|
||||||
obj.getBoolean("remove"),
|
|
||||||
obj.optString("updateJson"),
|
|
||||||
obj.optBoolean("web"),
|
|
||||||
obj.optBoolean("action"),
|
|
||||||
obj.getString("dir_id")
|
|
||||||
)
|
|
||||||
}.toList()
|
|
||||||
isNeedRefresh = false
|
|
||||||
}.onFailure { e ->
|
|
||||||
Log.e(TAG, "fetchModuleList: ", e)
|
|
||||||
isRefreshing = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// when both old and new is kotlin.collections.EmptyList
|
withContext(Dispatchers.IO) {
|
||||||
// moduleList update will don't trigger
|
withTimeoutOrNull(TIMEOUT_MILLIS) {
|
||||||
if (oldModuleList === modules) {
|
while (!Platform.isAlive) {
|
||||||
isRefreshing = false
|
delay(500)
|
||||||
}
|
}
|
||||||
|
} ?: run {
|
||||||
|
isRefreshing = false
|
||||||
|
Log.e(TAG, "Platform is not alive, aborting fetchModuleList")
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}, modules: $modules")
|
val start = SystemClock.elapsedRealtime()
|
||||||
|
val oldModuleList = modules
|
||||||
|
|
||||||
|
kotlin.runCatching {
|
||||||
|
val result = listModules()
|
||||||
|
Log.i(TAG, "result: $result")
|
||||||
|
|
||||||
|
val array = JSONArray(result)
|
||||||
|
modules = (0 until array.length())
|
||||||
|
.asSequence()
|
||||||
|
.map { array.getJSONObject(it) }
|
||||||
|
.map { obj ->
|
||||||
|
val id = obj.getString("id")
|
||||||
|
val dirId = obj.getString("dir_id")
|
||||||
|
val moduleDir = File("/data/adb/modules/$dirId")
|
||||||
|
val size = getModuleSize(moduleDir)
|
||||||
|
|
||||||
|
ModuleInfo(
|
||||||
|
id,
|
||||||
|
obj.optString("name"),
|
||||||
|
obj.optString("author", "Unknown"),
|
||||||
|
obj.optString("version", "Unknown"),
|
||||||
|
obj.optInt("versionCode", 0),
|
||||||
|
obj.optString("description"),
|
||||||
|
obj.getBoolean("enabled"),
|
||||||
|
obj.getBoolean("update"),
|
||||||
|
obj.getBoolean("remove"),
|
||||||
|
obj.optString("updateJson"),
|
||||||
|
obj.optBoolean("web"),
|
||||||
|
obj.optBoolean("action"),
|
||||||
|
dirId,
|
||||||
|
size,
|
||||||
|
obj.optString("banner")
|
||||||
|
)
|
||||||
|
}.toList()
|
||||||
|
isNeedRefresh = false
|
||||||
|
}.onFailure { e ->
|
||||||
|
Log.e(TAG, "fetchModuleList: ", e)
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// when both old and new is kotlin.collections.EmptyList
|
||||||
|
// moduleList update will don't trigger
|
||||||
|
if (oldModuleList === modules) {
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}, modules: $modules")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sanitizeVersionString(version: String): String {
|
||||||
|
return version.replace(Regex("[^a-zA-Z0-9.\\-_]"), "_")
|
||||||
|
}
|
||||||
|
|
||||||
fun checkUpdate(m: ModuleInfo): Triple<String, String, String> {
|
fun checkUpdate(m: ModuleInfo): Triple<String, String, String> {
|
||||||
val empty = Triple("", "", "")
|
val empty = Triple("", "", "")
|
||||||
if (m.updateJson.isEmpty() || m.remove || m.update || !m.enabled) {
|
if (m.updateJson.isEmpty() || m.remove || m.update || !m.enabled) {
|
||||||
@@ -165,7 +197,8 @@ class ModuleViewModel : ViewModel() {
|
|||||||
JSONObject(result)
|
JSONObject(result)
|
||||||
}.getOrNull() ?: return empty
|
}.getOrNull() ?: return empty
|
||||||
|
|
||||||
val version = updateJson.optString("version", "")
|
var version = updateJson.optString("version", "")
|
||||||
|
version = sanitizeVersionString(version)
|
||||||
val versionCode = updateJson.optInt("versionCode", 0)
|
val versionCode = updateJson.optInt("versionCode", 0)
|
||||||
val zipUrl = updateJson.optString("zipUrl", "")
|
val zipUrl = updateJson.optString("zipUrl", "")
|
||||||
val changelog = updateJson.optString("changelog", "")
|
val changelog = updateJson.optString("changelog", "")
|
||||||
|
|||||||
@@ -1,35 +1,32 @@
|
|||||||
package com.rifsxd.ksunext.ui.viewmodel
|
package com.rifsxd.ksunext.ui.viewmodel
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.ServiceConnection
|
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.os.IBinder
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
|
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import com.rifsxd.ksunext.IKsuInterface
|
|
||||||
import com.rifsxd.ksunext.Natives
|
import com.rifsxd.ksunext.Natives
|
||||||
import com.rifsxd.ksunext.ksuApp
|
import com.rifsxd.ksunext.ksuApp
|
||||||
import com.rifsxd.ksunext.ui.KsuService
|
|
||||||
import com.rifsxd.ksunext.ui.util.HanziToPinyin
|
import com.rifsxd.ksunext.ui.util.HanziToPinyin
|
||||||
import com.rifsxd.ksunext.ui.util.KsuCli
|
import com.rifsxd.ksunext.ui.webui.getInstalledPackagesAll
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import java.text.Collator
|
import java.text.Collator
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
|
|
||||||
class SuperUserViewModel : ViewModel() {
|
class SuperUserViewModel : ViewModel() {
|
||||||
|
val isPlatformAlive get() = Platform.isAlive
|
||||||
|
|
||||||
var refreshOnReturn by mutableStateOf(false)
|
var refreshOnReturn by mutableStateOf(false)
|
||||||
public set
|
public set
|
||||||
@@ -97,56 +94,26 @@ class SuperUserViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend inline fun connectKsuService(
|
|
||||||
crossinline onDisconnect: () -> Unit = {}
|
|
||||||
): Pair<IBinder, ServiceConnection> = suspendCoroutine {
|
|
||||||
val connection = object : ServiceConnection {
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
|
||||||
onDisconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
|
|
||||||
it.resume(binder as IBinder to this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val intent = Intent(ksuApp, KsuService::class.java)
|
|
||||||
|
|
||||||
val task = KsuService.bindOrTask(
|
|
||||||
intent,
|
|
||||||
Shell.EXECUTOR,
|
|
||||||
connection,
|
|
||||||
)
|
|
||||||
val shell = KsuCli.SHELL
|
|
||||||
task?.let { it1 -> shell.execTask(it1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stopKsuService() {
|
|
||||||
val intent = Intent(ksuApp, KsuService::class.java)
|
|
||||||
KsuService.stop(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun fetchAppList() {
|
suspend fun fetchAppList() {
|
||||||
|
|
||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
|
|
||||||
val result = connectKsuService {
|
|
||||||
Log.w(TAG, "KsuService disconnected")
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
withTimeoutOrNull(TIMEOUT_MILLIS) {
|
||||||
|
while (!isPlatformAlive) {
|
||||||
|
delay(500)
|
||||||
|
}
|
||||||
|
} ?: return@withContext // Exit early if timeout
|
||||||
|
|
||||||
val pm = ksuApp.packageManager
|
val pm = ksuApp.packageManager
|
||||||
val start = SystemClock.elapsedRealtime()
|
val start = SystemClock.elapsedRealtime()
|
||||||
|
|
||||||
val binder = result.first
|
val packages = Platform.getInstalledPackagesAll {
|
||||||
val allPackages = IKsuInterface.Stub.asInterface(binder).getPackages(0)
|
Log.e(TAG, "getInstalledPackagesAll:", it)
|
||||||
|
Toast.makeText(ksuApp, "Something went wrong, check logs", Toast.LENGTH_SHORT).show()
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
stopKsuService()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val packages = allPackages.list
|
|
||||||
|
|
||||||
apps = packages.map {
|
apps = packages.map {
|
||||||
val appInfo = it.applicationInfo
|
val appInfo = it.applicationInfo
|
||||||
val uid = appInfo!!.uid
|
val uid = appInfo!!.uid
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package com.rifsxd.ksunext.ui.webui
|
||||||
|
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
|
import android.util.Log
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
|
import com.dergoogler.mmrl.platform.hiddenApi.HiddenPackageManager
|
||||||
|
import com.dergoogler.mmrl.platform.hiddenApi.HiddenUserManager
|
||||||
|
import com.dergoogler.mmrl.platform.model.IProvider
|
||||||
|
import com.dergoogler.mmrl.platform.model.PlatformIntent
|
||||||
|
import com.rifsxd.ksunext.Natives
|
||||||
|
import com.rifsxd.ksunext.ksuApp
|
||||||
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class KsuLibSuProvider : IProvider {
|
||||||
|
override val name = "KsuLibSu"
|
||||||
|
|
||||||
|
override fun isAvailable() = true
|
||||||
|
|
||||||
|
override suspend fun isAuthorized() = Natives.becomeManager(ksuApp.packageName)
|
||||||
|
|
||||||
|
private val serviceIntent
|
||||||
|
get() = PlatformIntent(
|
||||||
|
ksuApp,
|
||||||
|
Platform.KsuNext,
|
||||||
|
SuService::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun bind(connection: ServiceConnection) {
|
||||||
|
RootService.bind(serviceIntent.intent, connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unbind(connection: ServiceConnection) {
|
||||||
|
RootService.stop(serviceIntent.intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun initPlatform() = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val active = Platform.init {
|
||||||
|
this.context = ksuApp
|
||||||
|
this.platform = Platform.KsuNext
|
||||||
|
this.provider = from(KsuLibSuProvider())
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!active) {
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@withContext active
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("KsuLibSu", "Failed to initialize platform", e)
|
||||||
|
return@withContext false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Platform.Companion.getInstalledPackagesAll(catch: (Exception) -> Unit = {}): List<PackageInfo> =
|
||||||
|
try {
|
||||||
|
val packages = mutableListOf<PackageInfo>()
|
||||||
|
val userInfos = userManager.getUsers()
|
||||||
|
|
||||||
|
for (userInfo in userInfos) {
|
||||||
|
packages.addAll(packageManager.getInstalledPackages(0, userInfo.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
packages
|
||||||
|
} catch (e: Exception) {
|
||||||
|
catch(e)
|
||||||
|
packageManager.getInstalledPackages(0, userManager.myUserId)
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.rifsxd.ksunext.ui.webui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.IBinder
|
||||||
|
import com.dergoogler.mmrl.platform.model.PlatformIntent.Companion.getPlatform
|
||||||
|
import com.dergoogler.mmrl.platform.service.ServiceManager
|
||||||
|
import com.topjohnwu.superuser.ipc.RootService
|
||||||
|
|
||||||
|
class SuService : RootService() {
|
||||||
|
override fun onBind(intent: Intent): IBinder {
|
||||||
|
val mode = intent.getPlatform()
|
||||||
|
return ServiceManager(mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@ import androidx.core.view.ViewCompat
|
|||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.webkit.WebViewAssetLoader
|
import androidx.webkit.WebViewAssetLoader
|
||||||
|
import com.dergoogler.mmrl.platform.model.ModId
|
||||||
|
import com.dergoogler.mmrl.webui.interfaces.WXOptions
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.rifsxd.ksunext.ui.util.createRootShell
|
import com.rifsxd.ksunext.ui.util.createRootShell
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -39,9 +41,10 @@ class WebUIActivity : ComponentActivity() {
|
|||||||
val name = intent.getStringExtra("name")!!
|
val name = intent.getStringExtra("name")!!
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name"))
|
setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name"))
|
||||||
} else {
|
} else {
|
||||||
val taskDescription = ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build()
|
val taskDescription =
|
||||||
|
ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build()
|
||||||
setTaskDescription(taskDescription)
|
setTaskDescription(taskDescription)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +65,7 @@ class WebUIActivity : ComponentActivity() {
|
|||||||
val webViewClient = object : WebViewClient() {
|
val webViewClient = object : WebViewClient() {
|
||||||
override fun shouldInterceptRequest(
|
override fun shouldInterceptRequest(
|
||||||
view: WebView,
|
view: WebView,
|
||||||
request: WebResourceRequest
|
request: WebResourceRequest,
|
||||||
): WebResourceResponse? {
|
): WebResourceResponse? {
|
||||||
return webViewAssetLoader.shouldInterceptRequest(request.url)
|
return webViewAssetLoader.shouldInterceptRequest(request.url)
|
||||||
}
|
}
|
||||||
@@ -82,7 +85,9 @@ class WebUIActivity : ComponentActivity() {
|
|||||||
settings.javaScriptEnabled = true
|
settings.javaScriptEnabled = true
|
||||||
settings.domStorageEnabled = true
|
settings.domStorageEnabled = true
|
||||||
settings.allowFileAccess = false
|
settings.allowFileAccess = false
|
||||||
webviewInterface = WebViewInterface(this@WebUIActivity, this, moduleDir)
|
webviewInterface = WebViewInterface(
|
||||||
|
WXOptions(this@WebUIActivity, this, ModId(moduleId))
|
||||||
|
)
|
||||||
addJavascriptInterface(webviewInterface, "ksu")
|
addJavascriptInterface(webviewInterface, "ksu")
|
||||||
setWebViewClient(webViewClient)
|
setWebViewClient(webViewClient)
|
||||||
loadUrl("https://mui.kernelsu.org/index.html")
|
loadUrl("https://mui.kernelsu.org/index.html")
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.rifsxd.ksunext.ui.webui
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.dergoogler.mmrl.platform.Platform
|
||||||
|
import com.dergoogler.mmrl.platform.model.ModId
|
||||||
|
import com.dergoogler.mmrl.ui.component.Loading
|
||||||
|
import com.dergoogler.mmrl.webui.screen.WebUIScreen
|
||||||
|
import com.dergoogler.mmrl.webui.util.rememberWebUIOptions
|
||||||
|
import com.rifsxd.ksunext.BuildConfig
|
||||||
|
import com.rifsxd.ksunext.ui.theme.KernelSUTheme
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class WebUIXActivity : ComponentActivity() {
|
||||||
|
private lateinit var webView: WebView
|
||||||
|
|
||||||
|
private val userAgent
|
||||||
|
get(): String {
|
||||||
|
val ksuVersion = BuildConfig.VERSION_CODE
|
||||||
|
|
||||||
|
val platform = Platform.get("Unknown") {
|
||||||
|
platform.name
|
||||||
|
}
|
||||||
|
|
||||||
|
val platformVersion = Platform.get(-1) {
|
||||||
|
moduleManager.versionCode
|
||||||
|
}
|
||||||
|
|
||||||
|
val osVersion = Build.VERSION.RELEASE
|
||||||
|
val deviceModel = Build.MODEL
|
||||||
|
|
||||||
|
return "KernelSU Next/$ksuVersion (Linux; Android $osVersion; $deviceModel; $platform/$platformVersion)"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
enableEdgeToEdge()
|
||||||
|
|
||||||
|
webView = WebView(this)
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
initPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
val moduleId = intent.getStringExtra("id")!!
|
||||||
|
val name = intent.getStringExtra("name")!!
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name"))
|
||||||
|
} else {
|
||||||
|
val taskDescription =
|
||||||
|
ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build()
|
||||||
|
setTaskDescription(taskDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
KernelSUTheme {
|
||||||
|
var isLoading by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
LaunchedEffect(Platform.isAlive) {
|
||||||
|
while (!Platform.isAlive) {
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
Loading()
|
||||||
|
|
||||||
|
return@KernelSUTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
val webDebugging = prefs.getBoolean("enable_web_debugging", false)
|
||||||
|
val erudaInject = prefs.getBoolean("use_webuix_eruda", false)
|
||||||
|
val dark = isSystemInDarkTheme()
|
||||||
|
|
||||||
|
val options = rememberWebUIOptions(
|
||||||
|
modId = ModId(moduleId),
|
||||||
|
debug = webDebugging,
|
||||||
|
appVersionCode = BuildConfig.VERSION_CODE,
|
||||||
|
isDarkMode = dark,
|
||||||
|
enableEruda = erudaInject,
|
||||||
|
cls = WebUIXActivity::class.java,
|
||||||
|
userAgentString = userAgent
|
||||||
|
)
|
||||||
|
|
||||||
|
WebUIScreen(
|
||||||
|
webView = webView,
|
||||||
|
options = options,
|
||||||
|
interfaces = listOf(
|
||||||
|
WebViewInterface.factory()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
package com.rifsxd.ksunext.ui.webui
|
package com.rifsxd.ksunext.ui.webui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.webkit.JavascriptInterface
|
import android.webkit.JavascriptInterface
|
||||||
import android.webkit.WebView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
import com.dergoogler.mmrl.webui.interfaces.WXInterface
|
||||||
|
import com.dergoogler.mmrl.webui.interfaces.WXOptions
|
||||||
|
import com.dergoogler.mmrl.webui.model.JavaScriptInterface
|
||||||
import com.topjohnwu.superuser.CallbackList
|
import com.topjohnwu.superuser.CallbackList
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
@@ -23,10 +24,15 @@ import java.io.File
|
|||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
class WebViewInterface(
|
class WebViewInterface(
|
||||||
val context: Context,
|
wxOptions: WXOptions,
|
||||||
private val webView: WebView,
|
) : WXInterface(wxOptions) {
|
||||||
private val modDir: String
|
override var name: String = "ksu"
|
||||||
) {
|
|
||||||
|
companion object {
|
||||||
|
fun factory() = JavaScriptInterface(WebViewInterface::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val modDir get() = "/data/adb/modules/${modId.id}"
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun exec(cmd: String): String {
|
fun exec(cmd: String): String {
|
||||||
@@ -59,7 +65,7 @@ class WebViewInterface(
|
|||||||
fun exec(
|
fun exec(
|
||||||
cmd: String,
|
cmd: String,
|
||||||
options: String?,
|
options: String?,
|
||||||
callbackFunc: String
|
callbackFunc: String,
|
||||||
) {
|
) {
|
||||||
val finalCommand = StringBuilder()
|
val finalCommand = StringBuilder()
|
||||||
processOptions(finalCommand, options)
|
processOptions(finalCommand, options)
|
||||||
@@ -168,9 +174,9 @@ class WebViewInterface(
|
|||||||
if (context is Activity) {
|
if (context is Activity) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
hideSystemUI(context.window)
|
hideSystemUI(activity.window)
|
||||||
} else {
|
} else {
|
||||||
showSystemUI(context.window)
|
showSystemUI(activity.window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,7 +185,7 @@ class WebViewInterface(
|
|||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun moduleInfo(): String {
|
fun moduleInfo(): String {
|
||||||
val moduleInfos = JSONArray(listModules())
|
val moduleInfos = JSONArray(listModules())
|
||||||
var currentModuleInfo = JSONObject()
|
val currentModuleInfo = JSONObject()
|
||||||
currentModuleInfo.put("moduleDir", modDir)
|
currentModuleInfo.put("moduleDir", modDir)
|
||||||
val moduleId = File(modDir).getName()
|
val moduleId = File(modDir).getName()
|
||||||
for (i in 0 until moduleInfos.length()) {
|
for (i in 0 until moduleInfos.length()) {
|
||||||
@@ -189,7 +195,7 @@ class WebViewInterface(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var keys = currentInfo.keys()
|
val keys = currentInfo.keys()
|
||||||
for (key in keys) {
|
for (key in keys) {
|
||||||
currentModuleInfo.put(key, currentInfo.get(key))
|
currentModuleInfo.put(key, currentInfo.get(key))
|
||||||
}
|
}
|
||||||
@@ -202,8 +208,12 @@ class WebViewInterface(
|
|||||||
fun hideSystemUI(window: Window) =
|
fun hideSystemUI(window: Window) =
|
||||||
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||||
controller.hide(WindowInsetsCompat.Type.systemBars())
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
controller.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showSystemUI(window: Window) =
|
fun showSystemUI(window: Window) =
|
||||||
WindowInsetsControllerCompat(window, window.decorView).show(WindowInsetsCompat.Type.systemBars())
|
WindowInsetsControllerCompat(
|
||||||
|
window,
|
||||||
|
window.decorView
|
||||||
|
).show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
|||||||
Binary file not shown.
BIN
manager/app/src/main/jniLibs/armeabi-v7a/libmagiskboot.so
Normal file
BIN
manager/app/src/main/jniLibs/armeabi-v7a/libmagiskboot.so
Normal file
Binary file not shown.
BIN
manager/app/src/main/jniLibs/x86_64/libmagiskboot.so
Normal file
BIN
manager/app/src/main/jniLibs/x86_64/libmagiskboot.so
Normal file
Binary file not shown.
@@ -32,11 +32,11 @@
|
|||||||
<string name="selinux_status_enforcing">مفعل</string>
|
<string name="selinux_status_enforcing">مفعل</string>
|
||||||
<string name="selinux_status_permissive">مرن</string>
|
<string name="selinux_status_permissive">مرن</string>
|
||||||
<string name="selinux_status_unknown">غير معروف</string>
|
<string name="selinux_status_unknown">غير معروف</string>
|
||||||
<string name="superuser">مستخدم خارق</string>
|
<string name="superuser">المستخدم خارق</string>
|
||||||
<string name="module_failed_to_enable">فشل في تشغيل إضافة: %s</string>
|
<string name="module_failed_to_enable">فشل في تشغيل إضافة: %s</string>
|
||||||
<string name="module_failed_to_disable">فشل في إيقاف إضافة: %s</string>
|
<string name="module_failed_to_disable">فشل في إيقاف إضافة: %s</string>
|
||||||
<string name="module_empty">لا توجد إضافات مثبته</string>
|
<string name="module_empty">لا توجد إضافات مثبته</string>
|
||||||
<string name="module">الإضافة</string>
|
<string name="module">الإضافات</string>
|
||||||
<string name="module_install_prompt_with_name">الإضافة/ات التالية سيتم تثبيتها: %1$s</string>
|
<string name="module_install_prompt_with_name">الإضافة/ات التالية سيتم تثبيتها: %1$s</string>
|
||||||
<string name="module_sort_a_to_z">تصنيف (أ-ي)</string>
|
<string name="module_sort_a_to_z">تصنيف (أ-ي)</string>
|
||||||
<string name="module_sort_z_to_a">تصنيف (ي-أ)</string>
|
<string name="module_sort_z_to_a">تصنيف (ي-أ)</string>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
<string name="reboot_userspace">إعادة تشغيل سريعة</string>
|
<string name="reboot_userspace">إعادة تشغيل سريعة</string>
|
||||||
<string name="reboot_recovery">إعادة التشغيل إلى وضع الريكفري</string>
|
<string name="reboot_recovery">إعادة التشغيل إلى وضع الريكفري</string>
|
||||||
<string name="reboot_bootloader">إعادة التشغيل إلى وضع bootloader</string>
|
<string name="reboot_bootloader">إعادة التشغيل إلى وضع bootloader</string>
|
||||||
<string name="reboot_download">إعادة التشغيل إلى وضع التحميل</string>
|
<string name="reboot_download">إعادة التشغيل إلى وضع التنزيل</string>
|
||||||
<string name="reboot_edl">إعادة التشغيل إلى وضع EDL</string>
|
<string name="reboot_edl">إعادة التشغيل إلى وضع EDL</string>
|
||||||
<string name="about">حول</string>
|
<string name="about">حول</string>
|
||||||
<string name="module_uninstall_confirm">هل انت متأكد من حذف تلك الإضافة %s؟</string>
|
<string name="module_uninstall_confirm">هل انت متأكد من حذف تلك الإضافة %s؟</string>
|
||||||
@@ -75,11 +75,11 @@
|
|||||||
<string name="reboot_to_apply">إعادة التشغيل لتطبيق التغييرات</string>
|
<string name="reboot_to_apply">إعادة التشغيل لتطبيق التغييرات</string>
|
||||||
<string name="module_magisk_conflict">الإضافات غير متاحة بسبب تعارض مع Magisk!</string>
|
<string name="module_magisk_conflict">الإضافات غير متاحة بسبب تعارض مع Magisk!</string>
|
||||||
<string name="home_mount_system">نظام الإضافات</string>
|
<string name="home_mount_system">نظام الإضافات</string>
|
||||||
<string name="home_magic_mount">Mount السحري</string>
|
<string name="home_magic_mount">Magic Mount</string>
|
||||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
<string name="unavailable">غير متاح</string>
|
<string name="unavailable">غير متاح</string>
|
||||||
<string name="use_overlay_fs">استخدام OverlayFS</string>
|
<string name="use_overlay_fs">استخدام OverlayFS</string>
|
||||||
<string name="use_overlay_fs_summary">التبديل بين استخدام OverlayFS أو Mount السحري لنظام Mount الخاص بـ KernelSU Next.</string>
|
<string name="use_overlay_fs_summary">التبديل بين استخدام OverlayFS أو Magic Mount لنظام Mount الخاص بـKernelSU Next.</string>
|
||||||
<string name="reboot_required">إعادة التشغيل مطلوبة</string>
|
<string name="reboot_required">إعادة التشغيل مطلوبة</string>
|
||||||
<string name="reboot_message">ستدخل التغييرات حيز التنفيذ بعد إعادة تشغيل النظام. هل تريد إعادة التشغيل الآن؟</string>
|
<string name="reboot_message">ستدخل التغييرات حيز التنفيذ بعد إعادة تشغيل النظام. هل تريد إعادة التشغيل الآن؟</string>
|
||||||
<string name="module_restore">استعادة الإضافة</string>
|
<string name="module_restore">استعادة الإضافة</string>
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
<string name="home_experimental_kernelsu_body_point_1"> • استخدم على مسؤوليتك: قد تحدث أعطال أو سلوك غير متوقع أو مشاكل في النظام.</string>
|
<string name="home_experimental_kernelsu_body_point_1"> • استخدم على مسؤوليتك: قد تحدث أعطال أو سلوك غير متوقع أو مشاكل في النظام.</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_2"> • لا ضمان: المطورون غير مسؤولين عن أي فقدان للبيانات أو تلف النظام أو عواقب أخرى ناتجة عن استخدامه.</string>
|
<string name="home_experimental_kernelsu_body_point_2"> • لا ضمان: المطورون غير مسؤولين عن أي فقدان للبيانات أو تلف النظام أو عواقب أخرى ناتجة عن استخدامه.</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_3"> • لأغراض الاختبار فقط: مخصص للمستخدمين الذين يفهمون المخاطر ويشعرون بالراحة في حل المشكلات.</string>
|
<string name="home_experimental_kernelsu_body_point_3"> • لأغراض الاختبار فقط: مخصص للمستخدمين الذين يفهمون المخاطر ويشعرون بالراحة في حل المشكلات.</string>
|
||||||
<string name="about_source_code"><![CDATA[عرض الشيفرة المصدرية في %1$s]]></string>
|
<string name="about_source_code"><![CDATA[عرض رمز المصدر في %1$s]]></string>
|
||||||
<string name="profile" translatable="false">ملف التطبيق</string>
|
<string name="profile" translatable="false">ملف التطبيق</string>
|
||||||
<string name="profile_default">افتراضي</string>
|
<string name="profile_default">افتراضي</string>
|
||||||
<string name="profile_template">قالب</string>
|
<string name="profile_template">قالب</string>
|
||||||
|
|||||||
@@ -120,7 +120,7 @@
|
|||||||
<string name="require_kernel_version">Die aktuelle KernelSU Next Version %1$d ist zu veraltet, damit der Manager richtig funktioniert. aktualisieren Sie bitte auf Version %2$d oder höher!</string>
|
<string name="require_kernel_version">Die aktuelle KernelSU Next Version %1$d ist zu veraltet, damit der Manager richtig funktioniert. aktualisieren Sie bitte auf Version %2$d oder höher!</string>
|
||||||
<string name="settings_umount_modules_default">Umount Module</string>
|
<string name="settings_umount_modules_default">Umount Module</string>
|
||||||
<string name="settings_umount_modules_default_summary">Der globale Standardwert für \„Umount Module\“ in App Profile. Wenn er aktiviert ist, werden alle Moduländerungen im System für Anwendungen entfernt, für die kein Profil festgelegt wurde.</string>
|
<string name="settings_umount_modules_default_summary">Der globale Standardwert für \„Umount Module\“ in App Profile. Wenn er aktiviert ist, werden alle Moduländerungen im System für Anwendungen entfernt, für die kein Profil festgelegt wurde.</string>
|
||||||
<string name="settings_susfs_toggle">verstecke kprobe hooks</string>
|
<string name="settings_susfs_toggle">verstecke kprobes hook</string>
|
||||||
<string name="settings_susfs_toggle_summary">Diese Option deaktiviert die von ksu erzeugten kprobe-hooks und aktiviert stattdessen die eingebetteten nicht-kprobe-hooks, die die gleiche Funktionalität implementieren, die auf einen Nicht-GKI-Kernel angewendet würde, der kprobe nicht unterstützt.</string>
|
<string name="settings_susfs_toggle_summary">Diese Option deaktiviert die von ksu erzeugten kprobe-hooks und aktiviert stattdessen die eingebetteten nicht-kprobe-hooks, die die gleiche Funktionalität implementieren, die auf einen Nicht-GKI-Kernel angewendet würde, der kprobe nicht unterstützt.</string>
|
||||||
<string name="profile_umount_modules_summary">Wenn Sie diese Option aktivieren, kann KernelSU Next alle von den Modulen für diese Anwendung geänderten Dateien wiederherstellen.</string>
|
<string name="profile_umount_modules_summary">Wenn Sie diese Option aktivieren, kann KernelSU Next alle von den Modulen für diese Anwendung geänderten Dateien wiederherstellen.</string>
|
||||||
<string name="profile_selinux_domain">Domain</string>
|
<string name="profile_selinux_domain">Domain</string>
|
||||||
|
|||||||
197
manager/app/src/main/res/values-fa/strings.xml
Normal file
197
manager/app/src/main/res/values-fa/strings.xml
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="issue_report_title">مشکلی دارید؟</string>
|
||||||
|
<string name="issue_report_body">با خطا مواجه شدهاید یا نظری دارید؟</string>
|
||||||
|
<string name="issue_report_body_2">هرچه زودتر گزارش دهید!</string>
|
||||||
|
<string name="issue_report_github">گزارش در گیتهاب</string>
|
||||||
|
<string name="issue_report_telegram">تماس از طریق تلگرام</string>
|
||||||
|
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||||
|
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||||
|
<string name="confirm">تأیید</string>
|
||||||
|
<string name="app_name" translatable="false">KernelSU Next</string>
|
||||||
|
<string name="home">خانه</string>
|
||||||
|
<string name="home_not_installed">نصب نشده</string>
|
||||||
|
<string name="home_click_to_install">برای نصب کلیک کنید</string>
|
||||||
|
<string name="home_working">در حال کار</string>
|
||||||
|
<string name="home_working_version">نسخه: %d</string>
|
||||||
|
<string name="home_superuser_count">کاربران ویژه: %d</string>
|
||||||
|
<string name="home_module_count">ماژولها: %d</string>
|
||||||
|
<string name="home_failure">امضای KernelSU Next v2 در هسته یافت نشد! [ !KSU_NEXT || != size/hash ]</string>
|
||||||
|
<string name="home_failure_tip">از توسعهدهنده هسته خود بخواهید KernelSU Next را یکپارچه کند!</string>
|
||||||
|
<string name="home_kernel">نسخه هسته</string>
|
||||||
|
<string name="enabled">فعال</string>
|
||||||
|
<string name="disabled">غیرفعال</string>
|
||||||
|
<string name="susfs_supported">پشتیبانیشده</string>
|
||||||
|
<string name="home_susfs">SuSFS: %s</string>
|
||||||
|
<string name="home_susfs_version">نسخه SuSFS</string>
|
||||||
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
|
<string name="home_android">نسخه اندروید</string>
|
||||||
|
<string name="home_manager_version">نسخه مدیر</string>
|
||||||
|
<string name="home_selinux_status">وضعیت SELinux</string>
|
||||||
|
<string name="selinux_status_disabled">غیرفعال</string>
|
||||||
|
<string name="selinux_status_enforcing">اجباری</string>
|
||||||
|
<string name="selinux_status_permissive">مجاز</string>
|
||||||
|
<string name="selinux_status_unknown">ناشناخته</string>
|
||||||
|
<string name="superuser">کاربر ویژه</string>
|
||||||
|
<string name="module_failed_to_enable">فعالسازی ماژول شکست خورد: %s</string>
|
||||||
|
<string name="module_failed_to_disable">غیرفعالسازی ماژول شکست خورد: %s</string>
|
||||||
|
<string name="module_empty">هیچ ماژولی نصب نشده</string>
|
||||||
|
<string name="module">ماژول</string>
|
||||||
|
<string name="module_install_prompt_with_name">ماژول(های) زیر نصب خواهد شد: %1$s</string>
|
||||||
|
<string name="module_sort_a_to_z">مرتبسازی (الف-ی)</string>
|
||||||
|
<string name="module_sort_z_to_a">مرتبسازی (ی-الف)</string>
|
||||||
|
<string name="uninstall">حذف نصب</string>
|
||||||
|
<string name="restore">بازیابی</string>
|
||||||
|
<string name="module_install">نصب</string>
|
||||||
|
<string name="install">نصب</string>
|
||||||
|
<string name="reboot">راهاندازی مجدد</string>
|
||||||
|
<string name="settings">تنظیمات</string>
|
||||||
|
<string name="reboot_userspace">راهاندازی نرم</string>
|
||||||
|
<string name="reboot_recovery">راهاندازی به حالت ریکاوری</string>
|
||||||
|
<string name="reboot_bootloader">راهاندازی به حالت بوتلودر</string>
|
||||||
|
<string name="reboot_download">راهاندازی به حالت دانلود</string>
|
||||||
|
<string name="reboot_edl">راهاندازی به حالت EDL</string>
|
||||||
|
<string name="about">درباره</string>
|
||||||
|
<string name="module_uninstall_confirm">آیا مطمئن هستید که میخواهید ماژول %s را حذف کنید؟</string>
|
||||||
|
<string name="module_uninstall_success">ماژول %s حذف شد</string>
|
||||||
|
<string name="module_uninstall_failed">حذف ماژول شکست خورد: %s</string>
|
||||||
|
<string name="module_restore_confirm">آیا مطمئن هستید که میخواهید ماژول %s را بازیابی کنید؟</string>
|
||||||
|
<string name="module_restore_success">ماژول %s بازیابی شد</string>
|
||||||
|
<string name="module_restore_failed">بازیابی ماژول شکست خورد: %s</string>
|
||||||
|
<string name="module_version">نسخه</string>
|
||||||
|
<string name="module_author">سازنده</string>
|
||||||
|
<string name="module_id">شناسه</string>
|
||||||
|
<string name="module_version_code">کد نسخه</string>
|
||||||
|
<string name="module_update_json">بهروزرسانی JSON</string>
|
||||||
|
<string name="module_update_json_empty">خالی</string>
|
||||||
|
<string name="enable_developer_options">فعالسازی گزینههای توسعهدهنده</string>
|
||||||
|
<string name="enable_developer_options_summary">نمایش تنظیمات مخفی و اطلاعات اشکالزدایی که فقط برای توسعهدهندگان مفید است.</string>
|
||||||
|
<string name="module_overlay_fs_not_available">ماژولها به دلیل غیرفعال بودن OverlayFS توسط هسته در دسترس نیستند.</string>
|
||||||
|
<string name="refresh">تازهسازی</string>
|
||||||
|
<string name="show_system_apps">نمایش برنامههای سیستمی</string>
|
||||||
|
<string name="hide_system_apps">پنهان کردن برنامههای سیستمی</string>
|
||||||
|
<string name="export_log">صدور گزارشها</string>
|
||||||
|
<string name="safe_mode">حالت ایمن</string>
|
||||||
|
<string name="reboot_to_apply">برای اعمال تغییرات راهاندازی مجدد کنید</string>
|
||||||
|
<string name="module_magisk_conflict">ماژولها به دلیل تداخل با Magisk در دسترس نیستند!</string>
|
||||||
|
<string name="home_mount_system">نصب سیستم</string>
|
||||||
|
<string name="home_magic_mount">نصب جادویی</string>
|
||||||
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
|
<string name="unavailable">در دسترس نیست</string>
|
||||||
|
<string name="use_overlay_fs">استفاده از OverlayFS</string>
|
||||||
|
<string name="use_overlay_fs_summary">تغییر بین استفاده از OverlayFS و نصب جادویی برای سیستم نصب KernelSU Next.</string>
|
||||||
|
<string name="reboot_required">نیاز به راهاندازی مجدد</string>
|
||||||
|
<string name="reboot_message">تغییرات پس از راهاندازی مجدد سیستم اعمال میشوند. آیا میخواهید اکنون راهاندازی کنید؟</string>
|
||||||
|
<string name="module_restore">بازیابی ماژول</string>
|
||||||
|
<string name="module_restore_message">بازیابی ماژولها از آخرین نسخه پشتیبان.</string>
|
||||||
|
<string name="backup_restore">پشتیبانگیری و بازیابی</string>
|
||||||
|
<string name="module_backup">پشتیبانگیری از ماژول</string>
|
||||||
|
<string name="module_backup_message">پشتیبانگیری از ماژولهای نصبشده کنونی.</string>
|
||||||
|
<string name="allowlist_restore">بازیابی لیست مجاز</string>
|
||||||
|
<string name="allowlist_restore_message">بازیابی لیست مجاز از آخرین نسخه پشتیبان.</string>
|
||||||
|
<string name="allowlist_backup">پشتیبانگیری از لیست مجاز</string>
|
||||||
|
<string name="allowlist_backup_message">پشتیبانگیری از لیست مجاز کنونی.</string>
|
||||||
|
<string name="warning">هشدار</string>
|
||||||
|
<string name="warning_message">این ویژگی هنوز در مرحله آزمایشی و در حال توسعه است. لطفاً پیش از ادامه، از ماژولهای خود نسخه پشتیبان تهیه کنید. این ویژگی را تنها در صورتی استفاده کنید که خطرات احتمالی را درک کرده باشید. با احتیاط ادامه دهید.</string>
|
||||||
|
<string name="proceed">ادامه</string>
|
||||||
|
<string name="cancel">لغو</string>
|
||||||
|
<string name="later">بعداً</string>
|
||||||
|
<string name="home_next_kernelsu">🔥 ساخت بعدی</string>
|
||||||
|
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||||
|
<string name="home_next_kernelsu_body">شاخه آزمایشی بعدی. آن را در گیتهاب بررسی کنید!</string>
|
||||||
|
<string name="home_experimental_kernelsu">⚠️ هشدار توسعه آزمایشی!</string>
|
||||||
|
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||||
|
<string name="home_experimental_kernelsu_body">KernelSU Next نسخهای غیررسمی است که همیشه در حال توسعه آزمایشی فعال است. این نسخه همانگونه که هست ارائه میشود، بدون تضمین پایداری، عملکرد یا قابلیت اطمینان.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_1"> • استفاده با مسئولیت خودتان: ممکن است با خرابی، رفتار غیرمنتظره یا مشکلات سیستمی مواجه شوید.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_2"> • بدون گارانتی: توسعهدهندگان مسئول هیچگونه از دست دادن داده، آسیب به سیستم یا سایر پیامدها نیستند.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_3"> • فقط برای آزمایش: برای کاربرانی که خطرات را درک کرده و با عیبیابی راحت هستند.</string>
|
||||||
|
<string name="about_source_code"><![CDATA[مشاهده کد منبع در %1$s]]></string>
|
||||||
|
<string name="profile" translatable="false">پروفایل برنامه</string>
|
||||||
|
<string name="profile_default">پیشفرض</string>
|
||||||
|
<string name="profile_template">الگو</string>
|
||||||
|
<string name="profile_custom">سفارشی</string>
|
||||||
|
<string name="profile_name">نام پروفایل</string>
|
||||||
|
<string name="profile_namespace">فضای نصب</string>
|
||||||
|
<string name="profile_namespace_inherited">ارثی</string>
|
||||||
|
<string name="profile_namespace_global">جهانی</string>
|
||||||
|
<string name="profile_namespace_individual">فردی</string>
|
||||||
|
<string name="profile_groups">گروهها</string>
|
||||||
|
<string name="profile_capabilities">قابلیتها</string>
|
||||||
|
<string name="profile_selinux_context">زمینه SELinux</string>
|
||||||
|
<string name="profile_umount_modules">حذف ماژولها</string>
|
||||||
|
<string name="failed_to_update_app_profile">بهروزرسانی پروفایل برنامه برای %s شکست خورد</string>
|
||||||
|
<string name="require_kernel_version">نسخه کنونی KernelSU Next %1$d برای عملکرد صحیح مدیر بسیار پایین است. لطفاً به نسخه %2$d یا بالاتر ارتقا دهید!</string>
|
||||||
|
<string name="settings_umount_modules_default">حذف پیشفرض ماژولها</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">مقدار پیشفرض جهانی برای «حذف ماژولها» در پروفایل برنامه. اگر فعال باشد، تمام تغییرات سیستمی ماژولها برای برنامههایی که پروفایل ندارند حذف میشود.</string>
|
||||||
|
<string name="settings_susfs_toggle">مخفی کردن قلابهای kprobe</string>
|
||||||
|
<string name="settings_susfs_toggle_summary">این گزینه قلابهای kprobe ایجادشده توسط ksu را غیرفعال کرده و بهجای آن، قلابهای غیر kprobe داخلی را فعال میکند که همان عملکرد را برای هستههای غیر GKI که از kprobe پشتیبانی نمیکنند، پیادهسازی میکند.</string>
|
||||||
|
<string name="profile_umount_modules_summary">فعال کردن این گزینه به KernelSU Next اجازه میدهد فایلهای تغییر یافته توسط ماژولها را برای این برنامه بازیابی کند.</string>
|
||||||
|
<string name="profile_selinux_domain">دامنه</string>
|
||||||
|
<string name="profile_selinux_rules">قوانین</string>
|
||||||
|
<string name="module_update">بهروزرسانی</string>
|
||||||
|
<string name="module_downloading">در حال دانلود ماژول: %s</string>
|
||||||
|
<string name="module_start_downloading">شروع دانلود: %s</string>
|
||||||
|
<string name="new_version_available">نسخه جدید %s در دسترس است، برای ارتقا کلیک کنید.</string>
|
||||||
|
<string name="launch_app">اجرا</string>
|
||||||
|
<string name="close">بستن</string>
|
||||||
|
<string name="force_stop_app">توقف اجباری</string>
|
||||||
|
<string name="restart_app">راهاندازی مجدد</string>
|
||||||
|
<string name="failed_to_update_sepolicy">بهروزرسانی قوانین SELinux برای %s شکست خورد</string>
|
||||||
|
<string name="su_not_allowed">اعطای دسترسی ویژه برای %s مجاز نیست</string>
|
||||||
|
<string name="module_changelog">تغییرات</string>
|
||||||
|
<string name="settings_profile_template">الگوی پروفایل برنامه</string>
|
||||||
|
<string name="settings_profile_template_summary">مدیریت الگوهای محلی و آنلاین پروفایل برنامه</string>
|
||||||
|
<string name="app_profile_template_create">ایجاد الگو</string>
|
||||||
|
<string name="app_profile_template_edit">ویرایش الگو</string>
|
||||||
|
<string name="app_profile_template_id">شناسه</string>
|
||||||
|
<string name="app_profile_template_id_invalid">شناسه الگو نامعتبر است</string>
|
||||||
|
<string name="app_profile_template_name">نام</string>
|
||||||
|
<string name="app_profile_template_description">توضیحات</string>
|
||||||
|
<string name="app_profile_template_save">ذخیره</string>
|
||||||
|
<string name="app_profile_template_delete">حذف</string>
|
||||||
|
<string name="app_profile_template_view">مشاهده الگو</string>
|
||||||
|
<string name="app_profile_template_readonly">فقط خواندنی</string>
|
||||||
|
<string name="app_profile_template_id_exist">شناسه الگو قبلاً وجود دارد!</string>
|
||||||
|
<string name="app_profile_import_export">واردات/صادرات</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">واردات از کلیپبورد</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">صادرات به کلیپبورد</string>
|
||||||
|
<string name="app_profile_template_export_empty">هیچ الگوی محلی برای صادرات یافت نشد!</string>
|
||||||
|
<string name="app_profile_template_import_success">با موفقیت وارد شد</string>
|
||||||
|
<string name="app_profile_template_sync">همگامسازی الگوهای آنلاین</string>
|
||||||
|
<string name="app_profile_template_save_failed">ذخیره الگو شکست خورد</string>
|
||||||
|
<string name="app_profile_template_import_empty">کلیپبورد خالی است!</string>
|
||||||
|
<string name="module_changelog_failed">دریافت تغییرات شکست خورد: %s</string>
|
||||||
|
<string name="settings_check_update">بررسی بهروزرسانی</string>
|
||||||
|
<string name="settings_check_update_summary">بررسی خودکار بهروزرسانیها هنگام باز کردن برنامه.</string>
|
||||||
|
<string name="grant_root_failed">اعطای دسترسی ریشه شکست خورد!</string>
|
||||||
|
<string name="action">اقدام</string>
|
||||||
|
<string name="open">باز کردن</string>
|
||||||
|
<string name="enable_web_debugging">فعالسازی اشکالزدایی وبویو</string>
|
||||||
|
<string name="enable_web_debugging_summary">میتواند برای اشکالزدایی رابط وب استفاده شود. لطفاً فقط در صورت نیاز فعال کنید.</string>
|
||||||
|
<string name="direct_install">نصب مستقیم (توصیهشده)</string>
|
||||||
|
<string name="select_file">انتخاب فایل</string>
|
||||||
|
<string name="install_inactive_slot">نصب در اسلات غیرفعال (پس از OTA)</string>
|
||||||
|
<string name="install_inactive_slot_warning">دستگاه شما پس از راهاندازی مجدد **اجباراً** به اسلات غیرفعال کنونی بوت خواهد شد!\nفقط پس از انجام OTA از این گزینه استفاده کنید.\nادامه میدهید؟</string>
|
||||||
|
<string name="install_next">بعدی</string>
|
||||||
|
<string name="select_file_tip">تصویر پارتیشن %1$s توصیه میشود</string>
|
||||||
|
<string name="select_kmi">انتخاب KMI</string>
|
||||||
|
<string name="shrink_sparse_image">کاهش اندازه تصویر پراکنده</string>
|
||||||
|
<string name="shrink_sparse_image_message">تغییر اندازه تصویر پراکندهای که ماژول در آن قرار دارد به اندازه واقعی آن. توجه داشته باشید که این ممکن است باعث عملکرد غیرعادی ماژول شود، بنابراین فقط در صورت نیاز (مانند پشتیبانگیری) استفاده کنید.</string>
|
||||||
|
<string name="settings_uninstall">حذف نصب</string>
|
||||||
|
<string name="settings_uninstall_temporary">حذف نصب موقت</string>
|
||||||
|
<string name="settings_uninstall_permanent">حذف نصب دائمی</string>
|
||||||
|
<string name="settings_restore_stock_image">بازیابی تصویر اصلی</string>
|
||||||
|
<string name="settings_uninstall_temporary_message">حذف موقت KernelSU Next، بازگشت به حالت اولیه پس از راهاندازی بعدی.</string>
|
||||||
|
<string name="settings_uninstall_permanent_message">حذف کامل و دائمی KernelSU Next (ریشه و همه ماژولها).</string>
|
||||||
|
<string name="settings_restore_stock_image_message">بازیابی تصویر کارخانهای (در صورت وجود نسخه پشتیبان)، معمولاً قبل از OTA استفاده میشود؛ اگر نیاز به حذف KernelSU Next دارید، لطفاً از «حذف نصب دائمی» استفاده کنید.</string>
|
||||||
|
<string name="flashing">در حال فلش</string>
|
||||||
|
<string name="flash_success">فلش موفق</string>
|
||||||
|
<string name="flash_failed">فلش ناموفق</string>
|
||||||
|
<string name="selected_lkm">LKM انتخابشده: %s</string>
|
||||||
|
<string name="save_log">ذخیره گزارشها</string>
|
||||||
|
<string name="log_saved">گزارشها ذخیره شدند</string>
|
||||||
|
<string name="send_log">اشتراک گزارشها</string>
|
||||||
|
<string name="settings_disable_su">غیرفعال کردن سازگاری su</string>
|
||||||
|
<string name="settings_disable_su_summary">غیرفعال کردن موقت توانایی هر برنامه برای کسب دسترسی ریشه از طریق دستور su (فرآیندهای ریشه موجود تحت تأثیر قرار نمیگیرند).</string>
|
||||||
|
<string name="settings_language">زبان</string>
|
||||||
|
</resources>
|
||||||
197
manager/app/src/main/res/values-hu/strings.xml
Normal file
197
manager/app/src/main/res/values-hu/strings.xml
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="issue_report_title">Problémája van?</string>
|
||||||
|
<string name="issue_report_body">Hibát észlelt, vagy van visszajelzése?</string>
|
||||||
|
<string name="issue_report_body_2">Jelentse mielőbb!</string>
|
||||||
|
<string name="issue_report_github">Report on GitHub</string>
|
||||||
|
<string name="issue_report_telegram">Kapcsolatfelvétel Telegramon keresztül</string>
|
||||||
|
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||||
|
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||||
|
<string name="confirm">Megerősítés</string>
|
||||||
|
<string name="app_name" translatable="false">KernelSU Next</string>
|
||||||
|
<string name="home">Kezdőlap</string>
|
||||||
|
<string name="home_not_installed">Nincs telepítve</string>
|
||||||
|
<string name="home_click_to_install">Kattintson a telepítéshez</string>
|
||||||
|
<string name="home_working">Működik</string>
|
||||||
|
<string name="home_working_version">Verzió: %d</string>
|
||||||
|
<string name="home_superuser_count">Superuserek: %d</string>
|
||||||
|
<string name="home_module_count">Modulok: %d</string>
|
||||||
|
<string name="home_failure">KernelSU Next v2 aláírás nem található a kernelben! [ !KSU_NEXT || != size/hash ]</string>
|
||||||
|
<string name="home_failure_tip">Kérje meg kernel fejlesztőjét, hogy integrálja a KernelSU Next-et!</string>
|
||||||
|
<string name="home_kernel">Kernel verzió</string>
|
||||||
|
<string name="enabled">Bekapcsolva</string>
|
||||||
|
<string name="disabled">Kikapcsolva</string>
|
||||||
|
<string name="susfs_supported">Támogatott</string>
|
||||||
|
<string name="home_susfs">SuSFS: %s</string>
|
||||||
|
<string name="home_susfs_version">SuSFS verzió</string>
|
||||||
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
|
<string name="home_android">Android verzió</string>
|
||||||
|
<string name="home_manager_version">Manager verzió</string>
|
||||||
|
<string name="home_selinux_status">SELinux státusz</string>
|
||||||
|
<string name="selinux_status_disabled">Letiltva</string>
|
||||||
|
<string name="selinux_status_enforcing">Kényszerítve</string>
|
||||||
|
<string name="selinux_status_permissive">Megengedő</string>
|
||||||
|
<string name="selinux_status_unknown">Ismeretlen</string>
|
||||||
|
<string name="superuser">Superuser</string>
|
||||||
|
<string name="module_failed_to_enable">Nem sikerült bekapcsolni a(z) %s modult</string>
|
||||||
|
<string name="module_failed_to_disable">Nem sikerült kikapcsolni a(z) %s modult</string>
|
||||||
|
<string name="module_empty">Nincs telepített modul</string>
|
||||||
|
<string name="module">Modul</string>
|
||||||
|
<string name="module_install_prompt_with_name">A következő modul(ok) lesznek telepítve: %1$s</string>
|
||||||
|
<string name="module_sort_a_to_z">Rendezés (A-Z)</string>
|
||||||
|
<string name="module_sort_z_to_a">Rendezés (Z-A)</string>
|
||||||
|
<string name="uninstall">Eltávolítás</string>
|
||||||
|
<string name="restore">Visszaállítás</string>
|
||||||
|
<string name="module_install">Telepítés</string>
|
||||||
|
<string name="install">Telepítés</string>
|
||||||
|
<string name="reboot">Újraindítás</string>
|
||||||
|
<string name="settings">Beállítások</string>
|
||||||
|
<string name="reboot_userspace">Lágy újraindítás</string>
|
||||||
|
<string name="reboot_recovery">Újraindítás Recovery módba</string>
|
||||||
|
<string name="reboot_bootloader">Újraindítás Bootloader módba</string>
|
||||||
|
<string name="reboot_download">Újraindítás Download módba</string>
|
||||||
|
<string name="reboot_edl">Újraindítás EDL módba</string>
|
||||||
|
<string name="about">Információ</string>
|
||||||
|
<string name="module_uninstall_confirm">Biztosan eltávolítja a(z) %s modult?</string>
|
||||||
|
<string name="module_uninstall_success">%s eltávolítva</string>
|
||||||
|
<string name="module_uninstall_failed">Nem sikerült eltávolítani az %s modult</string>
|
||||||
|
<string name="module_restore_confirm">Biztosan vissza szeretné állítan a(z) %s modult?</string>
|
||||||
|
<string name="module_restore_success">%s visszaállítva</string>
|
||||||
|
<string name="module_restore_failed">Nem sikerült visszaállítani a(z) %s modult</string>
|
||||||
|
<string name="module_version">Verzió</string>
|
||||||
|
<string name="module_author">Készítő</string>
|
||||||
|
<string name="module_id">Azonosító</string>
|
||||||
|
<string name="module_version_code">Kód</string>
|
||||||
|
<string name="module_update_json">UpdateJson</string>
|
||||||
|
<string name="module_update_json_empty">Üres</string>
|
||||||
|
<string name="enable_developer_options">Engedélyezze a fejlesztői beállításokat</string>
|
||||||
|
<string name="enable_developer_options_summary">Csak a fejlesztők számára releváns rejtett beállítások és hibakeresési információk megjelenítése.</string>
|
||||||
|
<string name="module_overlay_fs_not_available">A modulok nem érhetők el, mert az OverlayFS-t a kernel letiltotta.</string>
|
||||||
|
<string name="refresh">Frissítés</string>
|
||||||
|
<string name="show_system_apps">Rendszeralkalmazások megjelenítése</string>
|
||||||
|
<string name="hide_system_apps">Rendszeralkalmazások elrejtése</string>
|
||||||
|
<string name="export_log">Naplók exportálása</string>
|
||||||
|
<string name="safe_mode">Biztonságos mód</string>
|
||||||
|
<string name="reboot_to_apply">Indítsa újra a változtatások érvénybe lépéséhez</string>
|
||||||
|
<string name="module_magisk_conflict">A modulok a Magiskkel való konfliktus miatt nem érhetők el!</string>
|
||||||
|
<string name="home_mount_system">Csatolási rendszer</string>
|
||||||
|
<string name="home_magic_mount">Magic Mount</string>
|
||||||
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
|
<string name="unavailable">Nem elérhető</string>
|
||||||
|
<string name="use_overlay_fs">Használja az OverlayFS-t</string>
|
||||||
|
<string name="use_overlay_fs_summary">Váltás az OverlayFS és a Magic Mount módszerek között a KernelSU Next csatolási rendszerében.</string>
|
||||||
|
<string name="reboot_required">Újraindítás szükséges</string>
|
||||||
|
<string name="reboot_message">A változtatások a rendszer újraindítása után lépnek életbe. Szeretné most újraindítani?</string>
|
||||||
|
<string name="module_restore">Modul visszaállítása</string>
|
||||||
|
<string name="module_restore_message">Modulok visszaállítása biztonsági mentésből</string>
|
||||||
|
<string name="backup_restore">Mentés & Visszaállítás</string>
|
||||||
|
<string name="module_backup">Modul biztonsági mentése</string>
|
||||||
|
<string name="module_backup_message">Biztonsági mentés a jelenleg telepített modulokról.</string>
|
||||||
|
<string name="allowlist_restore">Engedélyezőlista visszaállítása</string>
|
||||||
|
<string name="allowlist_restore_message">Engedélyezőlista visszaállítása biztonsági mentésből.</string>
|
||||||
|
<string name="allowlist_backup">Az engedélyezési lista biztonsági mentése</string>
|
||||||
|
<string name="allowlist_backup_message">A jelenleg konfigurált engedélyezési lista biztonsági mentése.</string>
|
||||||
|
<string name="warning">Figyelem</string>
|
||||||
|
<string name="warning_message">Ez a funkció még béta állapotban van, és fejlesztés alatt áll. Kérjük, a folytatás előtt készítsen biztonsági másolatot a modulokról. Csak akkor használja ezt a funkciót, ha tisztában van a lehetséges kockázatokkal. Óvatosan járjon el.</string>
|
||||||
|
<string name="proceed">Folytatás</string>
|
||||||
|
<string name="cancel">Mégse</string>
|
||||||
|
<string name="later">Később</string>
|
||||||
|
<string name="home_next_kernelsu">🔥 Next build</string>
|
||||||
|
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||||
|
<string name="home_next_kernelsu_body">Next kísérleti branch. Nézze meg a GitHubon!</string>
|
||||||
|
<string name="home_experimental_kernelsu">⚠️ Figyelmeztetés kísérleti fejlesztésre!</string>
|
||||||
|
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||||
|
<string name="home_experimental_kernelsu_body">A KernelSU Next egy nem hivatalos verzió, amely folyamatosan kísérleti fejlesztés alatt áll. Az alkalmazás \"ahogy most van\", úgy kerül biztosításra, stabilitás, teljesítmény vagy megbízhatóság tekintetében semmilyen garancia nélkül.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_1">• Saját felelősségre használja: összeomlások, váratlan viselkedés vagy rendszerproblémák fordulhatnak elő.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_2">• Nincs garancia: a fejlesztők nem vállalnak felelősséget a használatából eredő adatvesztésért, rendszerkárosodásért vagy egyéb következményekért.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_3">• Csak tesztelési célokra: azoknak a felhasználóknak készült, akik megértik a kockázatokat, és jártasak a hibaelhárításban.</string>
|
||||||
|
<string name="about_source_code"><![CDATA[Tekintse meg a forráskódot: %1$s]]></string>
|
||||||
|
<string name="profile" translatable="false">App Profil</string>
|
||||||
|
<string name="profile_default">Alapértelmezett</string>
|
||||||
|
<string name="profile_template">Sablon</string>
|
||||||
|
<string name="profile_custom">Egyedi</string>
|
||||||
|
<string name="profile_name">Profil neve</string>
|
||||||
|
<string name="profile_namespace">Csatolási névtér</string>
|
||||||
|
<string name="profile_namespace_inherited">Örökölt</string>
|
||||||
|
<string name="profile_namespace_global">Globális</string>
|
||||||
|
<string name="profile_namespace_individual">Egyedi</string>
|
||||||
|
<string name="profile_groups">Csoportok</string>
|
||||||
|
<string name="profile_capabilities">Adottságok</string>
|
||||||
|
<string name="profile_selinux_context">SELinux környezet</string>
|
||||||
|
<string name="profile_umount_modules">Modulok lecsatolása</string>
|
||||||
|
<string name="failed_to_update_app_profile">Nem sikerült frissíteni a(z) %s alkalmazásprofilját</string>
|
||||||
|
<string name="require_kernel_version">A jelenlegi KernelSU Next verzió (%1$d) túl alacsony ahhoz, hogy a kezelő megfelelően működjön. Kérjük, frissítsen a(z) %2$d vagy újabb verzióra!</string>
|
||||||
|
<string name="settings_umount_modules_default">Modulok lecsatolása</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">A „Modulok lecsatolása” globális alapértelmezett értéke az alkalmazásprofilban. Ha engedélyezve van, eltávolítja a rendszer összes modul-módosítását az olyan alkalmazások esetében, amelyekhez nincs beállítva profil.</string>
|
||||||
|
<string name="settings_susfs_toggle">A kprobe hook-ok elrejtése</string>
|
||||||
|
<string name="settings_susfs_toggle_summary">Ez az opció letiltja a ksu által létrehozott kprobe hook-okat, és ehelyett aktiválja a beágyazott, nem kprobe hook-okat, megvalósítva ugyanazt a funkcionalitást, amelyet egy nem GKI kernel esetében alkalmaznának, amely nem támogatja a kprobe-ot.</string>
|
||||||
|
<string name="profile_umount_modules_summary">Az opció engedélyezése lehetővé teszi, hogy a KernelSU Next visszaállítsa az alkalmazás moduljai által módosított fájlokat.</string>
|
||||||
|
<string name="profile_selinux_domain">Domain</string>
|
||||||
|
<string name="profile_selinux_rules">Szabályok</string>
|
||||||
|
<string name="module_update">Frissítés</string>
|
||||||
|
<string name="module_downloading">%s modul letöltése</string>
|
||||||
|
<string name="module_start_downloading">Letöltés indítása: %s</string>
|
||||||
|
<string name="new_version_available">Új verzió (%s) elérhető, kattintson a frissítéshez.</string>
|
||||||
|
<string name="launch_app">Indítás</string>
|
||||||
|
<string name="close">Bezár</string>
|
||||||
|
<string name="force_stop_app">Kényszer leállítás</string>
|
||||||
|
<string name="restart_app">Újraindítás</string>
|
||||||
|
<string name="failed_to_update_sepolicy">Nem sikerült frissíteni a SELinux szabályait a következőhöz: %s</string>
|
||||||
|
<string name="su_not_allowed">Superuser megadása nem engedélyezett a következőhöz: %s</string>
|
||||||
|
<string name="module_changelog">Változásnapló</string>
|
||||||
|
<string name="settings_profile_template">Alkalmazásprofil sablon</string>
|
||||||
|
<string name="settings_profile_template_summary">Az alkalmazásprofil helyi és online sablonjának kezelése</string>
|
||||||
|
<string name="app_profile_template_create">Sablon létrehozása</string>
|
||||||
|
<string name="app_profile_template_edit">Sablon szerkesztése</string>
|
||||||
|
<string name="app_profile_template_id">Azonosító</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Érvénytelen sablonazonosító</string>
|
||||||
|
<string name="app_profile_template_name">Név</string>
|
||||||
|
<string name="app_profile_template_description">Leírás</string>
|
||||||
|
<string name="app_profile_template_save">Mentés</string>
|
||||||
|
<string name="app_profile_template_delete">Törlés</string>
|
||||||
|
<string name="app_profile_template_view">Sablon megtekintése</string>
|
||||||
|
<string name="app_profile_template_readonly">Csak olvasható</string>
|
||||||
|
<string name="app_profile_template_id_exist">A sablonazonosító már létezik!</string>
|
||||||
|
<string name="app_profile_import_export">Importálás/Exportálás</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importálás a vágólapról</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exportálás vágólapra</string>
|
||||||
|
<string name="app_profile_template_export_empty">Nem található az exportálandó helyi sablon!</string>
|
||||||
|
<string name="app_profile_template_import_success">Sikeresen importálva</string>
|
||||||
|
<string name="app_profile_template_sync">Online sablonok szinkronizálása</string>
|
||||||
|
<string name="app_profile_template_save_failed">Nem sikerült menteni a sablont</string>
|
||||||
|
<string name="app_profile_template_import_empty">A vágólap üres!</string>
|
||||||
|
<string name="module_changelog_failed">A változásnapló lekérése nem sikerült: %s</string>
|
||||||
|
<string name="settings_check_update">Ellenőrizze a frissítéseket</string>
|
||||||
|
<string name="settings_check_update_summary">Az alkalmazás megnyitásakor automatikusan ellenőrizze a frissítéseket.</string>
|
||||||
|
<string name="grant_root_failed">Nem sikerült a root jog megadása!</string>
|
||||||
|
<string name="action">Tevékenység</string>
|
||||||
|
<string name="open">Megnyitás</string>
|
||||||
|
<string name="enable_web_debugging">WebView hibakeresés engedélyezése</string>
|
||||||
|
<string name="enable_web_debugging_summary">A WebUI hibakeresésére. Kérjük, csak akkor engedélyezze, ha szükséges.</string>
|
||||||
|
<string name="direct_install">Közvetlen telepítés (ajánlott)</string>
|
||||||
|
<string name="select_file">Fájl kiválasztása a patcheléshez</string>
|
||||||
|
<string name="install_inactive_slot">Telepítés inaktív slotba (OTA után)</string>
|
||||||
|
<string name="install_inactive_slot_warning">Eszköze újraindítás után **KÉNYSZERÍTVE** lesz, hogy a jelenleg inaktív slotból induljon el! Ezt az opciót csak az OTA befejezése után használja. Folytatja?</string>
|
||||||
|
<string name="install_next">Következő</string>
|
||||||
|
<string name="select_file_tip">%1$s partíciókép javasolt</string>
|
||||||
|
<string name="select_kmi">Válassza ki a megfelelő KMI-t</string>
|
||||||
|
<string name="shrink_sparse_image">Sparse image minimalizálása</string>
|
||||||
|
<string name="shrink_sparse_image_message">Méretezze át a sparse imaget, ahol a modul található, a tényleges méretre. Vegye figyelembe, hogy ez a modul rendellenes működését okozhatja, ezért kérjük, csak akkor használja, ha szükséges (például biztonsági mentéshez).</string>
|
||||||
|
<string name="settings_uninstall">Eltávolítás</string>
|
||||||
|
<string name="settings_uninstall_temporary">Ideiglenes eltávolítás</string>
|
||||||
|
<string name="settings_uninstall_permanent">Végleges eltávolítás</string>
|
||||||
|
<string name="settings_restore_stock_image">Gyári képfájl visszaállítása</string>
|
||||||
|
<string name="settings_uninstall_temporary_message">A KernelSU ideiglenes eltávolítása, a következő újraindítás után állítsa vissza az eredeti állapotot.</string>
|
||||||
|
<string name="settings_uninstall_permanent_message">A KernelSU Next (Root és az összes modul) teljes és végleges eltávolítása.</string>
|
||||||
|
<string name="settings_restore_stock_image_message">Állítsa vissza a gyári készletképet (ha létezik biztonsági másolat), amelyet általában az OTA előtt használnak; Ha el kell távolítania a KernelSU Next-t, használja a „Végleges eltávolítás” lehetőséget.</string>
|
||||||
|
<string name="flashing">Telepítés</string>
|
||||||
|
<string name="flash_success">Sikeres telepítés</string>
|
||||||
|
<string name="flash_failed">A telepítés nem sikerült</string>
|
||||||
|
<string name="selected_lkm">A kiválasztott LKM: %s</string>
|
||||||
|
<string name="save_log">Mentse a naplókat</string>
|
||||||
|
<string name="log_saved">A naplók mentve</string>
|
||||||
|
<string name="send_log">Naplók megosztása</string>
|
||||||
|
<string name="settings_disable_su">Kapcsolja ki a su kompatibilitást</string>
|
||||||
|
<string name="settings_disable_su_summary">Ideiglenesen tiltsa le bármely alkalmazás azon képességét, hogy root jogosultságokat szerezzen a su paranccsal (a már meglévő folyamatokat ez nem érinti).</string>
|
||||||
|
<string name="settings_language">Nyelv</string>
|
||||||
|
</resources>
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
<string name="home">Home</string>
|
<string name="home">Home</string>
|
||||||
<string name="home_not_installed">Non installato</string>
|
<string name="home_not_installed">Non installato</string>
|
||||||
<string name="home_click_to_install">Clicca per installare</string>
|
<string name="home_click_to_install">Clicca per installare</string>
|
||||||
|
<string name="lkm_mode_deprecated">La modalità LKM è ora obsoleta!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Installa il kernel GKI o integra KernelSU Next sul tuo dispositivo.</string>
|
||||||
<string name="home_working">In esecuzione</string>
|
<string name="home_working">In esecuzione</string>
|
||||||
<string name="home_working_version">Versione: %d</string>
|
<string name="home_working_version">Versione: %d</string>
|
||||||
<string name="home_superuser_count">Applicazioni con accesso root: %d</string>
|
<string name="home_superuser_count">Applicazioni con accesso root: %d</string>
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
<string name="home_failure">Firma KernelSU Next v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
|
<string name="home_failure">Firma KernelSU Next v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||||
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel di integrare KernelSU Next!</string>
|
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel di integrare KernelSU Next!</string>
|
||||||
<string name="home_kernel">Versione Kernel</string>
|
<string name="home_kernel">Versione Kernel</string>
|
||||||
|
<string name="hook_mode">Modalità Hook</string>
|
||||||
<string name="enabled">Abilitato</string>
|
<string name="enabled">Abilitato</string>
|
||||||
<string name="disabled">Disabilitato</string>
|
<string name="disabled">Disabilitato</string>
|
||||||
<string name="susfs_supported">Supportato</string>
|
<string name="susfs_supported">Supportato</string>
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Versione Android</string>
|
<string name="home_android">Versione Android</string>
|
||||||
<string name="home_manager_version">Versione del manager</string>
|
<string name="home_manager_version">Versione del manager</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
<string name="home_selinux_status">Stato di SELinux</string>
|
<string name="home_selinux_status">Stato di SELinux</string>
|
||||||
<string name="selinux_status_disabled">Disabilitato</string>
|
<string name="selinux_status_disabled">Disabilitato</string>
|
||||||
<string name="selinux_status_enforcing">Enforcing</string>
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
@@ -123,7 +127,7 @@
|
|||||||
<string name="require_kernel_version">La versione attualmente installata di KernelSU Next %1$d è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %2$d o successiva!</string>
|
<string name="require_kernel_version">La versione attualmente installata di KernelSU Next %1$d è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %2$d o successiva!</string>
|
||||||
<string name="settings_umount_modules_default">Scollega moduli</string>
|
<string name="settings_umount_modules_default">Scollega moduli</string>
|
||||||
<string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string>
|
<string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string>
|
||||||
<string name="settings_susfs_toggle">Nascondi kprobe hooks</string>
|
<string name="settings_susfs_toggle">Nascondi kprobes hook</string>
|
||||||
<string name="settings_susfs_toggle_summary">Questa opzione disabilita gli hook kprobe creati da ksu e, al loro posto, attiva gli hook non-kprobe incorporati, implementando la stessa funzionalità che verrebbe applicata a un kernel non-GKI, che non supporta kprobe.</string>
|
<string name="settings_susfs_toggle_summary">Questa opzione disabilita gli hook kprobe creati da ksu e, al loro posto, attiva gli hook non-kprobe incorporati, implementando la stessa funzionalità che verrebbe applicata a un kernel non-GKI, che non supporta kprobe.</string>
|
||||||
<string name="profile_umount_modules_summary">Attivando questa opzione permetterai a KernelSU Next di ripristinare ogni file modificato dai moduli per questa app.</string>
|
<string name="profile_umount_modules_summary">Attivando questa opzione permetterai a KernelSU Next di ripristinare ogni file modificato dai moduli per questa app.</string>
|
||||||
<string name="profile_selinux_domain">Dominio</string>
|
<string name="profile_selinux_domain">Dominio</string>
|
||||||
@@ -176,7 +180,7 @@
|
|||||||
<string name="select_file_tip">Si consiglia l\'immagine della partizione %1$s</string>
|
<string name="select_file_tip">Si consiglia l\'immagine della partizione %1$s</string>
|
||||||
<string name="select_kmi">Scegli il KMI</string>
|
<string name="select_kmi">Scegli il KMI</string>
|
||||||
<string name="shrink_sparse_image">Riduci al minimo l\'immagine sparse</string>
|
<string name="shrink_sparse_image">Riduci al minimo l\'immagine sparse</string>
|
||||||
<string name="shrink_sparse_image_message">Ridimensiona l\'immagine sparse dei moduli alla sua reale dimensione. Nota che questo potrebbe causare malfunzionamenti dei moduli, quindi utilizzala solo quando necessario (Come per il backup)).</string>
|
<string name="shrink_sparse_image_message">Ridimensiona l\'immagine sparse dei moduli alla sua reale dimensione. Nota che questo potrebbe causare malfunzionamenti dei moduli, quindi utilizzala solo quando necessario (Come per il backup).</string>
|
||||||
<string name="settings_uninstall">Disinstalla</string>
|
<string name="settings_uninstall">Disinstalla</string>
|
||||||
<string name="settings_uninstall_temporary">Disinstalla temporaneamente</string>
|
<string name="settings_uninstall_temporary">Disinstalla temporaneamente</string>
|
||||||
<string name="settings_uninstall_permanent">Disinstalla permanentemente</string>
|
<string name="settings_uninstall_permanent">Disinstalla permanentemente</string>
|
||||||
@@ -194,4 +198,8 @@
|
|||||||
<string name="settings_disable_su">Disabilita la compatibilità su</string>
|
<string name="settings_disable_su">Disabilita la compatibilità su</string>
|
||||||
<string name="settings_disable_su_summary">Disattiva temporaneamente la possibilità per qualsiasi app di ottenere privilegi di root tramite il comando su (i processi di root esistenti non saranno interessati).</string>
|
<string name="settings_disable_su_summary">Disattiva temporaneamente la possibilità per qualsiasi app di ottenere privilegi di root tramite il comando su (i processi di root esistenti non saranno interessati).</string>
|
||||||
<string name="settings_language">Lingua</string>
|
<string name="settings_language">Lingua</string>
|
||||||
|
<string name="use_webuix">Usa WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Usa WebUI X invece di WebUI che supporta più API</string>
|
||||||
|
<string name="use_webuix_eruda">Iniettare Eruda in WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Inietta una console di debug in WebUI X per semplificare il debug. Richiede che il debug web sia attivo.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
<string name="home">Início</string>
|
<string name="home">Início</string>
|
||||||
<string name="home_not_installed">Não instalado</string>
|
<string name="home_not_installed">Não instalado</string>
|
||||||
<string name="home_click_to_install">Clique para instalar</string>
|
<string name="home_click_to_install">Clique para instalar</string>
|
||||||
|
<string name="lkm_mode_deprecated">O modo LKM agora está obsoleto!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Instale o kernel GKI ou integre o KernelSU Next ao seu dispositivo.</string>
|
||||||
<string name="home_working">Em execução</string>
|
<string name="home_working">Em execução</string>
|
||||||
<string name="home_working_version">Versão: %d</string>
|
<string name="home_working_version">Versão: %d</string>
|
||||||
<string name="home_superuser_count">SuperUsuários: %d</string>
|
<string name="home_superuser_count">SuperUsuários: %d</string>
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || != size/hash ]</string>
|
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||||
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
|
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
|
||||||
<string name="home_kernel">Versão do kernel</string>
|
<string name="home_kernel">Versão do kernel</string>
|
||||||
|
<string name="hook_mode">Modo do hook</string>
|
||||||
<string name="enabled">Ativado</string>
|
<string name="enabled">Ativado</string>
|
||||||
<string name="disabled">Desativado</string>
|
<string name="disabled">Desativado</string>
|
||||||
<string name="susfs_supported">Suportado</string>
|
<string name="susfs_supported">Suportado</string>
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Versão do Android</string>
|
<string name="home_android">Versão do Android</string>
|
||||||
<string name="home_manager_version">Versão do gerenciador</string>
|
<string name="home_manager_version">Versão do gerenciador</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
<string name="home_selinux_status">Status do SELinux</string>
|
<string name="home_selinux_status">Status do SELinux</string>
|
||||||
<string name="selinux_status_disabled">Desativado</string>
|
<string name="selinux_status_disabled">Desativado</string>
|
||||||
<string name="selinux_status_enforcing">Impondo</string>
|
<string name="selinux_status_enforcing">Impondo</string>
|
||||||
@@ -96,6 +100,7 @@
|
|||||||
<string name="proceed">Prosseguir</string>
|
<string name="proceed">Prosseguir</string>
|
||||||
<string name="cancel">Cancelar</string>
|
<string name="cancel">Cancelar</string>
|
||||||
<string name="later">Mais tarde</string>
|
<string name="later">Mais tarde</string>
|
||||||
|
<string name="lkm_warning_message">O patch LKM depende de componentes de código fechado. Deseja continuar?</string>
|
||||||
<string name="home_next_kernelsu">🔥 Compilação next</string>
|
<string name="home_next_kernelsu">🔥 Compilação next</string>
|
||||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||||
<string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string>
|
<string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string>
|
||||||
@@ -123,8 +128,8 @@
|
|||||||
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string>
|
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string>
|
||||||
<string name="settings_umount_modules_default">Desmontar módulos</string>
|
<string name="settings_umount_modules_default">Desmontar módulos</string>
|
||||||
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string>
|
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string>
|
||||||
<string name="settings_susfs_toggle">Ocultar ganchos kprobe</string>
|
<string name="settings_susfs_toggle">Ocultar hook kprobes</string>
|
||||||
<string name="settings_susfs_toggle_summary">Esta opção desativa os ganchos kprobe criados pelo ksu e, em vez disso, ativa os ganchos embutidos não-kprobe, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string>
|
<string name="settings_susfs_toggle_summary">Esta opção desativa os hook kprobes criados pelo ksu e, em vez disso, ativa os hooks embutidos não-kprobes, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string>
|
||||||
<string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string>
|
<string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string>
|
||||||
<string name="profile_selinux_domain">Domínio</string>
|
<string name="profile_selinux_domain">Domínio</string>
|
||||||
<string name="profile_selinux_rules">Regras</string>
|
<string name="profile_selinux_rules">Regras</string>
|
||||||
@@ -194,4 +199,8 @@
|
|||||||
<string name="settings_disable_su">Desativar compatibilidade su</string>
|
<string name="settings_disable_su">Desativar compatibilidade su</string>
|
||||||
<string name="settings_disable_su_summary">Desative temporariamente a capacidade de qualquer app obter privilégios root por meio do comando su (processos root existentes não serão afetados).</string>
|
<string name="settings_disable_su_summary">Desative temporariamente a capacidade de qualquer app obter privilégios root por meio do comando su (processos root existentes não serão afetados).</string>
|
||||||
<string name="settings_language">Idioma</string>
|
<string name="settings_language">Idioma</string>
|
||||||
|
<string name="use_webuix">Usar WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Use o WebUI X em vez do WebUI, que oferece suporte a mais APIs.</string>
|
||||||
|
<string name="use_webuix_eruda">Injetar Eruda no WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Injeta um console de depuração no WebUI X para facilitar a depuração. Requer que a depuração web esteja ativada.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
<string name="home">Главная</string>
|
<string name="home">Главная</string>
|
||||||
<string name="home_not_installed">Не установлено</string>
|
<string name="home_not_installed">Не установлено</string>
|
||||||
<string name="home_click_to_install">Нажмите, чтобы установить</string>
|
<string name="home_click_to_install">Нажмите, чтобы установить</string>
|
||||||
|
<string name="lkm_mode_deprecated">Режим LKM теперь устарел!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Установите GKI ядро или интегрируйте ядра рядом с вашим устройством.</string>
|
||||||
<string name="home_working">Работает</string>
|
<string name="home_working">Работает</string>
|
||||||
<string name="home_working_version">Версия: %d</string>
|
<string name="home_working_version">Версия: %d</string>
|
||||||
<string name="home_superuser_count">Superusers: %d</string>
|
<string name="home_superuser_count">Superusers: %d</string>
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [!KSU_NEXT || != size/hash]</string>
|
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [!KSU_NEXT || != size/hash]</string>
|
||||||
<string name="home_failure_tip">Попросите вашего разработчика ядра интегрировать KernelSU Next!</string>
|
<string name="home_failure_tip">Попросите вашего разработчика ядра интегрировать KernelSU Next!</string>
|
||||||
<string name="home_kernel">Версия ядра</string>
|
<string name="home_kernel">Версия ядра</string>
|
||||||
|
<string name="hook_mode">Режим хуков</string>
|
||||||
<string name="disabled">Отключено</string>
|
<string name="disabled">Отключено</string>
|
||||||
<string name="enabled">Включено</string>
|
<string name="enabled">Включено</string>
|
||||||
<string name="susfs_supported">Поддерживается</string>
|
<string name="susfs_supported">Поддерживается</string>
|
||||||
@@ -27,12 +30,13 @@
|
|||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Версия Android</string>
|
<string name="home_android">Версия Android</string>
|
||||||
<string name="home_manager_version">Версия менеджера</string>
|
<string name="home_manager_version">Версия менеджера</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
<string name="home_selinux_status">Статус SELinux</string>
|
<string name="home_selinux_status">Статус SELinux</string>
|
||||||
<string name="selinux_status_disabled">Отключен</string>
|
<string name="selinux_status_disabled">Отключен</string>
|
||||||
<string name="selinux_status_enforcing">Принудительный</string>
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
<string name="selinux_status_permissive">Разрешающий</string>
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
<string name="selinux_status_unknown">Неизвестно</string>
|
<string name="selinux_status_unknown">Неизвестно</string>
|
||||||
<string name="superuser">SuperUser</string>
|
<string name="superuser">Superuser</string>
|
||||||
<string name="module_failed_to_enable">Не удалось включить модуль: %s</string>
|
<string name="module_failed_to_enable">Не удалось включить модуль: %s</string>
|
||||||
<string name="module_failed_to_disable">Не удалось отключить модуль: %s</string>
|
<string name="module_failed_to_disable">Не удалось отключить модуль: %s</string>
|
||||||
<string name="module_empty">Нет установленных модулей</string>
|
<string name="module_empty">Нет установленных модулей</string>
|
||||||
@@ -60,11 +64,11 @@
|
|||||||
<string name="module_restore_failed">Не удалось восстановить: %s</string>
|
<string name="module_restore_failed">Не удалось восстановить: %s</string>
|
||||||
<string name="module_version">Версия</string>
|
<string name="module_version">Версия</string>
|
||||||
<string name="module_author">Автор</string>
|
<string name="module_author">Автор</string>
|
||||||
<string name="module_id">Идентификатор</string>
|
<string name="module_id">ID</string>
|
||||||
<string name="module_version_code">Код версии</string>
|
<string name="module_version_code">Код версии</string>
|
||||||
<string name="module_update_json">UpdateJson</string>
|
<string name="module_update_json">UpdateJson</string>
|
||||||
<string name="module_update_json_empty">Пусто</string>
|
<string name="module_update_json_empty">Пусто</string>
|
||||||
<string name="enable_developer_options">Включить настройки разработчика</string>
|
<string name="enable_developer_options">Режим разработчика</string>
|
||||||
<string name="enable_developer_options_summary">Показывать скрытые настройки и отладочную информацию, актуальную только для разработчиков.</string>
|
<string name="enable_developer_options_summary">Показывать скрытые настройки и отладочную информацию, актуальную только для разработчиков.</string>
|
||||||
<string name="module_overlay_fs_not_available">Модули недоступны, так как OverlayFS отключен ядром.</string>
|
<string name="module_overlay_fs_not_available">Модули недоступны, так как OverlayFS отключен ядром.</string>
|
||||||
<string name="refresh">Обновить</string>
|
<string name="refresh">Обновить</string>
|
||||||
@@ -74,23 +78,23 @@
|
|||||||
<string name="safe_mode">Безопасный режим</string>
|
<string name="safe_mode">Безопасный режим</string>
|
||||||
<string name="reboot_to_apply">Перезагрузите для применения</string>
|
<string name="reboot_to_apply">Перезагрузите для применения</string>
|
||||||
<string name="module_magisk_conflict">Модули недоступны из-за конфликта с Magisk!</string>
|
<string name="module_magisk_conflict">Модули недоступны из-за конфликта с Magisk!</string>
|
||||||
<string name="home_mount_system">Система монтирования модулей</string>
|
<string name="home_mount_system">Система монтирования</string>
|
||||||
<string name="home_magic_mount">Magic Mount</string>
|
<string name="home_magic_mount">Magic Mount</string>
|
||||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
<string name="unavailable">Недоступно</string>
|
<string name="unavailable">Недоступно</string>
|
||||||
<string name="use_overlay_fs">Использовать OverlayFS (Бета)</string>
|
<string name="use_overlay_fs">Использовать OverlayFS</string>
|
||||||
<string name="use_overlay_fs_summary">Переключение между использованием OverlayFS и Magic Mount для системы монтирования KernelSU Next.</string>
|
<string name="use_overlay_fs_summary">Переключение между использованием OverlayFS и Magic Mount для системы монтирования KernelSU Next.</string>
|
||||||
<string name="reboot_required">Требуется перезагрузка</string>
|
<string name="reboot_required">Требуется перезагрузка</string>
|
||||||
<string name="reboot_message">Изменения вступят в силу после перезагрузки системы. Перезагрузить сейчас?</string>
|
<string name="reboot_message">Изменения вступят в силу после перезагрузки системы. Перезагрузить сейчас?</string>
|
||||||
<string name="module_restore">Восстановить модуль</string>
|
<string name="module_restore">Восстановить модули</string>
|
||||||
<string name="module_restore_message">Восстановление модулей из последней резервной копии.</string>
|
<string name="module_restore_message">Восстановление модулей из последней резервной копии.</string>
|
||||||
<string name="backup_restore">Резервное копирование и восстановление</string>
|
<string name="backup_restore">Бэкапы и восстановление</string>
|
||||||
<string name="module_backup">Резервное копирование модуля</string>
|
<string name="module_backup">Бэкап модулей</string>
|
||||||
<string name="module_backup_message">Резервное копирование текущих установленных модулей.</string>
|
<string name="module_backup_message">Резервное копирование текущих установленных модулей.</string>
|
||||||
<string name="allowlist_restore">Восстановить список разрешений</string>
|
<string name="allowlist_restore">Восстановить список разрешений</string>
|
||||||
<string name="allowlist_restore_message">Восстановить список разрешений из последнего резервного копирования.</string>
|
<string name="allowlist_restore_message">Восстановить список разрешений из последнего резервного копирования.</string>
|
||||||
<string name="allowlist_backup">Создать резервную копию списка разрешений</string>
|
<string name="allowlist_backup">Бэкап списка разрешений</string>
|
||||||
<string name="allowlist_backup_message">Создать резервную копию текущего списка разрешений.</string>
|
<string name="allowlist_backup_message">Резервное копирование текущего списка разрешений.</string>
|
||||||
<string name="warning">Предупреждение</string>
|
<string name="warning">Предупреждение</string>
|
||||||
<string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string>
|
<string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string>
|
||||||
<string name="proceed">Продолжить</string>
|
<string name="proceed">Продолжить</string>
|
||||||
@@ -106,10 +110,10 @@
|
|||||||
<string name="home_experimental_kernelsu_body_point_2"> • Предупреждение: разработчики не несут ответственности за потерю данных, повреждение системы или другие последствия, вызванные использованием.</string>
|
<string name="home_experimental_kernelsu_body_point_2"> • Предупреждение: разработчики не несут ответственности за потерю данных, повреждение системы или другие последствия, вызванные использованием.</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_3"> • Только для тестирования: предназначено для пользователей, которые понимают риски и готовы решать возникающие проблемы.</string>
|
<string name="home_experimental_kernelsu_body_point_3"> • Только для тестирования: предназначено для пользователей, которые понимают риски и готовы решать возникающие проблемы.</string>
|
||||||
<string name="about_source_code"><![CDATA[Посмотреть исходный код на %1$s]]></string>
|
<string name="about_source_code"><![CDATA[Посмотреть исходный код на %1$s]]></string>
|
||||||
<string name="profile" translatable="false">Профиль приложения</string>
|
<string name="profile" translatable="false">Профиль Приложения</string>
|
||||||
<string name="profile_default">По умолчанию</string>
|
<string name="profile_default">По умолчанию</string>
|
||||||
<string name="profile_template">Шаблон</string>
|
<string name="profile_template">Шаблон</string>
|
||||||
<string name="profile_custom">Пользовательский</string>
|
<string name="profile_custom">Настроить</string>
|
||||||
<string name="profile_name">Имя профиля</string>
|
<string name="profile_name">Имя профиля</string>
|
||||||
<string name="profile_namespace">Пространство монтирования</string>
|
<string name="profile_namespace">Пространство монтирования</string>
|
||||||
<string name="profile_namespace_inherited">Унаследовано</string>
|
<string name="profile_namespace_inherited">Унаследовано</string>
|
||||||
@@ -119,12 +123,12 @@
|
|||||||
<string name="profile_capabilities">Возможности</string>
|
<string name="profile_capabilities">Возможности</string>
|
||||||
<string name="profile_selinux_context">Контекст SELinux</string>
|
<string name="profile_selinux_context">Контекст SELinux</string>
|
||||||
<string name="profile_umount_modules">Отключить модули</string>
|
<string name="profile_umount_modules">Отключить модули</string>
|
||||||
<string name="failed_to_update_app_profile">Не удалось обновить профиль приложения для %s</string>
|
<string name="failed_to_update_app_profile">Не удалось обновить Профиль Приложения для %s</string>
|
||||||
<string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string>
|
<string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string>
|
||||||
<string name="settings_umount_modules_default">Отмонтировать модули</string>
|
<string name="settings_umount_modules_default">Отключить модули</string>
|
||||||
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в профиле приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string>
|
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в Профиле Приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string>
|
||||||
<string name="settings_susfs_toggle">Скрыть хуки kprobe</string>
|
<string name="settings_susfs_toggle">Скрыть хук kprobes</string>
|
||||||
<string name="settings_susfs_toggle_summary">Отключает хуки kprobe, созданные ksu, и вместо этого активирует встроенные функции, реализующие ту же функциональность для ядер, которые не поддерживают kprobe.</string>
|
<string name="settings_susfs_toggle_summary">Эта опция отключает хук kprobes, созданный ksu, и вместо него активирует встроенный хук без использования kprobes, реализующий ту же функциональность, которая применяется к ядрам без GKI, не поддерживающим kprobe.</string>
|
||||||
<string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string>
|
<string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string>
|
||||||
<string name="profile_selinux_domain">Домен</string>
|
<string name="profile_selinux_domain">Домен</string>
|
||||||
<string name="profile_selinux_rules">Правила</string>
|
<string name="profile_selinux_rules">Правила</string>
|
||||||
@@ -139,8 +143,8 @@
|
|||||||
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для: %s</string>
|
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для: %s</string>
|
||||||
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
|
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
|
||||||
<string name="module_changelog">Журнал изменений</string>
|
<string name="module_changelog">Журнал изменений</string>
|
||||||
<string name="settings_profile_template">Шаблон профиля приложений</string>
|
<string name="settings_profile_template">Шаблон Профиля Приложений</string>
|
||||||
<string name="settings_profile_template_summary">Управление локальными и онлайн-шаблонами профилей приложений</string>
|
<string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами Профилей Приложений</string>
|
||||||
<string name="app_profile_template_create">Создать шаблон</string>
|
<string name="app_profile_template_create">Создать шаблон</string>
|
||||||
<string name="app_profile_template_edit">Редактировать шаблон</string>
|
<string name="app_profile_template_edit">Редактировать шаблон</string>
|
||||||
<string name="app_profile_template_id">Идентификатор</string>
|
<string name="app_profile_template_id">Идентификатор</string>
|
||||||
@@ -161,16 +165,16 @@
|
|||||||
<string name="app_profile_template_save_failed">Не удалось сохранить шаблон</string>
|
<string name="app_profile_template_save_failed">Не удалось сохранить шаблон</string>
|
||||||
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
|
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
|
||||||
<string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string>
|
<string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string>
|
||||||
<string name="settings_check_update">Проверить обновления</string>
|
<string name="settings_check_update">Проверять обновления</string>
|
||||||
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
|
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
|
||||||
<string name="grant_root_failed">Не удалось предоставить root-доступ!</string>
|
<string name="grant_root_failed">Не удалось предоставить root-доступ!</string>
|
||||||
<string name="action">Действие</string>
|
<string name="action">Запустить</string>
|
||||||
<string name="open">Открыть</string>
|
<string name="open">Открыть</string>
|
||||||
<string name="enable_web_debugging">Включить отладку WebView</string>
|
<string name="enable_web_debugging">Отладка WebView</string>
|
||||||
<string name="enable_web_debugging_summary">Можно использовать для отладки WebUI. Включайте только при необходимости.</string>
|
<string name="enable_web_debugging_summary">Можно использовать для отладки WebUI. Включайте только при необходимости.</string>
|
||||||
<string name="direct_install">Прямая установка (Рекомендуется)</string>
|
<string name="direct_install">Прямая установка (Рекомендуется)</string>
|
||||||
<string name="select_file">Выберите файл</string>
|
<string name="select_file">Выберите файл</string>
|
||||||
<string name="install_inactive_slot">Установить в неактивный слот (После OTA)</string>
|
<string name="install_inactive_slot">В неактивный слот (После OTA)</string>
|
||||||
<string name="install_inactive_slot_warning">Ваше устройство будет **ПРИНУДИТЕЛЬНО** загружено в текущий неактивный слот после перезагрузки!\nИспользуйте эту опцию только после завершения OTA.\nПродолжить?</string>
|
<string name="install_inactive_slot_warning">Ваше устройство будет **ПРИНУДИТЕЛЬНО** загружено в текущий неактивный слот после перезагрузки!\nИспользуйте эту опцию только после завершения OTA.\nПродолжить?</string>
|
||||||
<string name="install_next">Далее</string>
|
<string name="install_next">Далее</string>
|
||||||
<string name="select_file_tip">Рекомендуется образ раздела %1$s</string>
|
<string name="select_file_tip">Рекомендуется образ раздела %1$s</string>
|
||||||
@@ -191,6 +195,11 @@
|
|||||||
<string name="save_log">Сохранить логи</string>
|
<string name="save_log">Сохранить логи</string>
|
||||||
<string name="log_saved">Логи сохранены</string>
|
<string name="log_saved">Логи сохранены</string>
|
||||||
<string name="send_log">Поделиться логами</string>
|
<string name="send_log">Поделиться логами</string>
|
||||||
<string name="settings_disable_su">Отключить совместимость с su</string>
|
<string name="settings_disable_su">Откл. совместимость с su</string>
|
||||||
<string name="settings_disable_su_summary">Временно отключить возможность приложениям получать права root через команду su (существующие сеансы с правами root не будут затронуты).</string>
|
<string name="settings_disable_su_summary">Временно отключить возможность приложениям получать права root через команду su (существующие процессы с правами root не будут затронуты).</string>
|
||||||
|
<string name="settings_language">Язык</string>
|
||||||
|
<string name="use_webuix">Использовать WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Использовать WebUI X вместо WebUI, который поддерживает больше API.</string>
|
||||||
|
<string name="use_webuix_eruda">Инжект Eruda в WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Инжектить консоль отладки в WebUI X, чтобы упростить отладку. Требуется включить отладку WebView.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -109,8 +109,8 @@
|
|||||||
<string name="require_kernel_version">KernelSU Next เวอร์ชัน %1$d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถทำงานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชัน %2$d หรือสูงกว่า!</string>
|
<string name="require_kernel_version">KernelSU Next เวอร์ชัน %1$d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถทำงานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชัน %2$d หรือสูงกว่า!</string>
|
||||||
<string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string>
|
<string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string>
|
||||||
<string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string>
|
<string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string>
|
||||||
<string name="settings_susfs_toggle">ซ่อน kprobe hooks</string>
|
<string name="settings_susfs_toggle">ซ่อน kprobes hook</string>
|
||||||
<string name="settings_susfs_toggle_summary">จะปิดใช้งาน kprobe hooks ที่สร้างโดย ksu และเปิดใช้งาน non-kprobe hooks ที่ฝังไว้แทน โดยใช้ฟังก์ชันการทำงานเดียวกันกับที่ใช้กับเคอร์เนลที่ไม่ใช่ GKI ซึ่งไม่รองรับ</string>
|
<string name="settings_susfs_toggle_summary">จะปิดใช้งาน kprobes hook ที่สร้างโดย ksu และเปิดใช้งาน non-kprobes hook ที่ฝังไว้แทน โดยใช้ฟังก์ชันการทำงานเดียวกันกับที่ใช้กับเคอร์เนลที่ไม่ใช่ GKI ซึ่งไม่รองรับ</string>
|
||||||
<string name="profile_umount_modules_summary">การเปิดใช้งานตัวเลือกนี้จะทำให้ KernelSU Next สามารถกู้คืนไฟล์ที่แก้ไขโดยโมดูลสำหรับแอปนี้ได้</string>
|
<string name="profile_umount_modules_summary">การเปิดใช้งานตัวเลือกนี้จะทำให้ KernelSU Next สามารถกู้คืนไฟล์ที่แก้ไขโดยโมดูลสำหรับแอปนี้ได้</string>
|
||||||
<string name="profile_selinux_domain">โดเมน</string>
|
<string name="profile_selinux_domain">โดเมน</string>
|
||||||
<string name="profile_selinux_rules">กฎ</string>
|
<string name="profile_selinux_rules">กฎ</string>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
<string name="home">Ana Sayfa</string>
|
<string name="home">Ana Sayfa</string>
|
||||||
<string name="home_not_installed">Yüklü değil</string>
|
<string name="home_not_installed">Yüklü değil</string>
|
||||||
<string name="home_click_to_install">Yüklemek için tıklayın</string>
|
<string name="home_click_to_install">Yüklemek için tıklayın</string>
|
||||||
|
<string name="lkm_mode_deprecated">LKM modu artık kullanımdan kaldırıldı!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">GKI çekirdeğini kurun veya cihazınıza KernelSU Next entegre edin.</string>
|
||||||
<string name="home_working">Çalışıyor</string>
|
<string name="home_working">Çalışıyor</string>
|
||||||
<string name="home_working_version">Sürüm: %d</string>
|
<string name="home_working_version">Sürüm: %d</string>
|
||||||
<string name="home_superuser_count">Süper kullanıcılar: %d</string>
|
<string name="home_superuser_count">Süper kullanıcılar: %d</string>
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
<string name="home_failure">Kernel\'de KernelSU Next v2 imzası bulunamadı! [ !KSU_NEXT || != boyut/hash ]</string>
|
<string name="home_failure">Kernel\'de KernelSU Next v2 imzası bulunamadı! [ !KSU_NEXT || != boyut/hash ]</string>
|
||||||
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmesini isteyin!</string>
|
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmesini isteyin!</string>
|
||||||
<string name="home_kernel">Kernel sürümü</string>
|
<string name="home_kernel">Kernel sürümü</string>
|
||||||
|
<string name="hook_mode">Kanca Modu</string>
|
||||||
<string name="enabled">Etkin</string>
|
<string name="enabled">Etkin</string>
|
||||||
<string name="disabled">Devre dışı</string>
|
<string name="disabled">Devre dışı</string>
|
||||||
<string name="susfs_supported">Destekleniyor</string>
|
<string name="susfs_supported">Destekleniyor</string>
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Android sürümü</string>
|
<string name="home_android">Android sürümü</string>
|
||||||
<string name="home_manager_version">Yönetici sürümü</string>
|
<string name="home_manager_version">Yönetici sürümü</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
<string name="home_selinux_status">SELinux durumu</string>
|
<string name="home_selinux_status">SELinux durumu</string>
|
||||||
<string name="selinux_status_disabled">Devre dışı</string>
|
<string name="selinux_status_disabled">Devre dışı</string>
|
||||||
<string name="selinux_status_enforcing">Etkin (Enforcing)</string>
|
<string name="selinux_status_enforcing">Etkin (Enforcing)</string>
|
||||||
@@ -194,4 +198,8 @@
|
|||||||
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
|
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
|
||||||
<string name="settings_disable_su_summary">Geçici olarak herhangi bir uygulamanın su komutu aracılığıyla kök ayrıcalıkları elde etme yeteneğini devre dışı bırakır (mevcut kök süreçleri etkilenmez).</string>
|
<string name="settings_disable_su_summary">Geçici olarak herhangi bir uygulamanın su komutu aracılığıyla kök ayrıcalıkları elde etme yeteneğini devre dışı bırakır (mevcut kök süreçleri etkilenmez).</string>
|
||||||
<string name="settings_language">Dil</string>
|
<string name="settings_language">Dil</string>
|
||||||
|
<string name="use_webuix">WebUI X\'i kullanın</string>
|
||||||
|
<string name="use_webuix_summary">Daha fazla API\'yi destekleyen WebUI yerine WebUI X kullanın</string>
|
||||||
|
<string name="use_webuix_eruda">WebUI X\'e Eruda Enjekte Et</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Hata ayıklamayı kolaylaştırmak için WebUI X\'e bir debug konsolu enjekte edin. Web hata ayıklamanın açık olması gerekir.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
205
manager/app/src/main/res/values-uk/strings.xml
Normal file
205
manager/app/src/main/res/values-uk/strings.xml
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="issue_report_title">Виникли проблеми?</string>
|
||||||
|
<string name="issue_report_body">Виявлено помилку або є зворотній зв’язок?</string>
|
||||||
|
<string name="issue_report_body_2">Повідомте про це якнайшвидше!</string>
|
||||||
|
<string name="issue_report_github">Повідомити на GitHub</string>
|
||||||
|
<string name="issue_report_telegram">Зв’язатися через Telegram</string>
|
||||||
|
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||||
|
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||||
|
<string name="confirm">Підтвердити</string>
|
||||||
|
<string name="app_name" translatable="false">KernelSU Next</string>
|
||||||
|
<string name="home">Головна</string>
|
||||||
|
<string name="home_not_installed">Не встановлено</string>
|
||||||
|
<string name="home_click_to_install">Натисніть, щоб встановити</string>
|
||||||
|
<string name="lkm_mode_deprecated">Режим LKM тепер застарілий!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Встановіть ядро GKI або інтегруйте ядра поруч із вашим пристроєм.</string>
|
||||||
|
<string name="home_working">Працює</string>
|
||||||
|
<string name="home_working_version">Версія: %d</string>
|
||||||
|
<string name="home_superuser_count">SuperUsers: %d</string>
|
||||||
|
<string name="home_module_count">Модулі: %d</string>
|
||||||
|
<string name="home_failure">Підпис KernelSU Next v2 не знайдено в ядрі! [!KSU_NEXT || != size/hash]</string>
|
||||||
|
<string name="home_failure_tip">Попросіть вашого розробника ядра інтегрувати KernelSU Next!</string>
|
||||||
|
<string name="home_kernel">Версія ядра</string>
|
||||||
|
<string name="hook_mode">Режим хуків</string>
|
||||||
|
<string name="disabled">Вимкнено</string>
|
||||||
|
<string name="enabled">Увімкнено</string>
|
||||||
|
<string name="susfs_supported">Підтримується</string>
|
||||||
|
<string name="home_susfs">SuSFS: %s</string>
|
||||||
|
<string name="home_susfs_version">Версія SuSFS</string>
|
||||||
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
|
<string name="home_android">Версія Android</string>
|
||||||
|
<string name="home_manager_version">Версія менеджера</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
|
<string name="home_selinux_status">Статус SELinux</string>
|
||||||
|
<string name="selinux_status_disabled">Вимкнено</string>
|
||||||
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
|
<string name="selinux_status_unknown">Невідомо</string>
|
||||||
|
<string name="superuser">SuperUser</string>
|
||||||
|
<string name="module_failed_to_enable">Не вдалося увімкнути модуль: %s</string>
|
||||||
|
<string name="module_failed_to_disable">Не вдалося вимкнути модуль: %s</string>
|
||||||
|
<string name="module_empty">Нема встановлених модулів</string>
|
||||||
|
<string name="module">Модулі</string>
|
||||||
|
<string name="module_install_prompt_with_name">Наступні модуль(і) будуть встановлені: %1$s</string>
|
||||||
|
<string name="module_sort_a_to_z">Сортувати (А-Я)</string>
|
||||||
|
<string name="module_sort_z_to_a">Сортувати (Я-А)</string>
|
||||||
|
<string name="uninstall">Видалити</string>
|
||||||
|
<string name="restore">Відновити</string>
|
||||||
|
<string name="module_install">Встановити</string>
|
||||||
|
<string name="install">Встановити</string>
|
||||||
|
<string name="reboot">Перезавантаження</string>
|
||||||
|
<string name="settings">Налаштування</string>
|
||||||
|
<string name="reboot_userspace">М’яка перезавантаження</string>
|
||||||
|
<string name="reboot_recovery">Перезавантаження в Recovery</string>
|
||||||
|
<string name="reboot_bootloader">Перезавантаження в Bootloader</string>
|
||||||
|
<string name="reboot_download">Перезавантаження в Download</string>
|
||||||
|
<string name="reboot_edl">Перезавантаження в EDL</string>
|
||||||
|
<string name="about">Про програму</string>
|
||||||
|
<string name="module_uninstall_confirm">Ви впевнені, що хочете видалити модуль %s?</string>
|
||||||
|
<string name="module_uninstall_success">%s видалено</string>
|
||||||
|
<string name="module_uninstall_failed">Не вдалося видалити: %s</string>
|
||||||
|
<string name="module_restore_confirm">Ви впевнені, що хочете відновити модуль %s?</string>
|
||||||
|
<string name="module_restore_success">%s відновлено</string>
|
||||||
|
<string name="module_restore_failed">Не вдалося відновити: %s</string>
|
||||||
|
<string name="module_version">Версія</string>
|
||||||
|
<string name="module_author">Автор</string>
|
||||||
|
<string name="module_id">ID</string>
|
||||||
|
<string name="module_version_code">Код версії</string>
|
||||||
|
<string name="module_update_json">UpdateJson</string>
|
||||||
|
<string name="module_update_json_empty">Порожньо</string>
|
||||||
|
<string name="enable_developer_options">Режим розробника</string>
|
||||||
|
<string name="enable_developer_options_summary">Показувати приховані налаштування і відладкову інформацію, актуальну лише для розробників.</string>
|
||||||
|
<string name="module_overlay_fs_not_available">Модулі недоступні, оскільки OverlayFS вимкнено ядром.</string>
|
||||||
|
<string name="refresh">Оновити</string>
|
||||||
|
<string name="show_system_apps">Показати системні додатки</string>
|
||||||
|
<string name="hide_system_apps">Сховати системні додатки</string>
|
||||||
|
<string name="export_log">Експорт логів</string>
|
||||||
|
<string name="safe_mode">Безпечний режим</string>
|
||||||
|
<string name="reboot_to_apply">Перезавантажте для застосування</string>
|
||||||
|
<string name="module_magisk_conflict">Модулі недоступні через конфлікт з Magisk!</string>
|
||||||
|
<string name="home_mount_system">Система монтування</string>
|
||||||
|
<string name="home_magic_mount">Magic Mount</string>
|
||||||
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
|
<string name="unavailable">Недоступно</string>
|
||||||
|
<string name="use_overlay_fs">Використовувати OverlayFS</string>
|
||||||
|
<string name="use_overlay_fs_summary">Перемикання між використанням OverlayFS и Magic Mount для системи монтування KernelSU Next.</string>
|
||||||
|
<string name="reboot_required">Потрібно перезавантаження</string>
|
||||||
|
<string name="reboot_message">Зміни вступлять в силу після перезавантаження системи. Перезавантажити зараз?</string>
|
||||||
|
<string name="module_restore">Відновити модуль</string>
|
||||||
|
<string name="module_restore_message">Відновлення модулів із останньої резервної копії.</string>
|
||||||
|
<string name="backup_restore">Резервне копіювання і відновлення</string>
|
||||||
|
<string name="module_backup">Бекап модуля</string>
|
||||||
|
<string name="module_backup_message">Бекап поточних встановлених модулів.</string>
|
||||||
|
<string name="allowlist_restore">Відновити список дозволів</string>
|
||||||
|
<string name="allowlist_restore_message">Відновити список дозволів із останнього резервного копіювання.</string>
|
||||||
|
<string name="allowlist_backup">Бекап списку дозволів</string>
|
||||||
|
<string name="allowlist_backup_message">Бекап поточного списку дозволів.</string>
|
||||||
|
<string name="warning">Попередження</string>
|
||||||
|
<string name="warning_message">Ця функція все ще перебуває у стадії бета-тестування. Будь ласка, переконайтеся, що ви створили резервні копії модулів перед використанням. Використовуйте це лише якщо розумієте можливі ризики. Будьте обережні.</string>
|
||||||
|
<string name="proceed">Продовжити</string>
|
||||||
|
<string name="cancel">Скасувати</string>
|
||||||
|
<string name="later">Пізніше</string>
|
||||||
|
<string name="home_next_kernelsu">🔥 Наступна збірка</string>
|
||||||
|
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||||
|
<string name="home_next_kernelsu_body">Наступна експериментальна гілка. Подивіться на GitHub!</string>
|
||||||
|
<string name="home_experimental_kernelsu">⚠️ Попередження про експериментальну розробку!</string>
|
||||||
|
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||||
|
<string name="home_experimental_kernelsu_body">KernelSU Next — це неофіційна версія, яка завжди перебуває у стадії активної експериментальної розробки. Вона надається як є, без гарантій стабільності, продуктивності чи надійності.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_1"> • Використовуйте на свій страх і ризик: можуть виникати збої, несподівана поведінка або проблеми з системою.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_2"> • Попередження: розробники не несуть відповідальності за втрату даних, пошкодження системи або інші наслідки, викликані використанням.</string>
|
||||||
|
<string name="home_experimental_kernelsu_body_point_3"> • Лише для тестування: призначено для користувачів, які розуміють ризики і готові вирішувати виникаючі проблеми.</string>
|
||||||
|
<string name="about_source_code"><![CDATA[Переглянути вихідний код на %1$s]]></string>
|
||||||
|
<string name="profile" translatable="false">Профіль додатка</string>
|
||||||
|
<string name="profile_default">За замовчуванням</string>
|
||||||
|
<string name="profile_template">Шаблон</string>
|
||||||
|
<string name="profile_custom">Налаштувати</string>
|
||||||
|
<string name="profile_name">Ім’я профілю</string>
|
||||||
|
<string name="profile_namespace">Простір монтування</string>
|
||||||
|
<string name="profile_namespace_inherited">Успадковано</string>
|
||||||
|
<string name="profile_namespace_global">Глобальне</string>
|
||||||
|
<string name="profile_namespace_individual">Індивідуальне</string>
|
||||||
|
<string name="profile_groups">Групи</string>
|
||||||
|
<string name="profile_capabilities">Можливості</string>
|
||||||
|
<string name="profile_selinux_context">Контекст SELinux</string>
|
||||||
|
<string name="profile_umount_modules">Вимкнути модулі</string>
|
||||||
|
<string name="failed_to_update_app_profile">Не вдалося оновити Профіль додатка для %s</string>
|
||||||
|
<string name="require_kernel_version">Поточна версія KernelSU Next %1$d надто низька для коректної роботи менеджера. Будь ласка, оновіться до версії %2$d або вище!</string>
|
||||||
|
<string name="settings_umount_modules_default">Вимкнути модулі</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">Глобальне значення за замовчуванням для \"Вимкнути модулі\" у Профілі додатка. Якщо увімкнено, це видалить усі модифікації системи модулями для додатків без встановленого профілю.</string>
|
||||||
|
<string name="settings_susfs_toggle">Сховати хуки kprobe</string>
|
||||||
|
<string name="settings_susfs_toggle_summary">Вимикає хуки kprobe, створені ksu, і замість цього активує вбудовані функції, що реалізують ту ж функціональність для ядер, які не підтримують kprobe.</string>
|
||||||
|
<string name="profile_umount_modules_summary">Увімкнення цієї опції дозволить KernelSU Next відновлювати будь-які змінені модулями файли для цього додатка.</string>
|
||||||
|
<string name="profile_selinux_domain">Домен</string>
|
||||||
|
<string name="profile_selinux_rules">Правила</string>
|
||||||
|
<string name="module_update">Оновити</string>
|
||||||
|
<string name="module_downloading">Завантаження модуля: %s</string>
|
||||||
|
<string name="module_start_downloading">Початок завантаження: %s</string>
|
||||||
|
<string name="new_version_available">Доступна нова версія %s, натисніть для оновлення.</string>
|
||||||
|
<string name="launch_app">Запустити</string>
|
||||||
|
<string name="close">Закрити</string>
|
||||||
|
<string name="force_stop_app">Примусово зупинити</string>
|
||||||
|
<string name="restart_app">Перезапустити</string>
|
||||||
|
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string>
|
||||||
|
<string name="su_not_allowed">Надання прав суперкористувача заборонено для: %s</string>
|
||||||
|
<string name="module_changelog">Журнал змін</string>
|
||||||
|
<string name="settings_profile_template">Шаблон Профілю додатка</string>
|
||||||
|
<string name="settings_profile_template_summary">Управління локальними та онлайн шаблонами Профілів додатків</string>
|
||||||
|
<string name="app_profile_template_create">Створити шаблон</string>
|
||||||
|
<string name="app_profile_template_edit">Редагувати шаблон</string>
|
||||||
|
<string name="app_profile_template_id">Ідентифікатор</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Неправильний ідентифікатор шаблону</string>
|
||||||
|
<string name="app_profile_template_name">Ім’я</string>
|
||||||
|
<string name="app_profile_template_description">Опис</string>
|
||||||
|
<string name="app_profile_template_save">Зберегти</string>
|
||||||
|
<string name="app_profile_template_delete">Видалити</string>
|
||||||
|
<string name="app_profile_template_view">Перегляд шаблону</string>
|
||||||
|
<string name="app_profile_template_readonly">Тільки для читання</string>
|
||||||
|
<string name="app_profile_template_id_exist">Ідентифікатор шаблону вже існує!</string>
|
||||||
|
<string name="app_profile_import_export">Імпорт/Експорт</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Імпорт із буфера обміну</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Експорт у буфер обміну</string>
|
||||||
|
<string name="app_profile_template_export_empty">Не вдалося знайти локальний шаблон для експорту!</string>
|
||||||
|
<string name="app_profile_template_import_success">Успішно імпортовано</string>
|
||||||
|
<string name="app_profile_template_sync">Синхронізувати онлайн-шаблони</string>
|
||||||
|
<string name="app_profile_template_save_failed">Не вдалося зберегти шаблон</string>
|
||||||
|
<string name="app_profile_template_import_empty">Буфер обміну порожній!</string>
|
||||||
|
<string name="module_changelog_failed">Не вдалося отримати журнал змін: %s</string>
|
||||||
|
<string name="settings_check_update">Перевіряти оновлення</string>
|
||||||
|
<string name="settings_check_update_summary">Автоматично перевіряти оновлення при відкритті додатка.</string>
|
||||||
|
<string name="grant_root_failed">Не вдалося надати root-доступ!</string>
|
||||||
|
<string name="action">Запустити</string>
|
||||||
|
<string name="open">Відкрити</string>
|
||||||
|
<string name="enable_web_debugging">Відладка WebView</string>
|
||||||
|
<string name="enable_web_debugging_summary">Можна використовувати для відладки WebUI. Увімкніть лише при необхідності.</string>
|
||||||
|
<string name="direct_install">Пряма установка (Рекомендовано)</string>
|
||||||
|
<string name="select_file">Виберіть файл</string>
|
||||||
|
<string name="install_inactive_slot">У неактивний слот (Після OTA)</string>
|
||||||
|
<string name="install_inactive_slot_warning">Ваш пристрій буде **ПРИМУСОВО** завантажено у поточний неактивний слот після перезавантаження!\nВикористовуйте цю опцію лише після завершення OTA.\nПродовжити?</string>
|
||||||
|
<string name="install_next">Далі</string>
|
||||||
|
<string name="select_file_tip">Рекомендовано образ розділу %1$s</string>
|
||||||
|
<string name="select_kmi">Виберіть KMI</string>
|
||||||
|
<string name="shrink_sparse_image">Зменшити modules.img образ</string>
|
||||||
|
<string name="shrink_sparse_image_message">Змініть розмір modules.img образу, у якому знаходяться модулі, до його фактичного розміру. Зверніть увагу, що це може викликати ненормальну роботу модулів, тому використовуйте лише при необхідності (наприклад, для резервного копіювання).</string>
|
||||||
|
<string name="settings_uninstall">Видалення</string>
|
||||||
|
<string name="settings_uninstall_temporary">Тимчасове видалення</string>
|
||||||
|
<string name="settings_uninstall_permanent">Повне видалення</string>
|
||||||
|
<string name="settings_restore_stock_image">Відновити стандартний образ</string>
|
||||||
|
<string name="settings_uninstall_temporary_message">Тимчасово видаліть KernelSU Next, відновивши початковий стан після наступного перезавантаження.</string>
|
||||||
|
<string name="settings_uninstall_permanent_message">Повне і остаточне видалення KernelSU Next (Root та всіх модулів).</string>
|
||||||
|
<string name="settings_restore_stock_image_message">Відновлення стандартного заводського образу (якщо є резервна копія), зазвичай використовується перед OTA; якщо потрібно видалити KernelSU Next, використовуйте "Повне видалення".</string>
|
||||||
|
<string name="flashing">Прошивка</string>
|
||||||
|
<string name="flash_success">Прошивка виконана успішно</string>
|
||||||
|
<string name="flash_failed">Помилка прошивки</string>
|
||||||
|
<string name="selected_lkm">Вибрано LKM: %s</string>
|
||||||
|
<string name="save_log">Зберегти логи</string>
|
||||||
|
<string name="log_saved">Логи збережено</string>
|
||||||
|
<string name="send_log">Поділитися логами</string>
|
||||||
|
<string name="settings_disable_su">Вимкн. сумісність із su</string>
|
||||||
|
<string name="settings_disable_su_summary">Тимчасово вимкнути можливість додаткам отримувати права root через команду su (існуючі процеси з правами root не будуть зачеплені).</string>
|
||||||
|
<string name="settings_language">Мова</string>
|
||||||
|
<string name="use_webuix">Використовувати WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Використовувати WebUI X замість WebUI, який підтримує більше API.</string>
|
||||||
|
<string name="use_webuix_eruda">Інжект Eruda у WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Інжектити консоль відладки у WebUI X, щоб спростити відладку. Потрібно увімкнути відладку WebView.</string>
|
||||||
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="issue_report_title">Đang gặp sự cố?</string>
|
<string name="issue_report_title">Gặp sự cố?</string>
|
||||||
<string name="issue_report_body">Muốn báo cáo lỗi hoặc góp ý?</string>
|
<string name="issue_report_body">Muốn báo cáo lỗi hoặc góp ý?</string>
|
||||||
<string name="issue_report_body_2">Báo cáo hoặc góp ý nhanh nhất có thể!</string>
|
<string name="issue_report_body_2">Báo cáo hoặc góp ý nhanh nhất có thể!</string>
|
||||||
<string name="issue_report_github">Báo cáo trên GitHub</string>
|
<string name="issue_report_github">Báo cáo trên GitHub</string>
|
||||||
@@ -9,29 +9,31 @@
|
|||||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||||
<string name="confirm">Xác nhận</string>
|
<string name="confirm">Xác nhận</string>
|
||||||
<string name="app_name" translatable="false">KernelSU Next</string>
|
<string name="app_name" translatable="false">KernelSU Next</string>
|
||||||
<string name="home">Màn hình chính</string>
|
<string name="home">Trang chủ</string>
|
||||||
<string name="home_not_installed">Hỗ trợ nhưng chưa cài đặt</string>
|
<string name="home_not_installed">Hỗ trợ nhưng chưa cài đặt</string>
|
||||||
<string name="home_click_to_install">Bấm để cái đặt</string>
|
<string name="home_click_to_install">Bấm để cài đặt</string>
|
||||||
|
<string name="lkm_mode_deprecated">Chế độ LKM không còn được hỗ trợ!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Cài đặt kernel GKI hoặc tự nhúng KernelSU Next vào kernel của bạn.</string>
|
||||||
<string name="home_working">Đã cài đặt và hoạt động</string>
|
<string name="home_working">Đã cài đặt và hoạt động</string>
|
||||||
<string name="home_working_version">Phiên bản: %d</string>
|
<string name="home_working_version">Phiên bản: %d</string>
|
||||||
<string name="home_superuser_count">Ứng dụng đã cấp su: %d</string>
|
<string name="home_superuser_count">Ứng dụng đã cấp su: %d</string>
|
||||||
<string name="home_module_count">Modules: %d</string>
|
<string name="home_module_count">Module: %d</string>
|
||||||
<string name="home_failure">Chữ kí KernelSU Next v2 Không dược tìm thấy (chưa cài đặt,nhúng sai cách hoặc nhầm trình quản lý?) [ !KSU_NEXT || != size/hash ]</string>
|
<string name="home_failure">Không tìm thấy chữ kí KernelSU Next v2 (chưa cài đặt, nhúng sai cách hoặc nhầm trình quản lý?) [ !KSU_NEXT || != size/hash ]</string>
|
||||||
<string name="home_failure_tip">Hỏi hoặc tự nhúng nhân KernelSU Next vào Kernel của bạn!</string>
|
<string name="home_failure_tip">Hỏi hoặc tự nhúng KernelSU Next vào kernel của bạn!</string>
|
||||||
<string name="home_kernel">Phiên bản kernel</string>
|
<string name="home_kernel">Phiên bản kernel</string>
|
||||||
<string name="enabled">Kích hoạt</string>
|
<string name="enabled">Kích hoạt</string>
|
||||||
<string name="disabled">Vô hiệu hoá</string>
|
<string name="disabled">Vô hiệu hoá</string>
|
||||||
<string name="susfs_supported">hỗ trợ</string>
|
<string name="susfs_supported">Hỗ trợ</string>
|
||||||
<string name="home_susfs">SuSFS: %s</string>
|
<string name="home_susfs">SuSFS: %s</string>
|
||||||
<string name="home_susfs_version">Phiên bản SuSFS</string>
|
<string name="home_susfs_version">Phiên bản SuSFS</string>
|
||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Phiên bản android</string>
|
<string name="home_android">Phiên bản Android</string>
|
||||||
<string name="home_manager_version">Phiên bản trình quản lý</string>
|
<string name="home_manager_version">Phiên bản trình quản lý</string>
|
||||||
<string name="home_selinux_status">Trạng thái SELinux</string>
|
<string name="home_selinux_status">Trạng thái SELinux</string>
|
||||||
<string name="selinux_status_disabled">Vô hiệu hoá</string>
|
<string name="selinux_status_disabled">Vô hiệu hoá</string>
|
||||||
<string name="selinux_status_enforcing">Enforcing</string>
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
<string name="selinux_status_permissive">Permissive</string>
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
<string name="selinux_status_unknown">Chịu</string>
|
<string name="selinux_status_unknown">Không xác định</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">Superuser</string>
|
||||||
<string name="module_failed_to_enable">Không thể kích hoạt module: %s</string>
|
<string name="module_failed_to_enable">Không thể kích hoạt module: %s</string>
|
||||||
<string name="module_failed_to_disable">Không thể vô hiệu hoá module: %s</string>
|
<string name="module_failed_to_disable">Không thể vô hiệu hoá module: %s</string>
|
||||||
@@ -46,7 +48,7 @@
|
|||||||
<string name="install">Cài đặt</string>
|
<string name="install">Cài đặt</string>
|
||||||
<string name="reboot">Khởi động lại</string>
|
<string name="reboot">Khởi động lại</string>
|
||||||
<string name="settings">Cài đặt</string>
|
<string name="settings">Cài đặt</string>
|
||||||
<string name="reboot_userspace">Khởi động lại systemctrl</string>
|
<string name="reboot_userspace">Khởi động mềm</string>
|
||||||
<string name="reboot_recovery">Vào Recovery</string>
|
<string name="reboot_recovery">Vào Recovery</string>
|
||||||
<string name="reboot_bootloader">Vào Bootloader</string>
|
<string name="reboot_bootloader">Vào Bootloader</string>
|
||||||
<string name="reboot_download">Vào Download Mode</string>
|
<string name="reboot_download">Vào Download Mode</string>
|
||||||
@@ -57,7 +59,7 @@
|
|||||||
<string name="module_uninstall_failed">Gỡ cài đặt thất bại: %s</string>
|
<string name="module_uninstall_failed">Gỡ cài đặt thất bại: %s</string>
|
||||||
<string name="module_restore_confirm">Khôi phục module lại như lúc cài %s?</string>
|
<string name="module_restore_confirm">Khôi phục module lại như lúc cài %s?</string>
|
||||||
<string name="module_restore_success">%s đã khôi phục</string>
|
<string name="module_restore_success">%s đã khôi phục</string>
|
||||||
<string name="module_restore_failed">Khôi phục thất bại, vui lòng cài lại : %s</string>
|
<string name="module_restore_failed">Khôi phục thất bại, vui lòng cài lại: %s</string>
|
||||||
<string name="module_version">Phiên bản</string>
|
<string name="module_version">Phiên bản</string>
|
||||||
<string name="module_author">Người tạo ra</string>
|
<string name="module_author">Người tạo ra</string>
|
||||||
<string name="module_id">ID</string>
|
<string name="module_id">ID</string>
|
||||||
@@ -71,19 +73,19 @@
|
|||||||
<string name="show_system_apps">Hiện thị ứng dụng hệ thống</string>
|
<string name="show_system_apps">Hiện thị ứng dụng hệ thống</string>
|
||||||
<string name="hide_system_apps">Ẩn ứng dụng hệ thống</string>
|
<string name="hide_system_apps">Ẩn ứng dụng hệ thống</string>
|
||||||
<string name="export_log">Xuất logs</string>
|
<string name="export_log">Xuất logs</string>
|
||||||
<string name="safe_mode">CHẾ ĐỘ AN TOÀN!?!?</string>
|
<string name="safe_mode">CHẾ ĐỘ AN TOÀN</string>
|
||||||
<string name="reboot_to_apply">Khởi động lại để có hiệu lực</string>
|
<string name="reboot_to_apply">Khởi động lại để có hiệu lực</string>
|
||||||
<string name="module_magisk_conflict">Vui lòng gỡ magisk để sử dụng module</string>
|
<string name="module_magisk_conflict">Vui lòng gỡ magisk để sử dụng module</string>
|
||||||
<string name="home_mount_system">Cơ chế mount</string>
|
<string name="home_mount_system">Cơ chế mount</string>
|
||||||
<string name="home_magic_mount">Magic Mount</string>
|
<string name="home_magic_mount">Magic Mount</string>
|
||||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||||
<string name="unavailable">Không có sẵn</string>
|
<string name="unavailable">Không khả dụng</string>
|
||||||
<string name="use_overlay_fs">Sử dụng OverlayFS</string>
|
<string name="use_overlay_fs">Sử dụng OverlayFS</string>
|
||||||
<string name="use_overlay_fs_summary">Gạt bật tắt chuyển giữa phương thức OverlayFS và Magic Mount cho các tập mount hệ thống.</string>
|
<string name="use_overlay_fs_summary">Gạt bật tắt chuyển giữa phương thức OverlayFS và Magic Mount cho các tập mount hệ thống.</string>
|
||||||
<string name="reboot_required">Yêu cầu khởi động lại</string>
|
<string name="reboot_required">Yêu cầu khởi động lại</string>
|
||||||
<string name="reboot_message">Một/Nhiều thay đổi cần được khởi động lại hệ thống, khởi động luôn?</string>
|
<string name="reboot_message">Thay đổi sẽ có hiệu lực sau khi khởi động lại, khởi động ngay?</string>
|
||||||
<string name="module_restore">Khôi phục module</string>
|
<string name="module_restore">Khôi phục module</string>
|
||||||
<string name="module_restore_message">Khôi phục modules từ bản sao lưu gần nhất.</string>
|
<string name="module_restore_message">Khôi phục module từ bản sao lưu gần nhất.</string>
|
||||||
<string name="backup_restore">Sao lưu & Khôi phục</string>
|
<string name="backup_restore">Sao lưu & Khôi phục</string>
|
||||||
<string name="module_backup">Sao lưu module</string>
|
<string name="module_backup">Sao lưu module</string>
|
||||||
<string name="module_backup_message">Sao lưu những module đang được cài đặt.</string>
|
<string name="module_backup_message">Sao lưu những module đang được cài đặt.</string>
|
||||||
@@ -102,8 +104,8 @@
|
|||||||
<string name="home_experimental_kernelsu">⚠️ Cảnh báo nhánh thử nghiệm cho nhà phát triển!</string>
|
<string name="home_experimental_kernelsu">⚠️ Cảnh báo nhánh thử nghiệm cho nhà phát triển!</string>
|
||||||
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
|
||||||
<string name="home_experimental_kernelsu_body">KernelSU Next là 1 nhánh của KernelSU luôn có những nhánh thử nghiệm và cập nhật hàng ngày, nó có thể không ổn định</string>
|
<string name="home_experimental_kernelsu_body">KernelSU Next là 1 nhánh của KernelSU luôn có những nhánh thử nghiệm và cập nhật hàng ngày, nó có thể không ổn định</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_1"> • Tự chịu trách nghiệm: crashes, những thứ kì lạ, không vào được 1 vài ứng dụng(ngân hàng),... có thể diễn ra.</string>
|
<string name="home_experimental_kernelsu_body_point_1"> • Tự chịu trách nghiệm: crashes, những thứ kì lạ, không vào được 1 vài ứng dụng (ngân hàng),... có thể xảy ra.</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_2"> • Không bảo hành: Những nhà phát triển trong KernelSU (Next) và bên thứ 3 sẽ không chịu trách nghiệm khi hardbrick,bootloop,mất dữ liệu,... .</string>
|
<string name="home_experimental_kernelsu_body_point_2"> • Không bảo hành: Các nhà phát triển KernelSU Next và bên thứ 3 sẽ không chịu trách nghiệm cho hardbrick, bootloop, mất dữ liệu,...</string>
|
||||||
<string name="home_experimental_kernelsu_body_point_3"> • Đùng để thử nghiệm là chính: Chỉ dành cho những người có kĩ năng, kinh nghiệm, trải nghiệm .</string>
|
<string name="home_experimental_kernelsu_body_point_3"> • Đùng để thử nghiệm là chính: Chỉ dành cho những người có kĩ năng, kinh nghiệm, trải nghiệm .</string>
|
||||||
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s]]></string>
|
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s]]></string>
|
||||||
<string name="profile" translatable="false">Hồ sơ ứng dụng</string>
|
<string name="profile" translatable="false">Hồ sơ ứng dụng</string>
|
||||||
@@ -122,9 +124,9 @@
|
|||||||
<string name="failed_to_update_app_profile">Cập nhật hồ sơ ứng dụng thất bại cho %s</string>
|
<string name="failed_to_update_app_profile">Cập nhật hồ sơ ứng dụng thất bại cho %s</string>
|
||||||
<string name="require_kernel_version">Phiên bản KernelSU Next được nhúng trong kernel là %1$d và nó quá thấp để trình quản lý hoạt động. Vui lòng cập nhật lên phiên bản %2$d hoặc!</string>
|
<string name="require_kernel_version">Phiên bản KernelSU Next được nhúng trong kernel là %1$d và nó quá thấp để trình quản lý hoạt động. Vui lòng cập nhật lên phiên bản %2$d hoặc!</string>
|
||||||
<string name="settings_umount_modules_default">Umount modules cho toàn hệ thống</string>
|
<string name="settings_umount_modules_default">Umount modules cho toàn hệ thống</string>
|
||||||
<string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong hồ sơ ứng dụng. Nếu bật, tất cả nhưng module có can thiệp/thay đổi hệ thống sẽ không đổi trừ khi được kích hoạt trong hồ sơ ứng dụng riêng biệt. (modder oem rom hoặc những người muốn chép file vào phân vùng hệ thống nên tắt).</string>
|
<string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong Hồ sơ ứng dụng. Nếu bật, mọi thay đổi hệ thống do module gây ra sẽ bị gỡ bỏ đối với các ứng dụng chưa đặt hồ sơ riêng. (Modder OEM rom hoặc những người muốn chép file vào phân vùng hệ thống nên tắt).</string>
|
||||||
<string name="settings_susfs_toggle">Ẩn kprobe hooks</string>
|
<string name="settings_susfs_toggle">Ẩn kprobes hook</string>
|
||||||
<string name="settings_susfs_toggle_summary">Tính năng này sẽ vô hiệu hoá những kprobe hooks đã tạo bởi kernelsu và sẽ kích hoạt và nhúng những non-kprobe hooks,đảm bảo những kernel non-GKI(EOL) hoạt động ổn định.</string>
|
<string name="settings_susfs_toggle_summary">Tính năng này sẽ vô hiệu hoá những kprobes hook đã tạo bởi kernelsu và sẽ kích hoạt và nhúng những non-kprobes hook, đảm bảo những kernel non-GKI(EOL) hoạt động ổn định.</string>
|
||||||
<string name="profile_umount_modules_summary">Kích hoạt tính năng này sẽ tách các ứng dụng chưa cấp hồ sơ riêng và root.</string>
|
<string name="profile_umount_modules_summary">Kích hoạt tính năng này sẽ tách các ứng dụng chưa cấp hồ sơ riêng và root.</string>
|
||||||
<string name="profile_selinux_domain">Tên miền</string>
|
<string name="profile_selinux_domain">Tên miền</string>
|
||||||
<string name="profile_selinux_rules">Quyền</string>
|
<string name="profile_selinux_rules">Quyền</string>
|
||||||
@@ -171,9 +173,9 @@
|
|||||||
<string name="direct_install">Cài đặt trực tiếp (cho GKI 2.0)</string>
|
<string name="direct_install">Cài đặt trực tiếp (cho GKI 2.0)</string>
|
||||||
<string name="select_file">Chọn file</string>
|
<string name="select_file">Chọn file</string>
|
||||||
<string name="install_inactive_slot">Cài đặt vào phân vùng update (cho người OTA)</string>
|
<string name="install_inactive_slot">Cài đặt vào phân vùng update (cho người OTA)</string>
|
||||||
<string name="install_inactive_slot_warning">Thiết bị của bạn sẽ BUỘC khởi động vào phân dùng chưa được sử dụng (có thể A hoặc B)\nSử dụng sau khi update OTA.\nTiếp?</string>
|
<string name="install_inactive_slot_warning">Thiết bị của bạn sẽ BUỘC khởi động vào phân dùng chưa được sử dụng (A hoặc B)\nSử dụng sau khi update OTA.\nTiếp?</string>
|
||||||
<string name="install_next">Tiếp</string>
|
<string name="install_next">Tiếp</string>
|
||||||
<string name="select_file_tip">tập tin %1$s được khuyến kích</string>
|
<string name="select_file_tip">Tập tin %1$s được khuyến khích</string>
|
||||||
<string name="select_kmi">Chọn KMI</string>
|
<string name="select_kmi">Chọn KMI</string>
|
||||||
<string name="shrink_sparse_image">Nén module.img</string>
|
<string name="shrink_sparse_image">Nén module.img</string>
|
||||||
<string name="shrink_sparse_image_message">Nén lại module.img về kích thước thực, CHỈ SỬ DỤNG KHI CÓ HIỂU BIẾT VÀ CẦN THIẾT!?!?!?!?!.</string>
|
<string name="shrink_sparse_image_message">Nén lại module.img về kích thước thực, CHỈ SỬ DỤNG KHI CÓ HIỂU BIẾT VÀ CẦN THIẾT!?!?!?!?!.</string>
|
||||||
@@ -182,7 +184,7 @@
|
|||||||
<string name="settings_uninstall_permanent">Gỡ cài đặt sạch</string>
|
<string name="settings_uninstall_permanent">Gỡ cài đặt sạch</string>
|
||||||
<string name="settings_restore_stock_image">Khôi phục phân vùng khởi động về mặc định</string>
|
<string name="settings_restore_stock_image">Khôi phục phân vùng khởi động về mặc định</string>
|
||||||
<string name="settings_uninstall_temporary_message">Tạm thời gỡ KernelSU Next.</string>
|
<string name="settings_uninstall_temporary_message">Tạm thời gỡ KernelSU Next.</string>
|
||||||
<string name="settings_uninstall_permanent_message">Gỡ cài đặt sạch hoàn toàn, trả về trạng thái lúc đầu .</string>
|
<string name="settings_uninstall_permanent_message">Gỡ cài đặt sạch hoàn toàn, trả về trạng thái ban đầu.</string>
|
||||||
<string name="settings_restore_stock_image_message">Khôi phục lại boot lúc đầu (nếu có); nếu bạn cần gỡ hẳn KernelSU Next, sử dụng\"Gỡ cài đặt sạch\".</string>
|
<string name="settings_restore_stock_image_message">Khôi phục lại boot lúc đầu (nếu có); nếu bạn cần gỡ hẳn KernelSU Next, sử dụng\"Gỡ cài đặt sạch\".</string>
|
||||||
<string name="flashing">Đang cài đặt</string>
|
<string name="flashing">Đang cài đặt</string>
|
||||||
<string name="flash_success">Cài đặt thành công</string>
|
<string name="flash_success">Cài đặt thành công</string>
|
||||||
@@ -194,4 +196,8 @@
|
|||||||
<string name="settings_disable_su">Vô hiệu hoá khả năng của lệnh SU</string>
|
<string name="settings_disable_su">Vô hiệu hoá khả năng của lệnh SU</string>
|
||||||
<string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (những app đã cấp trước đó không bị ảnh hưởng).</string>
|
<string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (những app đã cấp trước đó không bị ảnh hưởng).</string>
|
||||||
<string name="settings_language">Ngôn ngữ</string>
|
<string name="settings_language">Ngôn ngữ</string>
|
||||||
|
<string name="use_webuix">Dùng WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Dùng WebUI X thay vì WebUI (hỗ trợ nhiều API hơn).</string>
|
||||||
|
<string name="use_webuix_eruda">Nhúng nhân Eruda vào WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Nhúng trình gỡ lỗi vào WebUI X để việc sửa lỗi thuận tiện hơn. Yêu cầu gỡ lỗi webview được bật.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<string name="home_susfs">SuSFS:%s</string>
|
<string name="home_susfs">SuSFS:%s</string>
|
||||||
<string name="home_susfs_version">SuSFS 版本</string>
|
<string name="home_susfs_version">SuSFS 版本</string>
|
||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">安卓版本</string>
|
<string name="home_android">Android 版本</string>
|
||||||
<string name="home_manager_version">管理器版本</string>
|
<string name="home_manager_version">管理器版本</string>
|
||||||
<string name="home_selinux_status">SELinux 状态</string>
|
<string name="home_selinux_status">SELinux 状态</string>
|
||||||
<string name="selinux_status_disabled">被禁用</string>
|
<string name="selinux_status_disabled">被禁用</string>
|
||||||
|
|||||||
@@ -12,13 +12,19 @@
|
|||||||
<string name="home">Home</string>
|
<string name="home">Home</string>
|
||||||
<string name="home_not_installed">Not installed</string>
|
<string name="home_not_installed">Not installed</string>
|
||||||
<string name="home_click_to_install">Click to install</string>
|
<string name="home_click_to_install">Click to install</string>
|
||||||
|
<string name="lkm_mode_deprecated">LKM mode is now deprecated!</string>
|
||||||
|
<string name="lkm_alternative_suggestion">Install GKI kernel or integrate KernelSU Next to your device.</string>
|
||||||
<string name="home_working">Working</string>
|
<string name="home_working">Working</string>
|
||||||
<string name="home_working_version">Version: %d</string>
|
<string name="home_working_version">Version: %d</string>
|
||||||
<string name="home_superuser_count">Superusers: %d</string>
|
<string name="home_superuser_count">Superusers: %d</string>
|
||||||
<string name="home_module_count">Modules: %d</string>
|
<string name="home_module_count">Modules: %d</string>
|
||||||
|
<string name="home_module_update_count">Updates: %d</string>
|
||||||
<string name="home_failure">KernelSU Next v2 signature not found in kernel! [ !KSU_NEXT || != size/hash ]</string>
|
<string name="home_failure">KernelSU Next v2 signature not found in kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||||
<string name="home_failure_tip">Ask your kernel developer to integrate KernelSU Next!</string>
|
<string name="home_failure_tip">Ask your kernel developer to integrate KernelSU Next!</string>
|
||||||
<string name="home_kernel">Kernel version</string>
|
<string name="home_kernel">Kernel version</string>
|
||||||
|
<string name="hook_mode">Hook mode</string>
|
||||||
|
<string name="enable">Enable</string>
|
||||||
|
<string name="disable">Disable</string>
|
||||||
<string name="enabled">Enabled</string>
|
<string name="enabled">Enabled</string>
|
||||||
<string name="disabled">Disabled</string>
|
<string name="disabled">Disabled</string>
|
||||||
<string name="susfs_supported">Supported</string>
|
<string name="susfs_supported">Supported</string>
|
||||||
@@ -27,6 +33,7 @@
|
|||||||
<string name="home_susfs_sus_su">SuS SU</string>
|
<string name="home_susfs_sus_su">SuS SU</string>
|
||||||
<string name="home_android">Android version</string>
|
<string name="home_android">Android version</string>
|
||||||
<string name="home_manager_version">Manager version</string>
|
<string name="home_manager_version">Manager version</string>
|
||||||
|
<string name="home_abi">ABI</string>
|
||||||
<string name="home_selinux_status">SELinux status</string>
|
<string name="home_selinux_status">SELinux status</string>
|
||||||
<string name="selinux_status_disabled">Disabled</string>
|
<string name="selinux_status_disabled">Disabled</string>
|
||||||
<string name="selinux_status_enforcing">Enforcing</string>
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
@@ -38,13 +45,16 @@
|
|||||||
<string name="module_empty">No module installed</string>
|
<string name="module_empty">No module installed</string>
|
||||||
<string name="module">Module</string>
|
<string name="module">Module</string>
|
||||||
<string name="module_install_prompt_with_name">The following module(s) will be installed: %1$s</string>
|
<string name="module_install_prompt_with_name">The following module(s) will be installed: %1$s</string>
|
||||||
<string name="module_sort_a_to_z">Sort (A-Z)</string>
|
<string name="module_sort_a_to_z">Sort (A → Z)</string>
|
||||||
<string name="module_sort_z_to_a">Sort (Z-A)</string>
|
<string name="module_sort_z_to_a">Sort (Z → A)</string>
|
||||||
|
<string name="module_size_low_to_high">Sort (Low → High)</string>
|
||||||
|
<string name="module_size_high_to_low">Sort (High → Low)</string>
|
||||||
<string name="uninstall">Uninstall</string>
|
<string name="uninstall">Uninstall</string>
|
||||||
<string name="restore">Restore</string>
|
<string name="restore">Restore</string>
|
||||||
<string name="module_install">Install</string>
|
<string name="module_install">Install</string>
|
||||||
<string name="install">Install</string>
|
<string name="install">Install</string>
|
||||||
<string name="reboot">Reboot</string>
|
<string name="reboot">Reboot</string>
|
||||||
|
<string name="uninstalled">Uninstalled</string>
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="reboot_userspace">Soft Reboot</string>
|
<string name="reboot_userspace">Soft Reboot</string>
|
||||||
<string name="reboot_recovery">Reboot to Recovery</string>
|
<string name="reboot_recovery">Reboot to Recovery</string>
|
||||||
@@ -96,6 +106,7 @@
|
|||||||
<string name="proceed">Proceed</string>
|
<string name="proceed">Proceed</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
<string name="later">Later</string>
|
<string name="later">Later</string>
|
||||||
|
<string name="lkm_warning_message">The LKM patch relies on closed source components. Do you want to continue?</string>
|
||||||
<string name="home_next_kernelsu">🔥 Next build</string>
|
<string name="home_next_kernelsu">🔥 Next build</string>
|
||||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||||
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>
|
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>
|
||||||
@@ -123,12 +134,13 @@
|
|||||||
<string name="require_kernel_version">The current KernelSU Next version %1$d is too low for the manager to work properly. Please upgrade to version %2$d or higher!</string>
|
<string name="require_kernel_version">The current KernelSU Next version %1$d is too low for the manager to work properly. Please upgrade to version %2$d or higher!</string>
|
||||||
<string name="settings_umount_modules_default">Umount modules</string>
|
<string name="settings_umount_modules_default">Umount modules</string>
|
||||||
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
|
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
|
||||||
<string name="settings_susfs_toggle">Hide kprobe hooks</string>
|
<string name="settings_susfs_toggle">Hide kprobes hook</string>
|
||||||
<string name="settings_susfs_toggle_summary">This option disables the kprobe hooks created by ksu and, instead, activates the embedded non-kprobe hooks, implementing the same functionality that would be applied to a non-GKI kernel, which doesn\'t support kprobe.</string>
|
<string name="settings_susfs_toggle_summary">This option disables the kprobes hook created by ksu and, instead, activates the embedded non-kprobes hook, implementing the same functionality that would be applied to a non-GKI kernel, which doesn\'t support kprobe.</string>
|
||||||
<string name="profile_umount_modules_summary">Enabling this option will allow KernelSU Next to restore any modified files by the modules for this app.</string>
|
<string name="profile_umount_modules_summary">Enabling this option will allow KernelSU Next to restore any modified files by the modules for this app.</string>
|
||||||
<string name="profile_selinux_domain">Domain</string>
|
<string name="profile_selinux_domain">Domain</string>
|
||||||
<string name="profile_selinux_rules">Rules</string>
|
<string name="profile_selinux_rules">Rules</string>
|
||||||
<string name="module_update">Update</string>
|
<string name="module_update">Update</string>
|
||||||
|
<string name="module_updated">Updated</string>
|
||||||
<string name="module_downloading">Downloading module: %s</string>
|
<string name="module_downloading">Downloading module: %s</string>
|
||||||
<string name="module_start_downloading">Start downloading: %s</string>
|
<string name="module_start_downloading">Start downloading: %s</string>
|
||||||
<string name="new_version_available">New version %s is available, click to upgrade.</string>
|
<string name="new_version_available">New version %s is available, click to upgrade.</string>
|
||||||
@@ -136,6 +148,10 @@
|
|||||||
<string name="close">Close</string>
|
<string name="close">Close</string>
|
||||||
<string name="force_stop_app">Force stop</string>
|
<string name="force_stop_app">Force stop</string>
|
||||||
<string name="restart_app">Restart</string>
|
<string name="restart_app">Restart</string>
|
||||||
|
<string name="settings_amoled_mode">AMOLED mode</string>
|
||||||
|
<string name="settings_amoled_mode_summary">Enable a pure black theme useful for AMOLED screens to reduce eye strain and save battery.</string>
|
||||||
|
<string name="restart_required">Restart Required</string>
|
||||||
|
<string name="restart_app_message">The app needs to restart for this change to take effect.</string>
|
||||||
<string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string>
|
<string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string>
|
||||||
<string name="su_not_allowed">Granting superuser isn\'t allowed for: %s</string>
|
<string name="su_not_allowed">Granting superuser isn\'t allowed for: %s</string>
|
||||||
<string name="module_changelog">Changelog</string>
|
<string name="module_changelog">Changelog</string>
|
||||||
@@ -165,6 +181,7 @@
|
|||||||
<string name="settings_check_update_summary">Automatically check for updates when opening the app.</string>
|
<string name="settings_check_update_summary">Automatically check for updates when opening the app.</string>
|
||||||
<string name="grant_root_failed">Failed to grant root!</string>
|
<string name="grant_root_failed">Failed to grant root!</string>
|
||||||
<string name="action">Action</string>
|
<string name="action">Action</string>
|
||||||
|
<string name="webui">WebUI</string>
|
||||||
<string name="open">Open</string>
|
<string name="open">Open</string>
|
||||||
<string name="enable_web_debugging">Enable WebView debugging</string>
|
<string name="enable_web_debugging">Enable WebView debugging</string>
|
||||||
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
|
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
|
||||||
@@ -194,4 +211,13 @@
|
|||||||
<string name="settings_disable_su">Disable su compatibility</string>
|
<string name="settings_disable_su">Disable su compatibility</string>
|
||||||
<string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (existing root processes won\'t be affected).</string>
|
<string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (existing root processes won\'t be affected).</string>
|
||||||
<string name="settings_language">Language</string>
|
<string name="settings_language">Language</string>
|
||||||
|
<string name="settings_legacyui">Use Legacy UI</string>
|
||||||
|
<string name="settings_legacyui_summary">Switch to the previous user interface style.</string>
|
||||||
|
<string name="settings_banner">Enable banners</string>
|
||||||
|
<string name="settings_banner_summary">Show background banners for modules.</string>
|
||||||
|
<string name="use_webuix">Use WebUI X</string>
|
||||||
|
<string name="use_webuix_summary">Use WebUI X instead of WebUI, which supports more APIs.</string>
|
||||||
|
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
|
||||||
|
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
|
||||||
|
<string name="customization">Customization</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ cmaker {
|
|||||||
"-DANDROID_STL=none",
|
"-DANDROID_STL=none",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
abiFilters("arm64-v8a")
|
abiFilters("arm64-v8a", "armeabi-v7a", "x86_64")
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
if (it.name == "release") {
|
if (it.name == "release") {
|
||||||
@@ -30,7 +30,7 @@ cmaker {
|
|||||||
val androidMinSdkVersion = 26
|
val androidMinSdkVersion = 26
|
||||||
val androidTargetSdkVersion = 35
|
val androidTargetSdkVersion = 35
|
||||||
val androidCompileSdkVersion = 35
|
val androidCompileSdkVersion = 35
|
||||||
val androidCompileNdkVersion = "28.0.13004108"
|
val androidCompileNdkVersion = "28.1.13356709"
|
||||||
val androidSourceCompatibility = JavaVersion.VERSION_21
|
val androidSourceCompatibility = JavaVersion.VERSION_21
|
||||||
val androidTargetCompatibility = JavaVersion.VERSION_21
|
val androidTargetCompatibility = JavaVersion.VERSION_21
|
||||||
val managerVersionCode by extra(getVersionCode())
|
val managerVersionCode by extra(getVersionCode())
|
||||||
@@ -78,7 +78,7 @@ subprojects {
|
|||||||
versionName = managerVersionName
|
versionName = managerVersionName
|
||||||
}
|
}
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters += listOf("arm64-v8a")
|
abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.9.1"
|
agp = "8.10.0"
|
||||||
kotlin = "2.1.20"
|
kotlin = "2.1.21"
|
||||||
ksp = "2.1.20-1.0.32"
|
ksp = "2.1.21-2.0.1"
|
||||||
compose-bom = "2025.03.01"
|
compose-bom = "2025.05.01"
|
||||||
lifecycle = "2.8.7"
|
lifecycle = "2.9.0"
|
||||||
navigation = "2.8.9"
|
navigation = "2.9.0"
|
||||||
activity-compose = "1.10.1"
|
activity-compose = "1.10.1"
|
||||||
kotlinx-coroutines = "1.10.1"
|
kotlinx-coroutines = "1.10.2"
|
||||||
coil-compose = "2.7.0"
|
coil-compose = "2.7.0"
|
||||||
compose-destination = "2.1.0"
|
compose-destination = "2.2.0"
|
||||||
sheets-compose-dialogs = "1.3.0"
|
sheets-compose-dialogs = "1.3.0"
|
||||||
markdown = "4.6.2"
|
markdown = "4.6.2"
|
||||||
webkit = "1.13.0"
|
webkit = "1.13.0"
|
||||||
@@ -17,6 +17,7 @@ parcelablelist = "2.0.1"
|
|||||||
libsu = "6.0.0"
|
libsu = "6.0.0"
|
||||||
apksign = "1.4"
|
apksign = "1.4"
|
||||||
cmaker = "1.2"
|
cmaker = "1.2"
|
||||||
|
mmrl = "2bb00b3c2b"
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
agp-app = { id = "com.android.application", version.ref = "agp" }
|
agp-app = { id = "com.android.application", version.ref = "agp" }
|
||||||
@@ -72,3 +73,8 @@ sheet-compose-dialogs-input = { group = "com.maxkeppeler.sheets-compose-dialogs"
|
|||||||
markdown = { group = "io.noties.markwon", name = "core", version.ref = "markdown" }
|
markdown = { group = "io.noties.markwon", name = "core", version.ref = "markdown" }
|
||||||
|
|
||||||
lsposed-cxx = { module = "org.lsposed.libcxx:libcxx", version = "27.0.12077973" }
|
lsposed-cxx = { module = "org.lsposed.libcxx:libcxx", version = "27.0.12077973" }
|
||||||
|
|
||||||
|
mmrl-webui = { group = "com.github.MMRLApp.MMRL", name = "webui", version.ref = "mmrl" }
|
||||||
|
mmrl-platform = { group = "com.github.MMRLApp.MMRL", name = "platform", version.ref = "mmrl" }
|
||||||
|
mmrl-ui = { group = "com.github.MMRLApp.MMRL", name = "ui", version.ref = "mmrl" }
|
||||||
|
mmrl-hidden-api = { group = "com.github.MMRLApp.MMRL", name = "hidden-api", version.ref = "mmrl" }
|
||||||
BIN
manager/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
manager/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user