You've already forked KernelSU
mirror of
https://github.com/tiann/KernelSU.git
synced 2025-08-27 23:46:34 +00:00
Compare commits
291 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f341a4e3a | ||
|
|
40d7bc6256 | ||
|
|
56dbc980f4 | ||
|
|
bf71ff133c | ||
|
|
a9b156df43 | ||
|
|
1690e5db02 | ||
|
|
300d9d4cca | ||
|
|
3f12080dfe | ||
|
|
b670db2d22 | ||
|
|
62a31b3dc2 | ||
|
|
a395b1011e | ||
|
|
406070914a | ||
|
|
8685fa1f60 | ||
|
|
c95163b144 | ||
|
|
648d56da39 | ||
|
|
33c0a9eebd | ||
|
|
3f86fb016d | ||
|
|
66316e76f5 | ||
|
|
5591a94f87 | ||
|
|
f855f8148a | ||
|
|
0c52f24612 | ||
|
|
9635a00036 | ||
|
|
cbc04ff6df | ||
|
|
8e448767a5 | ||
|
|
2820779947 | ||
|
|
a99c69f9b4 | ||
|
|
a829707b16 | ||
|
|
77d16ac896 | ||
|
|
d02855a40a | ||
|
|
b904680f13 | ||
|
|
811c68cac0 | ||
|
|
f20ccc1728 | ||
|
|
66e7db2a4e | ||
|
|
e6b05b1d3c | ||
|
|
329010a694 | ||
|
|
9c4d20c0f2 | ||
|
|
355b55a01d | ||
|
|
e85646fad4 | ||
|
|
4969c5f548 | ||
|
|
55f8f2da90 | ||
|
|
65bff7bf03 | ||
|
|
30dfbbdc0e | ||
|
|
fceffc9cfe | ||
|
|
01b685ce58 | ||
|
|
cbd184421c | ||
|
|
b0a42abf4f | ||
|
|
cfc982f2f3 | ||
|
|
e0e7058d14 | ||
|
|
e0802b0d15 | ||
|
|
81f15ef120 | ||
|
|
20c19d7126 | ||
|
|
a360cd87c0 | ||
|
|
ea9b572402 | ||
|
|
6bf9e0478e | ||
|
|
abf0dacb36 | ||
|
|
263b986bcd | ||
|
|
15bdd9f507 | ||
|
|
810a62f795 | ||
|
|
07e475c5dc | ||
|
|
eb02e42bc7 | ||
|
|
5db51b0715 | ||
|
|
60d2685f7e | ||
|
|
a4b9ea04a4 | ||
|
|
f80d0764b5 | ||
|
|
f80769a82a | ||
|
|
64269c8c4f | ||
|
|
9f04482b90 | ||
|
|
aca505c3e6 | ||
|
|
d4826bc97c | ||
|
|
4efc8164f1 | ||
|
|
0fc25cf091 | ||
|
|
ca438291cc | ||
|
|
d6cab60e6d | ||
|
|
4d4bd4793f | ||
|
|
c1a2cbf1e4 | ||
|
|
4b1fb121b4 | ||
|
|
883a3e3407 | ||
|
|
27bd18f60e | ||
|
|
7cb5fb47e1 | ||
|
|
d43b40572d | ||
|
|
c99b5b31c1 | ||
|
|
ca960a2a8f | ||
|
|
cce423a2f6 | ||
|
|
946fb6f999 | ||
|
|
b6ecce4317 | ||
|
|
be70a91f16 | ||
|
|
71c2790f08 | ||
|
|
8733b390ca | ||
|
|
c4e106d6f8 | ||
|
|
b612efcfad | ||
|
|
7f53882007 | ||
|
|
23ba3182cf | ||
|
|
8abd37a35c | ||
|
|
d7bc853bfc | ||
|
|
16c5aba4ff | ||
|
|
3914242457 | ||
|
|
eaa12161d6 | ||
|
|
0f985917f9 | ||
|
|
a569b1c76e | ||
|
|
7f1ea2e178 | ||
|
|
da89a45d56 | ||
|
|
dc2fb20d24 | ||
|
|
d7625722db | ||
|
|
4144f10d9a | ||
|
|
aaddaf1a78 | ||
|
|
2fec279de3 | ||
|
|
1e676e5dc2 | ||
|
|
7b63e099ce | ||
|
|
aef943ebe3 | ||
|
|
1637864636 | ||
|
|
e934bfb648 | ||
|
|
653225bb5b | ||
|
|
decbdeb5d7 | ||
|
|
51ca19f267 | ||
|
|
5b920f8230 | ||
|
|
601ce2120a | ||
|
|
6d79060e4c | ||
|
|
e95e87a7a4 | ||
|
|
144b0cc8e9 | ||
|
|
d9d9066316 | ||
|
|
3af293f991 | ||
|
|
60c9fabb44 | ||
|
|
23ffc2a3b2 | ||
|
|
2bab388bbf | ||
|
|
e9997a07c1 | ||
|
|
757e69b15e | ||
|
|
506385cfad | ||
|
|
4b27a9a324 | ||
|
|
1326fd32c5 | ||
|
|
90d63fe184 | ||
|
|
0f8a1346c7 | ||
|
|
1fad91a4e2 | ||
|
|
ddff9ee701 | ||
|
|
c7a9655ab9 | ||
|
|
fd7681c3ff | ||
|
|
e3e4d2eed4 | ||
|
|
30e00859b9 | ||
|
|
faf7a8e3b1 | ||
|
|
b82fc971dd | ||
|
|
52f5727875 | ||
|
|
01711b4114 | ||
|
|
153ce9a39a | ||
|
|
f37cc16117 | ||
|
|
5f31571cc7 | ||
|
|
92a1267b29 | ||
|
|
b99701d216 | ||
|
|
097e291d93 | ||
|
|
eb3f604ab8 | ||
|
|
3d9ca63bac | ||
|
|
4be7485180 | ||
|
|
afefe20c96 | ||
|
|
76e7d7c60c | ||
|
|
d08f537c89 | ||
|
|
88e20d102d | ||
|
|
32b3ec9844 | ||
|
|
fbeea49318 | ||
|
|
5deecb3b50 | ||
|
|
534ac88195 | ||
|
|
d867c3c5e2 | ||
|
|
aca9ac50f3 | ||
|
|
d6cbda49aa | ||
|
|
fe7f509f9d | ||
|
|
26da7d590e | ||
|
|
706cd1e73e | ||
|
|
6472b14a59 | ||
|
|
c305dca5ab | ||
|
|
94978b7b28 | ||
|
|
161b3280c4 | ||
|
|
e69769d25f | ||
|
|
a1153683e1 | ||
|
|
79341ab501 | ||
|
|
05b33abb79 | ||
|
|
f5095f96fa | ||
|
|
dcd9d65c92 | ||
|
|
fa3dec8852 | ||
|
|
87d10054ae | ||
|
|
1a308afe63 | ||
|
|
f46830f28f | ||
|
|
c560d603e6 | ||
|
|
064de704f2 | ||
|
|
860911c455 | ||
|
|
1d04c5086c | ||
|
|
f4eab986a9 | ||
|
|
701e85d931 | ||
|
|
bf43654725 | ||
|
|
a56a922f96 | ||
|
|
19a697a968 | ||
|
|
c9b540b12c | ||
|
|
cd48f64154 | ||
|
|
acd2c343e2 | ||
|
|
dec7f91182 | ||
|
|
d2684292e8 | ||
|
|
07b940d127 | ||
|
|
845515fa6b | ||
|
|
0db7aa573e | ||
|
|
3783f82b28 | ||
|
|
684973b4bf | ||
|
|
0617c4440b | ||
|
|
9223558197 | ||
|
|
c13040a0ea | ||
|
|
b45c4f57c5 | ||
|
|
8196243478 | ||
|
|
b7f937b7f9 | ||
|
|
8fdff569d6 | ||
|
|
b658d820a1 | ||
|
|
ce56c19ad9 | ||
|
|
d27561c505 | ||
|
|
57898f13c1 | ||
|
|
5da1767ff8 | ||
|
|
aa21385a36 | ||
|
|
697e06125a | ||
|
|
95c383ea18 | ||
|
|
048e94ba69 | ||
|
|
4a9f1de7a0 | ||
|
|
00438a6d6e | ||
|
|
88d4eca8ff | ||
|
|
8a298bb867 | ||
|
|
5526fa2468 | ||
|
|
c26a26b92d | ||
|
|
75e64eafd2 | ||
|
|
961478fa23 | ||
|
|
a903b0fa4e | ||
|
|
0f09b90f5b | ||
|
|
8b81aeaf70 | ||
|
|
b4a52f89cc | ||
|
|
e9df5105b3 | ||
|
|
cd2711395a | ||
|
|
83a8d77018 | ||
|
|
426fde58fd | ||
|
|
59040c3aea | ||
|
|
f4b53daddf | ||
|
|
4c79ad7a81 | ||
|
|
fb6565bd19 | ||
|
|
a3e939ab90 | ||
|
|
80797548b5 | ||
|
|
f86fce6e16 | ||
|
|
318be535a8 | ||
|
|
92d4de3a73 | ||
|
|
3cf5fc4c51 | ||
|
|
4e3cbf627a | ||
|
|
72febb34c0 | ||
|
|
03068f279d | ||
|
|
7371eae382 | ||
|
|
fae1fd9826 | ||
|
|
ec5d9e6368 | ||
|
|
64f849dc10 | ||
|
|
d68fa5aed5 | ||
|
|
1b67c1b153 | ||
|
|
f349507232 | ||
|
|
bf823a29e8 | ||
|
|
55f712d1b2 | ||
|
|
ca10d7bcb9 | ||
|
|
d24813b2c3 | ||
|
|
a6325193cf | ||
|
|
7a1767b4c9 | ||
|
|
2d4d26c68e | ||
|
|
3f98493bb3 | ||
|
|
927f2a26bd | ||
|
|
344c08bb79 | ||
|
|
84f16e4c82 | ||
|
|
4ff9dcaa17 | ||
|
|
34b64b8310 | ||
|
|
8f4e7f8a79 | ||
|
|
75b5fdfb9d | ||
|
|
d4e19bb8fc | ||
|
|
571f89fac3 | ||
|
|
9e058c48a6 | ||
|
|
e828053439 | ||
|
|
8a7d153b02 | ||
|
|
06fdae18d2 | ||
|
|
df8c91b306 | ||
|
|
10b31bd09a | ||
|
|
54a705d8dc | ||
|
|
294caf3deb | ||
|
|
a1f7d474f9 | ||
|
|
1df5fec49b | ||
|
|
fd03626362 | ||
|
|
9b294682b0 | ||
|
|
a4fb9e4031 | ||
|
|
3ebee74efc | ||
|
|
433627c82b | ||
|
|
6cce322107 | ||
|
|
906007a7b3 | ||
|
|
583426ecc5 | ||
|
|
ce892bc439 | ||
|
|
1f1d4d454e | ||
|
|
4695b41f53 | ||
|
|
52f17cde40 | ||
|
|
3408f944e6 | ||
|
|
b1830049f1 | ||
|
|
79951f06ed |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behaviour:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See the error
|
|
||||||
|
|
||||||
**Expected behaviour**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Smartphone (please complete the following information):**
|
|
||||||
- Device: [e.g. iPhone6]
|
|
||||||
- OS: [e.g. iOS8.1]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
72
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
72
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Create a report to help us improve KernelSU
|
||||||
|
labels: [Bug]
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Please check before submitting an issue
|
||||||
|
options:
|
||||||
|
- label: I have searched the issues and haven't found anything relevant
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- label: I will upload bugreport file in KernelSU Manager - Settings - Report log
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- label: I know how to reproduce the issue which may not be specific to my device
|
||||||
|
required: false
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: To Reproduce
|
||||||
|
description: Steps to reproduce the behaviour
|
||||||
|
placeholder: |
|
||||||
|
- 1. Go to '...'
|
||||||
|
- 2. Click on '....'
|
||||||
|
- 3. Scroll down to '....'
|
||||||
|
- 4. See error
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Logs
|
||||||
|
description: If applicable, add crash or any other logs to help us figure out the problem.
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Device info
|
||||||
|
value: |
|
||||||
|
- Device:
|
||||||
|
- OS Version:
|
||||||
|
- KernelSU Version:
|
||||||
|
- Kernel Version:
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem here.
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
From f1e398602b989ac197cdd0fda4a7c4c323b03eb9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: DozNaka <dozdguide@gmail.com>
|
|
||||||
Date: Mon, 11 Apr 2022 20:43:45 -0400
|
|
||||||
Subject: [PATCH] Makefile: Use CCACHE for faster compilation
|
|
||||||
|
|
||||||
---
|
|
||||||
Makefile | 20 ++++++++++----------
|
|
||||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index e8b8d5894..51e8aac6e 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -442,21 +442,21 @@ KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
|
|
||||||
# Make variables (CC, etc...)
|
|
||||||
CPP = $(CC) -E
|
|
||||||
ifneq ($(LLVM),)
|
|
||||||
-CC = clang
|
|
||||||
-LD = ld.lld
|
|
||||||
-AR = llvm-ar
|
|
||||||
+CC = $(CCACHE) clang
|
|
||||||
+LD = $(CCACHE) ld.lld
|
|
||||||
+AR = $(CCACHE) llvm-ar
|
|
||||||
NM = llvm-nm
|
|
||||||
-OBJCOPY = llvm-objcopy
|
|
||||||
-OBJDUMP = llvm-objdump
|
|
||||||
+OBJCOPY = $(CCACHE) llvm-objcopy
|
|
||||||
+OBJDUMP = $(CCACHE) llvm-objdump
|
|
||||||
READELF = llvm-readelf
|
|
||||||
STRIP = llvm-strip
|
|
||||||
else
|
|
||||||
-CC = $(CROSS_COMPILE)gcc
|
|
||||||
-LD = $(CROSS_COMPILE)ld
|
|
||||||
-AR = $(CROSS_COMPILE)ar
|
|
||||||
+CC = $(CCACHE) $(CROSS_COMPILE)gcc
|
|
||||||
+LD = $(CCACHE) $(CROSS_COMPILE)ld
|
|
||||||
+AR = $(CCACHE) $(CROSS_COMPILE)ar
|
|
||||||
NM = $(CROSS_COMPILE)nm
|
|
||||||
-OBJCOPY = $(CROSS_COMPILE)objcopy
|
|
||||||
-OBJDUMP = $(CROSS_COMPILE)objdump
|
|
||||||
+OBJCOPY = $(CCACHE) $(CROSS_COMPILE)objcopy
|
|
||||||
+OBJDUMP = $(CCACHE) $(CROSS_COMPILE)objdump
|
|
||||||
READELF = $(CROSS_COMPILE)readelf
|
|
||||||
STRIP = $(CROSS_COMPILE)strip
|
|
||||||
endif
|
|
||||||
--
|
|
||||||
2.37.2
|
|
||||||
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
From f1e398602b989ac197cdd0fda4a7c4c323b03eb9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: DozNaka <dozdguide@gmail.com>
|
|
||||||
Date: Mon, 11 Apr 2022 20:43:45 -0400
|
|
||||||
Subject: [PATCH] Makefile: Use CCACHE for faster compilation
|
|
||||||
|
|
||||||
---
|
|
||||||
Makefile | 20 ++++++++++----------
|
|
||||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index e8b8d5894..51e8aac6e 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -442,21 +442,21 @@ KBUILD_HOSTLDLIBS := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
|
|
||||||
# Make variables (CC, etc...)
|
|
||||||
CPP = $(CC) -E
|
|
||||||
ifneq ($(LLVM),)
|
|
||||||
-CC = clang
|
|
||||||
-LD = ld.lld
|
|
||||||
-AR = llvm-ar
|
|
||||||
+CC = $(CCACHE) clang
|
|
||||||
+LD = $(CCACHE) ld.lld
|
|
||||||
+AR = $(CCACHE) llvm-ar
|
|
||||||
NM = llvm-nm
|
|
||||||
-OBJCOPY = llvm-objcopy
|
|
||||||
-OBJDUMP = llvm-objdump
|
|
||||||
+OBJCOPY = $(CCACHE) llvm-objcopy
|
|
||||||
+OBJDUMP = $(CCACHE) llvm-objdump
|
|
||||||
READELF = llvm-readelf
|
|
||||||
STRIP = llvm-strip
|
|
||||||
else
|
|
||||||
-CC = $(CROSS_COMPILE)gcc
|
|
||||||
-LD = $(CROSS_COMPILE)ld
|
|
||||||
-AR = $(CROSS_COMPILE)ar
|
|
||||||
+CC = $(CCACHE) $(CROSS_COMPILE)gcc
|
|
||||||
+LD = $(CCACHE) $(CROSS_COMPILE)ld
|
|
||||||
+AR = $(CCACHE) $(CROSS_COMPILE)ar
|
|
||||||
NM = $(CROSS_COMPILE)nm
|
|
||||||
-OBJCOPY = $(CROSS_COMPILE)objcopy
|
|
||||||
-OBJDUMP = $(CROSS_COMPILE)objdump
|
|
||||||
+OBJCOPY = $(CCACHE) $(CROSS_COMPILE)objcopy
|
|
||||||
+OBJDUMP = $(CCACHE) $(CROSS_COMPILE)objdump
|
|
||||||
READELF = $(CROSS_COMPILE)readelf
|
|
||||||
STRIP = $(CROSS_COMPILE)strip
|
|
||||||
endif
|
|
||||||
--
|
|
||||||
2.37.2
|
|
||||||
|
|
||||||
24
.github/workflows/build-kernel-a12.yml
vendored
24
.github/workflows/build-kernel-a12.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Build Kernel - Android 12
|
name: Build Kernel - Android 12
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main", "ci"]
|
branches: ["main", "ci", "checkci"]
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/build-kernel-a12.yml"
|
- ".github/workflows/build-kernel-a12.yml"
|
||||||
- ".github/workflows/gki-kernel.yml"
|
- ".github/workflows/gki-kernel.yml"
|
||||||
@@ -17,7 +17,7 @@ on:
|
|||||||
workflow_call:
|
workflow_call:
|
||||||
jobs:
|
jobs:
|
||||||
build-kernel:
|
build-kernel:
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -43,6 +43,8 @@ jobs:
|
|||||||
os_patch_level: 2023-07
|
os_patch_level: 2023-07
|
||||||
- sub_level: 185
|
- sub_level: 185
|
||||||
os_patch_level: 2023-09
|
os_patch_level: 2023-09
|
||||||
|
- sub_level: 198
|
||||||
|
os_patch_level: 2023-11
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -51,13 +53,13 @@ jobs:
|
|||||||
tag: android12-5.10-${{ matrix.os_patch_level }}
|
tag: android12-5.10-${{ matrix.os_patch_level }}
|
||||||
os_patch_level: ${{ matrix.os_patch_level }}
|
os_patch_level: ${{ matrix.os_patch_level }}
|
||||||
patch_path: "5.10"
|
patch_path: "5.10"
|
||||||
|
|
||||||
upload-artifacts:
|
upload-artifacts:
|
||||||
needs: build-kernel
|
needs: build-kernel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
|
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
|
||||||
env:
|
env:
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
|
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
@@ -65,7 +67,7 @@ jobs:
|
|||||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -83,7 +85,7 @@ jobs:
|
|||||||
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
|
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
|
||||||
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
|
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
|
||||||
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
|
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
|
||||||
pip3 install python-telegram-bot
|
pip3 install telethon==1.31.1
|
||||||
|
|
||||||
- name: Set boot sign key
|
- name: Set boot sign key
|
||||||
env:
|
env:
|
||||||
@@ -93,8 +95,12 @@ jobs:
|
|||||||
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
|
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup mutex for uploading
|
- name: Bot session cache
|
||||||
uses: ben-z/gh-action-mutex@v1.0-alpha-7
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
- name: Build boot images
|
- name: Build boot images
|
||||||
run: |
|
run: |
|
||||||
@@ -113,13 +119,13 @@ jobs:
|
|||||||
run: ls -R
|
run: ls -R
|
||||||
|
|
||||||
- name: Upload images artifact
|
- name: Upload images artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot-images-android12
|
name: boot-images-android12
|
||||||
path: Image-android12*/*.img.gz
|
path: Image-android12*/*.img.gz
|
||||||
|
|
||||||
check-build-kernel:
|
check-build-kernel:
|
||||||
if: github.event_name == 'pull_request'
|
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android12-5.10
|
version: android12-5.10
|
||||||
|
|||||||
45
.github/workflows/build-kernel-a13.yml
vendored
45
.github/workflows/build-kernel-a13.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Build Kernel - Android 13
|
name: Build Kernel - Android 13
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main", "ci"]
|
branches: ["main", "ci", "checkci"]
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/build-kernel-a13.yml"
|
- ".github/workflows/build-kernel-a13.yml"
|
||||||
- ".github/workflows/gki-kernel.yml"
|
- ".github/workflows/gki-kernel.yml"
|
||||||
@@ -17,7 +17,7 @@ on:
|
|||||||
workflow_call:
|
workflow_call:
|
||||||
jobs:
|
jobs:
|
||||||
build-kernel:
|
build-kernel:
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -42,6 +42,12 @@ jobs:
|
|||||||
- version: "5.10"
|
- version: "5.10"
|
||||||
sub_level: 186
|
sub_level: 186
|
||||||
os_patch_level: 2023-09
|
os_patch_level: 2023-09
|
||||||
|
- version: "5.10"
|
||||||
|
sub_level: 189
|
||||||
|
os_patch_level: 2023-11
|
||||||
|
- version: "5.10"
|
||||||
|
sub_level: 198
|
||||||
|
os_patch_level: 2023-12
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 41
|
sub_level: 41
|
||||||
os_patch_level: 2022-11
|
os_patch_level: 2022-11
|
||||||
@@ -60,6 +66,12 @@ jobs:
|
|||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 119
|
sub_level: 119
|
||||||
os_patch_level: 2023-09
|
os_patch_level: 2023-09
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 123
|
||||||
|
os_patch_level: 2023-11
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 137
|
||||||
|
os_patch_level: 2023-12
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -68,13 +80,13 @@ jobs:
|
|||||||
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
||||||
os_patch_level: ${{ matrix.os_patch_level }}
|
os_patch_level: ${{ matrix.os_patch_level }}
|
||||||
patch_path: ${{ matrix.version }}
|
patch_path: ${{ matrix.version }}
|
||||||
|
|
||||||
upload-artifacts:
|
upload-artifacts:
|
||||||
needs: build-kernel
|
needs: build-kernel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
|
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
|
||||||
env:
|
env:
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
|
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
@@ -82,7 +94,7 @@ jobs:
|
|||||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -100,7 +112,7 @@ jobs:
|
|||||||
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
|
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
|
||||||
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
|
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
|
||||||
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
|
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
|
||||||
pip3 install python-telegram-bot
|
pip3 install telethon==1.31.1
|
||||||
|
|
||||||
- name: Set boot sign key
|
- name: Set boot sign key
|
||||||
env:
|
env:
|
||||||
@@ -110,8 +122,12 @@ jobs:
|
|||||||
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
|
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup mutex for uploading
|
- name: Bot session cache
|
||||||
uses: ben-z/gh-action-mutex@v1.0-alpha-7
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
- name: Build boot images
|
- name: Build boot images
|
||||||
run: |
|
run: |
|
||||||
@@ -125,30 +141,31 @@ jobs:
|
|||||||
echo "VERSION: $VERSION"
|
echo "VERSION: $VERSION"
|
||||||
cd -
|
cd -
|
||||||
bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh
|
bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh
|
||||||
|
|
||||||
- name: Display structure of boot files
|
- name: Display structure of boot files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
|
|
||||||
- name: Upload images artifact
|
- name: Upload images artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot-images-android13
|
name: boot-images-android13
|
||||||
path: Image-android13*/*.img.gz
|
path: Image-android13*/*.img.gz
|
||||||
|
|
||||||
check-build-kernel:
|
check-build-kernel:
|
||||||
if: github.event_name == 'pull_request'
|
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- version: "5.10"
|
- version: "5.10"
|
||||||
sub_level: 187
|
sub_level: 189
|
||||||
os_patch_level: 2023-08
|
os_patch_level: 2023-10
|
||||||
- version: "5.15"
|
- version: "5.15"
|
||||||
sub_level: 119
|
sub_level: 123
|
||||||
os_patch_level: 2023-09
|
os_patch_level: 2023-10
|
||||||
uses: ./.github/workflows/gki-kernel.yml
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
with:
|
with:
|
||||||
version: android13-${{ matrix.version }}
|
version: android13-${{ matrix.version }}
|
||||||
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
|
version_name: android13-${{ matrix.version }}.${{ matrix.sub_level }}
|
||||||
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
tag: android13-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
||||||
|
os_patch_level: ${{ matrix.os_patch_level }}
|
||||||
patch_path: ${{ matrix.version }}
|
patch_path: ${{ matrix.version }}
|
||||||
|
|||||||
132
.github/workflows/build-kernel-a14.yml
vendored
Normal file
132
.github/workflows/build-kernel-a14.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
name: Build Kernel - Android 14
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main", "ci", "checkci"]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/build-kernel-a14.yml"
|
||||||
|
- ".github/workflows/gki-kernel.yml"
|
||||||
|
- ".github/scripts/build_a13.sh"
|
||||||
|
- "kernel/**"
|
||||||
|
pull_request:
|
||||||
|
branches: ["main"]
|
||||||
|
paths:
|
||||||
|
- ".github/workflows/build-kernel-a14.yml"
|
||||||
|
- ".github/workflows/gki-kernel.yml"
|
||||||
|
- ".github/scripts/build-a13.sh"
|
||||||
|
- "kernel/**"
|
||||||
|
workflow_call:
|
||||||
|
jobs:
|
||||||
|
build-kernel:
|
||||||
|
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 110
|
||||||
|
os_patch_level: 2023-09
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 131
|
||||||
|
os_patch_level: 2023-11
|
||||||
|
- version: "6.1"
|
||||||
|
sub_level: 25
|
||||||
|
os_patch_level: 2023-10
|
||||||
|
- version: "6.1"
|
||||||
|
sub_level: 43
|
||||||
|
os_patch_level: 2023-11
|
||||||
|
- version: "6.1"
|
||||||
|
sub_level: 57
|
||||||
|
os_patch_level: 2023-12
|
||||||
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
version: android14-${{ matrix.version }}
|
||||||
|
version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }}
|
||||||
|
tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
||||||
|
os_patch_level: ${{ matrix.os_patch_level }}
|
||||||
|
patch_path: ${{ matrix.version }}
|
||||||
|
|
||||||
|
upload-artifacts:
|
||||||
|
needs: build-kernel
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }}
|
||||||
|
env:
|
||||||
|
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 }}
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: KernelSU
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: List artifacts
|
||||||
|
run: |
|
||||||
|
tree
|
||||||
|
|
||||||
|
- name: Download prebuilt toolchain
|
||||||
|
run: |
|
||||||
|
AOSP_MIRROR=https://android.googlesource.com
|
||||||
|
BRANCH=main-kernel-build-2023
|
||||||
|
git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools
|
||||||
|
git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools
|
||||||
|
git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1
|
||||||
|
pip3 install telethon==1.31.1
|
||||||
|
|
||||||
|
- name: Set boot sign key
|
||||||
|
env:
|
||||||
|
BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }}
|
||||||
|
run: |
|
||||||
|
if [ ! -z "$BOOT_SIGN_KEY" ]; then
|
||||||
|
echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Bot session cache
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
|
- name: Build boot images
|
||||||
|
run: |
|
||||||
|
export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool
|
||||||
|
export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip
|
||||||
|
export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4
|
||||||
|
export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py
|
||||||
|
export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py
|
||||||
|
cd $GITHUB_WORKSPACE/KernelSU
|
||||||
|
export VERSION=$(($(git rev-list --count HEAD) + 10200))
|
||||||
|
echo "VERSION: $VERSION"
|
||||||
|
cd -
|
||||||
|
bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh
|
||||||
|
|
||||||
|
- name: Display structure of boot files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: Upload images artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: boot-images-android14
|
||||||
|
path: Image-android14*/*.img.gz
|
||||||
|
|
||||||
|
check-build-kernel:
|
||||||
|
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- version: "5.15"
|
||||||
|
sub_level: 110
|
||||||
|
os_patch_level: 2023-09
|
||||||
|
uses: ./.github/workflows/gki-kernel.yml
|
||||||
|
with:
|
||||||
|
version: android14-${{ matrix.version }}
|
||||||
|
version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }}
|
||||||
|
tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }}
|
||||||
|
os_patch_level: ${{ matrix.os_patch_level }}
|
||||||
|
patch_path: ${{ matrix.version }}
|
||||||
18
.github/workflows/build-kernel-arcvm.yml
vendored
18
.github/workflows/build-kernel-arcvm.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Build Kernel - ChromeOS ARCVM
|
name: Build Kernel - ChromeOS ARCVM
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["main", "ci", "checkci"]
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/build-kernel-arcvm.yml"
|
- ".github/workflows/build-kernel-arcvm.yml"
|
||||||
- "kernel/**"
|
- "kernel/**"
|
||||||
@@ -15,6 +15,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
if: github.event_name != 'pull_request' || (github.event_name == 'pull_request' && !github.event.pull_request.draft)
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: [x86_64]
|
arch: [x86_64]
|
||||||
@@ -81,7 +82,7 @@ jobs:
|
|||||||
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
||||||
|
|
||||||
echo "[+] Apply KernelSU patches"
|
echo "[+] Apply KernelSU patches"
|
||||||
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.10/*.patch
|
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.10/*.patch || echo "[-] No patch found"
|
||||||
|
|
||||||
echo "[+] Patch script/setlocalversion"
|
echo "[+] Patch script/setlocalversion"
|
||||||
sed -i 's/-dirty//g' $KERNEL_ROOT/scripts/setlocalversion
|
sed -i 's/-dirty//g' $KERNEL_ROOT/scripts/setlocalversion
|
||||||
@@ -110,16 +111,23 @@ jobs:
|
|||||||
echo "file_path=${PWD}/arch/x86/boot/bzImage" >> $GITHUB_ENV
|
echo "file_path=${PWD}/arch/x86/boot/bzImage" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Upload kernel-ARCVM-${{ matrix.arch }}-${{ matrix.version }}
|
- name: Upload kernel-ARCVM-${{ matrix.arch }}-${{ matrix.version }}
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: kernel-ARCVM-${{ matrix.arch }}-${{ matrix.version }}
|
name: kernel-ARCVM-${{ matrix.arch }}-${{ matrix.version }}
|
||||||
path: "${{ env.file_path }}"
|
path: "${{ env.file_path }}"
|
||||||
|
|
||||||
|
- name: Bot session cache
|
||||||
|
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
- name: Post to Telegram
|
- name: Post to Telegram
|
||||||
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
|
if: ${{ ( github.event_name == 'push' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
|
||||||
env:
|
env:
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
|
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
@@ -135,6 +143,6 @@ jobs:
|
|||||||
echo "[+] Image to upload"
|
echo "[+] Image to upload"
|
||||||
ls -l "${{ env.file_path }}.gz"
|
ls -l "${{ env.file_path }}.gz"
|
||||||
if [ -n "${{ secrets.BOT_TOKEN }}" ]; then
|
if [ -n "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
pip3 install python-telegram-bot
|
pip3 install telethon==1.31.1
|
||||||
python3 "$GITHUB_WORKSPACE/KernelSU/scripts/ksubot.py" "${{ env.file_path }}.gz"
|
python3 "$GITHUB_WORKSPACE/KernelSU/scripts/ksubot.py" "${{ env.file_path }}.gz"
|
||||||
fi
|
fi
|
||||||
|
|||||||
129
.github/workflows/build-kernel-wsa.yml
vendored
129
.github/workflows/build-kernel-wsa.yml
vendored
@@ -1,131 +1,38 @@
|
|||||||
name: Build Kernel - WSA
|
name: Build Kernel - WSA
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["main", "ci", "checkci"]
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/build-kernel-wsa.yml"
|
- ".github/workflows/build-kernel-wsa.yml"
|
||||||
|
- ".github/workflows/wsa-kernel.yml"
|
||||||
- "kernel/**"
|
- "kernel/**"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/build-kernel-wsa.yml"
|
- ".github/workflows/build-kernel-wsa.yml"
|
||||||
|
- ".github/workflows/wsa-kernel.yml"
|
||||||
- "kernel/**"
|
- "kernel/**"
|
||||||
workflow_call:
|
workflow_call:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
arch: [x86_64, arm64]
|
arch: [x86_64, arm64]
|
||||||
version: ["5.15.94.2", "5.15.104.1", "5.15.104.2", "5.15.104.3"]
|
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 }}
|
||||||
|
|
||||||
name: Build WSA-Kernel-${{ matrix.version }}-${{ matrix.arch }}
|
check_build:
|
||||||
runs-on: ubuntu-20.04
|
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
|
||||||
env:
|
uses: ./.github/workflows/wsa-kernel.yml
|
||||||
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
|
strategy:
|
||||||
CCACHE_NOHASHDIR: "true"
|
matrix:
|
||||||
CCACHE_HARDLINK: "true"
|
arch: [x86_64, arm64]
|
||||||
|
with:
|
||||||
steps:
|
arch: ${{ matrix.arch }}
|
||||||
- name: Install Build Tools
|
version: "5.15.104.4"
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends bc bison build-essential ca-certificates flex git gnupg libelf-dev libssl-dev lsb-release software-properties-common wget libncurses-dev binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu nuget gzip
|
|
||||||
export LLVM_VERSION=12
|
|
||||||
wget -q https://apt.llvm.org/llvm.sh
|
|
||||||
sudo bash ./llvm.sh $LLVM_VERSION
|
|
||||||
cd /usr/bin
|
|
||||||
sudo ln -sf clang-$LLVM_VERSION clang
|
|
||||||
sudo ln -sf ld.lld-$LLVM_VERSION ld.lld
|
|
||||||
sudo ln -sf llvm-objdump-$LLVM_VERSION llvm-objdump
|
|
||||||
sudo ln -sf llvm-ar-$LLVM_VERSION llvm-ar
|
|
||||||
sudo ln -sf llvm-nm-$LLVM_VERSION llvm-nm
|
|
||||||
sudo ln -sf llvm-strip-$LLVM_VERSION llvm-strip
|
|
||||||
sudo ln -sf llvm-objcopy-$LLVM_VERSION llvm-objcopy
|
|
||||||
sudo ln -sf llvm-readelf-$LLVM_VERSION llvm-readelf
|
|
||||||
sudo ln -sf clang++-$LLVM_VERSION clang++
|
|
||||||
|
|
||||||
- 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/${{ matrix.version }}
|
|
||||||
path: WSA-Linux-Kernel
|
|
||||||
|
|
||||||
- name: Setup Ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
|
||||||
with:
|
|
||||||
key: WSA-Kernel-${{ matrix.version }}-${{ matrix.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
|
|
||||||
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
|
||||||
echo "[+] Apply KernelSU patches"
|
|
||||||
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.15/*.patch
|
|
||||||
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: |
|
|
||||||
declare -A ARCH_MAP=(["x86_64"]="x64" ["arm64"]="arm64")
|
|
||||||
cp configs/wsa/config-wsa-${ARCH_MAP[${{ matrix.arch }}]} .config
|
|
||||||
make olddefconfig
|
|
||||||
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 FILE_NAME=(["x86_64"]="bzImage" ["arm64"]="Image")
|
|
||||||
make -j`nproc` LLVM=1 ARCH=${{ matrix.arch }} $(if [ "${{ matrix.arch }}" == "arm64" ]; then echo CROSS_COMPILE=aarch64-linux-gnu; fi) ${FILE_NAME[${{ matrix.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[${{ matrix.arch }}]}/boot/${FILE_NAME[${{ matrix.arch }}]}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Upload kernel-${{ matrix.arch }}-${{ matrix.version }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: kernel-WSA-${{ matrix.arch }}-${{ matrix.version }}
|
|
||||||
path: "${{ env.file_path }}"
|
|
||||||
|
|
||||||
- name: Post to Telegram
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.ref_type == 'tag'
|
|
||||||
env:
|
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_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 }}
|
|
||||||
run: |
|
|
||||||
TITLE=kernel-${{ matrix.arch }}-WSA-${{ matrix.version }}
|
|
||||||
echo "[+] title: $TITLE"
|
|
||||||
export TITLE
|
|
||||||
export VERSION="${{ env.kernelsu_version }}"
|
|
||||||
echo "[+] Compress images"
|
|
||||||
gzip -n -f -9 "${{ env.file_path }}"
|
|
||||||
echo "[+] Image to upload"
|
|
||||||
ls -l "${{ env.file_path }}.gz"
|
|
||||||
if [ -n "${{ secrets.BOT_TOKEN }}" ]; then
|
|
||||||
pip3 install python-telegram-bot
|
|
||||||
python3 "$GITHUB_WORKSPACE/KernelSU/scripts/ksubot.py" "${{ env.file_path }}.gz"
|
|
||||||
fi
|
|
||||||
47
.github/workflows/build-manager.yml
vendored
47
.github/workflows/build-manager.yml
vendored
@@ -50,15 +50,17 @@ jobs:
|
|||||||
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
|
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
|
||||||
run: |
|
run: |
|
||||||
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
|
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
|
||||||
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}' >> gradle.properties
|
{
|
||||||
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}' >> gradle.properties
|
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
|
||||||
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}' >> gradle.properties
|
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
|
||||||
echo KEYSTORE_FILE='../key.jks' >> gradle.properties
|
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
|
||||||
echo ${{ secrets.KEYSTORE }} | base64 --decode > key.jks
|
echo KEYSTORE_FILE='../key.jks'
|
||||||
|
} >> gradle.properties
|
||||||
|
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
java-version: "17"
|
java-version: "17"
|
||||||
@@ -69,13 +71,13 @@ jobs:
|
|||||||
gradle-home-cache-cleanup: true
|
gradle-home-cache-cleanup: true
|
||||||
|
|
||||||
- name: Download arm64 ksud
|
- name: Download arm64 ksud
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud-aarch64-linux-android
|
name: ksud-aarch64-linux-android
|
||||||
path: .
|
path: .
|
||||||
|
|
||||||
- name: Download x86_64 ksud
|
- name: Download x86_64 ksud
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud-x86_64-linux-android
|
name: ksud-x86_64-linux-android
|
||||||
path: .
|
path: .
|
||||||
@@ -89,28 +91,39 @@ jobs:
|
|||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: |
|
run: |
|
||||||
echo 'org.gradle.parallel=true' >> gradle.properties
|
{
|
||||||
echo 'org.gradle.vfs.watch=true' >> gradle.properties
|
echo 'org.gradle.parallel=true'
|
||||||
echo 'org.gradle.jvmargs=-Xmx2048m' >> gradle.properties
|
echo 'org.gradle.vfs.watch=true'
|
||||||
echo 'android.native.buildOutput=verbose' >> gradle.properties
|
echo 'org.gradle.jvmargs=-Xmx2048m'
|
||||||
|
echo 'android.native.buildOutput=verbose'
|
||||||
|
} >> gradle.properties
|
||||||
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
|
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
|
||||||
./gradlew clean assembleRelease
|
./gradlew clean assembleRelease
|
||||||
|
|
||||||
- name: Upload build artifact
|
- name: Upload build artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: manager
|
name: manager
|
||||||
path: manager/app/build/outputs/apk/release/*.apk
|
path: manager/app/build/outputs/apk/release/*.apk
|
||||||
|
|
||||||
- name: Setup mutex for uploading
|
- name: Upload mappings
|
||||||
uses: ben-z/gh-action-mutex@v1.0-alpha-7
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: "mappings"
|
||||||
|
path: "manager/app/build/outputs/mapping/release/"
|
||||||
|
|
||||||
|
- name: Bot session cache
|
||||||
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
- name: Upload to telegram
|
- name: Upload to telegram
|
||||||
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
env:
|
env:
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
|
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
@@ -121,6 +134,6 @@ jobs:
|
|||||||
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
export VERSION=$(git rev-list --count HEAD)
|
export VERSION=$(git rev-list --count HEAD)
|
||||||
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
|
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
|
||||||
pip3 install python-telegram-bot
|
pip3 install telethon==1.31.1
|
||||||
python3 $GITHUB_WORKSPACE/scripts/ksubot.py $APK
|
python3 $GITHUB_WORKSPACE/scripts/ksubot.py $APK
|
||||||
fi
|
fi
|
||||||
|
|||||||
18
.github/workflows/build-su.yml
vendored
18
.github/workflows/build-su.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Build SU
|
name: Build SU
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: [ "main", "ci" ]
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/build-su.yml'
|
- '.github/workflows/build-su.yml'
|
||||||
- 'userspace/su/**'
|
- 'userspace/su/**'
|
||||||
@@ -28,24 +28,26 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
- uses: nttld/setup-ndk@v1
|
- uses: nttld/setup-ndk@v1
|
||||||
with:
|
with:
|
||||||
ndk-version: r25b
|
ndk-version: r25c
|
||||||
local-cache: true
|
|
||||||
- name: Build su
|
- name: Build su
|
||||||
working-directory: ./userspace/su
|
working-directory: ./userspace/su
|
||||||
run: ndk-build
|
run: ndk-build
|
||||||
- name: Upload a Build Artifact
|
- name: Upload a Build Artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: su
|
name: su
|
||||||
path: ./userspace/su/libs
|
path: ./userspace/su/libs
|
||||||
- name: Setup mutex for uploading
|
- name: Bot session cache
|
||||||
uses: ben-z/gh-action-mutex@v1.0-alpha-7
|
|
||||||
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
- name: Upload to telegram
|
- name: Upload to telegram
|
||||||
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true'
|
||||||
env:
|
env:
|
||||||
CHAT_ID: ${{ secrets.CHAT_ID }}
|
CHAT_ID: ${{ secrets.CHAT_ID }}
|
||||||
CACHE_CHAT_ID: ${{ secrets.CACHE_CHAT_ID }}
|
|
||||||
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
|
||||||
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
||||||
@@ -55,7 +57,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
export VERSION=$(git rev-list --count HEAD)
|
export VERSION=$(git rev-list --count HEAD)
|
||||||
pip3 install python-telegram-bot
|
pip3 install telethon==1.31.1
|
||||||
mv ./userspace/su/libs/arm64-v8a/su su-arm64
|
mv ./userspace/su/libs/arm64-v8a/su su-arm64
|
||||||
mv ./userspace/su/libs/x86_64/su su-x86_64
|
mv ./userspace/su/libs/x86_64/su su-x86_64
|
||||||
python3 scripts/ksubot.py su-arm64 su-x86_64
|
python3 scripts/ksubot.py su-arm64 su-x86_64
|
||||||
|
|||||||
2
.github/workflows/clippy.yml
vendored
2
.github/workflows/clippy.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
workspaces: userspace/ksud
|
workspaces: userspace/ksud
|
||||||
|
|
||||||
- name: Install cross
|
- name: Install cross
|
||||||
run: cargo install cross
|
run: cargo install cross --locked
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
62
.github/workflows/deploy-website.yml
vendored
62
.github/workflows/deploy-website.yml
vendored
@@ -8,30 +8,60 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- '.github/workflows/deploy-website.yml'
|
- '.github/workflows/deploy-website.yml'
|
||||||
- 'website/**'
|
- 'website/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||||
|
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||||
|
concurrency:
|
||||||
|
group: pages
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
# Build job
|
||||||
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: ./website
|
working-directory: ./website
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0 # Not needed if lastUpdated is not enabled
|
||||||
- uses: actions/setup-node@v3
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
cache: yarn
|
cache: yarn # or pnpm / yarn
|
||||||
cache-dependency-path: website/yarn.lock
|
cache-dependency-path: website/yarn.lock
|
||||||
- run: yarn install --frozen-lockfile
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
- name: Build
|
- name: Install dependencies
|
||||||
run: yarn docs:build
|
run: yarn install --frozen-lockfile
|
||||||
|
- name: Build with VitePress
|
||||||
- name: Deploy
|
run: |
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
yarn docs:build
|
||||||
|
touch docs/.vitepress/dist/.nojekyll
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
path: website/docs/.vitepress/dist
|
||||||
publish_dir: website/docs/.vitepress/dist
|
|
||||||
cname: kernelsu.org # if wanna deploy to custom domain
|
# Deployment job
|
||||||
|
deploy:
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Deploy
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
|
|||||||
29
.github/workflows/gki-kernel.yml
vendored
29
.github/workflows/gki-kernel.yml
vendored
@@ -54,8 +54,6 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
CHAT_ID:
|
CHAT_ID:
|
||||||
required: false
|
required: false
|
||||||
CACHE_CHAT_ID:
|
|
||||||
required: false
|
|
||||||
BOT_TOKEN:
|
BOT_TOKEN:
|
||||||
required: false
|
required: false
|
||||||
MESSAGE_THREAD_ID:
|
MESSAGE_THREAD_ID:
|
||||||
@@ -128,14 +126,13 @@ jobs:
|
|||||||
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
|
DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
|
||||||
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
||||||
echo "[+] Apply KernelSU patches"
|
echo "[+] Apply KernelSU patches"
|
||||||
cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch
|
cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found"
|
||||||
echo "[+] Patch script/setlocalversion"
|
|
||||||
sed -i 's/-dirty//g' $GKI_ROOT/common/scripts/setlocalversion
|
|
||||||
|
|
||||||
if [ "$IS_DEBUG_KERNEL" = "true" ]; then
|
if [ "$IS_DEBUG_KERNEL" = "true" ]; then
|
||||||
echo "[+] Enable debug features for kernel"
|
echo "[+] Enable debug features for kernel"
|
||||||
echo "ccflags-y += -DCONFIG_KSU_DEBUG" >> $GITHUB_WORKSPACE/KernelSU/kernel/Makefile
|
echo "ccflags-y += -DCONFIG_KSU_DEBUG" >> $GITHUB_WORKSPACE/KernelSU/kernel/Makefile
|
||||||
fi
|
fi
|
||||||
|
repo status
|
||||||
echo "[+] KernelSU setup done."
|
echo "[+] KernelSU setup done."
|
||||||
|
|
||||||
- name: Symbol magic
|
- name: Symbol magic
|
||||||
@@ -157,6 +154,15 @@ jobs:
|
|||||||
max-size: 2G
|
max-size: 2G
|
||||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||||
|
|
||||||
|
- name: Make working directory clean to avoid dirty
|
||||||
|
working-directory: android-kernel
|
||||||
|
run: |
|
||||||
|
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
|
||||||
|
git config --global user.email "bot@kernelsu.org"
|
||||||
|
git config --global user.name "KernelSUBot"
|
||||||
|
cd common/ && git add -A && git commit -a -m "Add KernelSU"
|
||||||
|
repo status
|
||||||
|
|
||||||
- name: Build boot.img
|
- name: Build boot.img
|
||||||
working-directory: android-kernel
|
working-directory: android-kernel
|
||||||
run: |
|
run: |
|
||||||
@@ -164,12 +170,19 @@ jobs:
|
|||||||
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
|
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
|
||||||
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
|
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
|
||||||
fi
|
fi
|
||||||
CCACHE="/usr/bin/ccache" LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
|
if [ -e build/build.sh ]; then
|
||||||
|
LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="/usr/bin/ccache clang"
|
||||||
|
else
|
||||||
|
tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Prepare artifacts
|
- name: Prepare artifacts
|
||||||
id: prepareArtifacts
|
id: prepareArtifacts
|
||||||
run: |
|
run: |
|
||||||
OUTDIR=android-kernel/out/${{ inputs.version }}/dist
|
OUTDIR=android-kernel/out/${{ inputs.version }}/dist
|
||||||
|
if [ ! -e $OUTDIR ]; then
|
||||||
|
OUTDIR=android-kernel/dist
|
||||||
|
fi
|
||||||
mkdir output
|
mkdir output
|
||||||
cp $OUTDIR/Image ./output/
|
cp $OUTDIR/Image ./output/
|
||||||
cp $OUTDIR/Image.lz4 ./output/
|
cp $OUTDIR/Image.lz4 ./output/
|
||||||
@@ -178,13 +191,13 @@ jobs:
|
|||||||
cp $OUTDIR/Image ./AnyKernel3/
|
cp $OUTDIR/Image ./AnyKernel3/
|
||||||
|
|
||||||
- name: Upload Image and Image.gz
|
- name: Upload Image and Image.gz
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Image-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
|
name: Image-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
|
||||||
path: ./output/*
|
path: ./output/*
|
||||||
|
|
||||||
- name: Upload AnyKernel3
|
- name: Upload AnyKernel3
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
|
name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
|
||||||
path: ./AnyKernel3/*
|
path: ./AnyKernel3/*
|
||||||
|
|||||||
4
.github/workflows/ksud.yml
vendored
4
.github/workflows/ksud.yml
vendored
@@ -24,13 +24,13 @@ jobs:
|
|||||||
cache-targets: false
|
cache-targets: false
|
||||||
|
|
||||||
- name: Install cross
|
- name: Install cross
|
||||||
run: cargo install cross
|
run: cargo install cross --locked
|
||||||
|
|
||||||
- name: Build ksud
|
- name: Build ksud
|
||||||
run: cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud/Cargo.toml
|
run: cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud/Cargo.toml
|
||||||
|
|
||||||
- name: Upload ksud artifact
|
- name: Upload ksud artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ksud-${{ inputs.target }}
|
name: ksud-${{ inputs.target }}
|
||||||
path: userspace/ksud/target/**/release/ksud
|
path: userspace/ksud/target/**/release/ksud
|
||||||
|
|||||||
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -11,23 +11,31 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
build-a12-kernel:
|
build-a12-kernel:
|
||||||
uses: ./.github/workflows/build-kernel-a12.yml
|
uses: ./.github/workflows/build-kernel-a12.yml
|
||||||
|
secrets: inherit
|
||||||
build-a13-kernel:
|
build-a13-kernel:
|
||||||
uses: ./.github/workflows/build-kernel-a13.yml
|
uses: ./.github/workflows/build-kernel-a13.yml
|
||||||
|
secrets: inherit
|
||||||
|
build-a14-kernel:
|
||||||
|
uses: ./.github/workflows/build-kernel-a14.yml
|
||||||
|
secrets: inherit
|
||||||
build-wsa-kernel:
|
build-wsa-kernel:
|
||||||
uses: ./.github/workflows/build-kernel-wsa.yml
|
uses: ./.github/workflows/build-kernel-wsa.yml
|
||||||
|
secrets: inherit
|
||||||
build-arcvm-kernel:
|
build-arcvm-kernel:
|
||||||
uses: ./.github/workflows/build-kernel-arcvm.yml
|
uses: ./.github/workflows/build-kernel-arcvm.yml
|
||||||
|
secrets: inherit
|
||||||
release:
|
release:
|
||||||
needs:
|
needs:
|
||||||
- build-manager
|
- build-manager
|
||||||
- build-a12-kernel
|
- build-a12-kernel
|
||||||
- build-a13-kernel
|
- build-a13-kernel
|
||||||
|
- build-a14-kernel
|
||||||
- build-wsa-kernel
|
- build-wsa-kernel
|
||||||
- build-arcvm-kernel
|
- build-arcvm-kernel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
- name: Zip AnyKernel3
|
- name: Zip AnyKernel3
|
||||||
run: |
|
run: |
|
||||||
for dir in AnyKernel3-*; do
|
for dir in AnyKernel3-*; do
|
||||||
|
|||||||
135
.github/workflows/wsa-kernel.yml
vendored
Normal file
135
.github/workflows/wsa-kernel.yml
vendored
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
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-20.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@v3
|
||||||
|
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.2
|
||||||
|
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
|
||||||
|
grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE
|
||||||
|
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 }}"
|
||||||
|
|
||||||
|
- name: Bot session cache
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.ref_type == 'tag'
|
||||||
|
id: bot_session_cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: scripts/ksubot.session
|
||||||
|
key: ${{ runner.os }}-bot-session
|
||||||
|
|
||||||
|
- name: Post to Telegram
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.ref_type == 'tag'
|
||||||
|
env:
|
||||||
|
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 }}
|
||||||
|
run: |
|
||||||
|
TITLE=kernel-${{ inputs.arch }}-WSA-${{ inputs.version }}
|
||||||
|
echo "[+] title: $TITLE"
|
||||||
|
export TITLE
|
||||||
|
export VERSION="${{ env.kernelsu_version }}"
|
||||||
|
echo "[+] Compress images"
|
||||||
|
gzip -n -f -9 "${{ env.file_path }}"
|
||||||
|
echo "[+] Image to upload"
|
||||||
|
ls -l "${{ env.file_path }}.gz"
|
||||||
|
if [ -n "${{ secrets.BOT_TOKEN }}" ]; then
|
||||||
|
pip3 install telethon==1.31.1
|
||||||
|
python3 "$GITHUB_WORKSPACE/KernelSU/scripts/ksubot.py" "${{ env.file_path }}.gz"
|
||||||
|
fi
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
|
**English** | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
**English** | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
A Kernel-based root solution for Android devices.
|
A Kernel-based root solution for Android devices.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
1. Kernel-based `su` and root access management.
|
1. Kernel-based `su` and root access management.
|
||||||
2. Module system based on overlayfs.
|
2. Module system based on [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage.
|
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage.
|
||||||
|
|
||||||
## Compatibility State
|
## Compatibility State
|
||||||
@@ -27,16 +34,20 @@ Currently, only `arm64-v8a` and `x86_64` are supported.
|
|||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
To help translate KernelSU or improve existing translations, please use [Weblate](https://hosted.weblate.org/engage/kernelsu/).
|
To help translate KernelSU or improve existing translations, please use [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR of Manager's translation is no longer accepted, because it will conflict with Weblate.
|
||||||
|
|
||||||
## Discussion
|
## Discussion
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
For information on reporting security vulnerabilities in KernelSU, see [SECURITY.md](/SECURITY.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
- Files under the `kernel` directory are [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- Files under the `kernel` directory are [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- All other parts except the `kernel` directory are [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- All other parts except the `kernel` directory are [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | **简体中文** | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | **简体中文** | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
一个 Android 上基于内核的 root 方案。
|
一个 Android 上基于内核的 root 方案。
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 基于内核的 su 和权限管理。
|
- 基于内核的 `su` 和权限管理。
|
||||||
- 基于 overlayfs 的模块系统。
|
- 基于 [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模块系统。
|
||||||
- [App Profile](https://kernelsu.org/guide/app-profile.html): 把 Root 权限关进笼子里。
|
- [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html): 把 Root 权限关进笼子里。
|
||||||
|
|
||||||
## 兼容状态
|
## 兼容状态
|
||||||
|
|
||||||
@@ -16,25 +24,30 @@ KernelSU 官方支持 GKI 2.0 的设备(内核版本5.10以上);旧内核
|
|||||||
|
|
||||||
WSA, ChromeOS 和运行在容器上的 Android 也可以与 KernelSU 一起工作。
|
WSA, ChromeOS 和运行在容器上的 Android 也可以与 KernelSU 一起工作。
|
||||||
|
|
||||||
目前支持架构 : `arm64-v8a` 和 `x86_64`
|
目前支持架构 : `arm64-v8a` 和 `x86_64`。
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
- [安装教程](https://kernelsu.org/zh_CN/guide/installation.html)
|
- [安装教程](https://kernelsu.org/zh_CN/guide/installation.html)
|
||||||
- [如何构建?](https://kernelsu.org/zh_CN/guide/how-to-build.html)
|
- [如何构建?](https://kernelsu.org/zh_CN/guide/how-to-build.html)
|
||||||
|
- [官方网站](https://kernelsu.org/zh_CN/)
|
||||||
|
|
||||||
## 参与翻译
|
## 参与翻译
|
||||||
|
|
||||||
要将 KernelSU 翻译成您的语言,或完善现有的翻译,请使用 [Weblate](https://hosted.weblate.org/engage/kernelsu/)。
|
要将 KernelSU 翻译成您的语言,或完善现有的翻译,请使用 [Weblate](https://hosted.weblate.org/engage/kernelsu/)。现已不再接受有关管理器翻译的PR,因为这会与Weblate冲突。
|
||||||
|
|
||||||
## 讨论
|
## 讨论
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
|
## 安全性
|
||||||
|
|
||||||
|
有关报告 KernelSU 安全漏洞的信息,请参阅 [SECURITY.md](/SECURITY.md)。
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
- 目录 `kernel` 下所有文件为 [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- 目录 `kernel` 下所有文件为 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
|
||||||
- 除 `kernel` 目录的其他部分均为 [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- 除 `kernel` 目录的其他部分均为 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。
|
||||||
|
|
||||||
## 鸣谢
|
## 鸣谢
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +1,56 @@
|
|||||||
[ 🇬🇧 English](README.md) | 🇪🇸 **Español** | [🇨🇳 简体中文](README_CN.md) | [🇹🇼 繁體中文](README_TW.md) | [ 🇯🇵 日本語](README_JP.md) | [🇵🇱 Polski](README_PL.md) | [🇧🇷 Portuguese-Brazil](README_PT-BR.md) | [🇹🇷 Türkçe](README_TR.md) | [🇷🇺Русский](README_RU.md) | [🇻🇳Tiếng Việt](README_VI.md) | [ɪᴅ indonesia](README_ID.md) | [עברית](README_iw.md) | [🇮🇳हिंदी](README_IN.md)
|
[English](README.md) | **Español** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
<div style="display: flex; align-items: center;">
|
# KernelSU
|
||||||
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="">
|
|
||||||
<div style="margin-left: 20px;">
|
|
||||||
<span style="font-size: large; "><b>KernelSU</b></span>
|
|
||||||
<br>
|
|
||||||
<span style="font-size: medium; "><i>Una solución root basada en el kernel para dispositivos Android.</i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 🚀 Características
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
**1.** Binario `su` basado en el kernel y gestión de acceso root.<br/>
|
Una solución root basada en el kernel para dispositivos Android.
|
||||||
**2.** Sistema de módulos basado en **OverlayFS**.
|
|
||||||
|
|
||||||
## ✅ Estado de compatibilidad
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
|
## Características
|
||||||
|
|
||||||
|
1. Binario `su` basado en el kernel y gestión de acceso root.
|
||||||
|
2. Sistema de módulos basado en [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
|
|
||||||
|
## Estado de compatibilidad
|
||||||
|
|
||||||
**KernelSU** soporta de forma oficial dispositivos Android con **GKI 2.0** (a partir de la versión **5.10** del kernel). Los kernels antiguos (a partir de la versión **4.14**) también son compatibles, pero necesitas compilarlos por tu cuenta.
|
**KernelSU** soporta de forma oficial dispositivos Android con **GKI 2.0** (a partir de la versión **5.10** del kernel). Los kernels antiguos (a partir de la versión **4.14**) también son compatibles, pero necesitas compilarlos por tu cuenta.
|
||||||
|
|
||||||
El **Subsistema de Windows para Android (WSA)** e implementaciones de Android basadas en contenedores, como **Waydroid**, también deberían funcionar con **KernelSU** integrado.
|
Con esto, WSA, ChromeOS y Android basado en contenedores están todos compatibles.
|
||||||
|
|
||||||
Actualmente se soportan las siguientes **ABIs**: `arm64-v8a`; `x86_64`.
|
Actualmente, solo se admiten las arquitecturas `arm64-v8a` y `x86_64`.
|
||||||
|
|
||||||
## 📖 Uso
|
## Uso
|
||||||
|
|
||||||
[¿Cómo instalarlo?](https://kernelsu.org/guide/installation.html)
|
- [¿Cómo instalarlo?](https://kernelsu.org/guide/installation.html)
|
||||||
|
- [¿Cómo compilarlo?](https://kernelsu.org/guide/how-to-build.html)
|
||||||
|
- [Site oficial](https://kernelsu.org/)
|
||||||
|
|
||||||
## 🔨 Compilación
|
## Traducción
|
||||||
|
|
||||||
[¿Cómo compilarlo?](https://kernelsu.org/guide/how-to-build.html)
|
Para ayudar a traducir KernelSU o mejorar las traducciones existentes, utilice [Weblate](https://hosted.weblate.org/engage/kernelsu/). Ya no se aceptan PR de la traducción de Manager porque entrará en conflicto con Weblate.
|
||||||
|
|
||||||
## 💬 Discusión
|
## Discusión
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
## ⚖️ Licencia
|
## Seguridad
|
||||||
|
|
||||||
- Los archivos bajo el directorio `kernel` están licenciados bajo [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
Para obtener información sobre cómo informar vulnerabilidades de seguridad en KernelSU, consulte [SECURITY.md](/SECURITY.md).
|
||||||
- Todas las demás partes, a excepción del directorio `kernel`, están licenciados bajo [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html).
|
|
||||||
|
|
||||||
## 👥 Créditos
|
## Licencia
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): la idea de **KernelSU**.
|
- Los archivos bajo el directorio `kernel` están licenciados bajo [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- [genuine](https://github.com/brevent/genuine/): la validación del **esquema de firmas APK v2**.
|
- Todas las demás partes, a excepción del directorio `kernel`, están licenciados bajo [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
|
## Créditos
|
||||||
|
|
||||||
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): la idea de KernelSU.
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): la poderosa herramienta root.
|
||||||
|
- [genuine](https://github.com/brevent/genuine/): validación de firma apk v2.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): algunas habilidades de rootkit.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): algunas habilidades de rootkit.
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): la implementación de la **política de SELinux (SEPolicy)**.
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portugis-Brasil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | **Indonesia** | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | **Indonesia** | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Solusi root berbasis Kernel untuk perangkat Android.
|
Solusi root berbasis Kernel untuk perangkat Android.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Fitur
|
## Fitur
|
||||||
|
|
||||||
1. Manajemen akses root dan `su` berbasis kernel.
|
1. Manajemen akses root dan `su` berbasis kernel.
|
||||||
2. Sistem modul berdasarkan overlayfs.
|
2. Sistem modul berdasarkan [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
3. [Profil Aplikasi](https://kernelsu.org/guide/app-profile.html): Kunci daya root di dalam sangkar.
|
3. [Profil Aplikasi](https://kernelsu.org/guide/app-profile.html): Kunci daya root di dalam sangkar.
|
||||||
|
|
||||||
## Status Kompatibilitas
|
## Status Kompatibilitas
|
||||||
@@ -20,9 +28,9 @@ Dan ABI yang didukung saat ini adalah: `arm64-v8a` dan `x86_64`
|
|||||||
|
|
||||||
## Penggunaan
|
## Penggunaan
|
||||||
|
|
||||||
- [Petunjuk Instalasi](https://kernelsu.org/guide/installation.html)
|
- [Petunjuk Instalasi](https://kernelsu.org/id_ID/guide/installation.html)
|
||||||
- [Bagaimana cara membuat?](https://kernelsu.org/guide/how-to-build.html)
|
- [Bagaimana cara membuat?](https://kernelsu.org/id_ID/guide/how-to-build.html)
|
||||||
- [Situs Web Resmi](https://kernelsu.org/)
|
- [Situs Web Resmi](https://kernelsu.org/id_ID/)
|
||||||
|
|
||||||
## Terjemahan
|
## Terjemahan
|
||||||
|
|
||||||
@@ -34,8 +42,8 @@ Untuk menerjemahkan KernelSU ke dalam bahasa Anda atau menyempurnakan terjemahan
|
|||||||
|
|
||||||
## Lisensi
|
## Lisensi
|
||||||
|
|
||||||
- File di bawah direktori `kernel` adalah [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- File di bawah direktori `kernel` adalah [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- Semua bagian lain kecuali direktori `kernel` adalah [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- Semua bagian lain kecuali direktori `kernel` adalah [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## Kredit
|
## Kredit
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | **हिंदी**
|
||||||
|
|
||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | **हिंदी**
|
# KernelSU
|
||||||
|
|
||||||
<div style="display: flex; align-items: center;">
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="">
|
|
||||||
<div style="margin-left: 20px;">
|
Android उपकरणों के लिए कर्नेल-आधारित रूट समाधान।
|
||||||
<span style="font-size: large; "><b>KernelSU</b></span>
|
|
||||||
<br>
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
<span style="font-size: medium; "><i>Android उपकरणों के लिए कर्नेल-आधारित रूट समाधान।</i></span>
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
</div>
|
[](https://t.me/KernelSU)
|
||||||
</div>
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## विशेषताएँ
|
## विशेषताएँ
|
||||||
|
|
||||||
1. कर्नेल-आधारित `su` और रूट एक्सेस प्रबंधन।
|
1. कर्नेल-आधारित `su` और रूट एक्सेस प्रबंधन।
|
||||||
2. Overlayfs पर आधारित मॉड्यूल प्रणाली।
|
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) पर आधारित मॉड्यूल प्रणाली।
|
||||||
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Root शक्ति को पिंजरे में बंद कर दो।
|
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Root शक्ति को पिंजरे में बंद कर दो।
|
||||||
|
|
||||||
## अनुकूलता अवस्था
|
## अनुकूलता अवस्था
|
||||||
@@ -40,8 +42,8 @@ KernelSU का अनुवाद करने या मौजूदा अन
|
|||||||
|
|
||||||
## लाइसेंस
|
## लाइसेंस
|
||||||
|
|
||||||
- `Kernel` निर्देशिका के अंतर्गत फ़ाइलें हैं [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- `Kernel` निर्देशिका के अंतर्गत फ़ाइलें हैं [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
- `Kernel` निर्देशिका को छोड़कर अन्य सभी भाग हैं [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- `Kernel` निर्देशिका को छोड़कर अन्य सभी भाग हैं [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)
|
||||||
|
|
||||||
## आभार सूची
|
## आभार सूची
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | **עברית** | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | **עברית** | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
פתרון לניהול root מבוסס על Kernel עבור מכשירי Android.
|
פתרון לניהול root מבוסס על Kernel עבור מכשירי Android.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## תכונות
|
## תכונות
|
||||||
|
|
||||||
1. ניהול root ו־`su` מבוססים על Kernel.
|
1. ניהול root ו־`su` מבוססים על Kernel.
|
||||||
2. מערכת מודולים מבוססת overlayfs.
|
2. מערכת מודולים מבוססת [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
3. [פרופיל אפליקציה](https://kernelsu.org/guide/app-profile.html): נעילת גישת root בכלוב.
|
3. [פרופיל אפליקציה](https://kernelsu.org/guide/app-profile.html): נעילת גישת root בכלוב.
|
||||||
|
|
||||||
## מצב תאימות
|
## מצב תאימות
|
||||||
@@ -34,12 +42,12 @@ KernelSU תומך במכשירי Android GKI 2.0 (kernel 5.10+) באופן רש
|
|||||||
|
|
||||||
## רשיון
|
## רשיון
|
||||||
|
|
||||||
- קבצים תחת הספרייה `kernel` מוגנים על פי [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- קבצים תחת הספרייה `kernel` מוגנים על פי [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- כל החלקים האחרים, למעט הספרייה `kernel`, מוגנים על פי [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- כל החלקים האחרים, למעט הספרייה `kernel`, מוגנים על פי [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## קרדיטים
|
## קרדיטים
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): הרעיון של KernelSU.
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): הרעיון של KernelSU.
|
||||||
- [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): כמה יכולות רוט.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): כמה יכולות רוט.
|
||||||
@@ -1,16 +1,23 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **日本語** | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **日本語** | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Android におけるカーネルベースの root ソリューションです。
|
Android におけるカーネルベースの root ソリューションです。
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## 特徴
|
## 特徴
|
||||||
|
|
||||||
1. カーネルベースの `su` と権限管理
|
1. カーネルベースの `su` と権限管理。
|
||||||
2. OverlayFS に基づくモジュールシステム
|
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) に基づくモジュールシステム。
|
||||||
3. [アプリのプロファイル](https://kernelsu.org/guide/app-profile.html): root の権限をケージ内に閉じ込めます。
|
3. [アプリのプロファイル](https://kernelsu.org/guide/app-profile.html): root の権限をケージ内に閉じ込めます。
|
||||||
|
|
||||||
|
|
||||||
## 対応状況
|
## 対応状況
|
||||||
|
|
||||||
KernelSU は GKI 2.0 デバイス(カーネルバージョン 5.10 以上)を公式にサポートしています。古いカーネル(4.14以上)とも互換性がありますが、自分でカーネルをビルドする必要があります。
|
KernelSU は GKI 2.0 デバイス(カーネルバージョン 5.10 以上)を公式にサポートしています。古いカーネル(4.14以上)とも互換性がありますが、自分でカーネルをビルドする必要があります。
|
||||||
@@ -23,11 +30,11 @@ WSA 、ChromeOS とコンテナ上で動作する Android でも KernelSU を統
|
|||||||
|
|
||||||
- [インストール方法はこちら](https://kernelsu.org/ja_JP/guide/installation.html)
|
- [インストール方法はこちら](https://kernelsu.org/ja_JP/guide/installation.html)
|
||||||
- [ビルド方法はこちら](https://kernelsu.org/guide/how-to-build.html)
|
- [ビルド方法はこちら](https://kernelsu.org/guide/how-to-build.html)
|
||||||
- [公式サイト](https://kernelsu.org)
|
- [公式サイト](https://kernelsu.org/ja_JP/)
|
||||||
|
|
||||||
## 翻訳
|
## 翻訳
|
||||||
|
|
||||||
KernelSU をあなたの言語に翻訳するか、既存の翻訳を改善するには、[Weblate](https://hosted.weblate.org/engage/kernelsu/) を使用してください。
|
KernelSU をあなたの言語に翻訳するか、既存の翻訳を改善するには、[Weblate](https://hosted.weblate.org/engage/kernelsu/) を使用してください。Manager翻訳した PR は、Weblate と競合するため受け入れられなくなりました。
|
||||||
|
|
||||||
## ディスカッション
|
## ディスカッション
|
||||||
|
|
||||||
@@ -35,13 +42,12 @@ KernelSU をあなたの言語に翻訳するか、既存の翻訳を改善す
|
|||||||
|
|
||||||
## ライセンス
|
## ライセンス
|
||||||
|
|
||||||
- `kernel` ディレクトリの下にあるすべてのファイル: [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- `kernel` ディレクトリの下にあるすべてのファイル: [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
|
||||||
- `kernel` ディレクトリ以外のすべてのファイル: [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- `kernel` ディレクトリ以外のすべてのファイル: [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。
|
||||||
|
|
||||||
## クレジット
|
## クレジット
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU のアイデア元
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU のアイデア元。
|
||||||
- [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 のスキル。
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | **Polski** | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | **Polski** | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Rozwiązanie root oparte na jądrze dla urządzeń z systemem Android.
|
Rozwiązanie root oparte na jądrze dla urządzeń z systemem Android.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Cechy
|
## Cechy
|
||||||
|
|
||||||
1. Oparte na jądrze `su` i zarządzanie dostępem roota.
|
1. Oparte na jądrze `su` i zarządzanie dostępem roota.
|
||||||
2. System modułów oparty na overlayfs.
|
2. System modułów oparty na [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
|
|
||||||
## Kompatybilność
|
## Kompatybilność
|
||||||
|
|
||||||
@@ -19,24 +27,29 @@ Aktualnie obsługiwane ABI to : `arm64-v8a` i `x86_64`.
|
|||||||
|
|
||||||
## Użycie
|
## Użycie
|
||||||
|
|
||||||
[Instalacja](https://kernelsu.org/guide/installation.html)
|
- [Instalacja](https://kernelsu.org/guide/installation.html)
|
||||||
|
- [Jak skompilować?](https://kernelsu.org/guide/how-to-build.html)
|
||||||
|
|
||||||
## Kompilacja
|
## Tłumaczenie
|
||||||
|
|
||||||
[Jak skompilować?](https://kernelsu.org/guide/how-to-build.html)
|
Aby pomóc w tłumaczeniu KernelSU lub ulepszyć istniejące tłumaczenia, użyj [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR tłumaczenia Managera nie jest już akceptowany, ponieważ będzie kolidował z Weblate.
|
||||||
|
|
||||||
## Dyskusja
|
## Dyskusja
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
|
## Bezpieczeństwo
|
||||||
|
|
||||||
|
Informacje na temat zgłaszania luk w zabezpieczeniach w KernelSU można znaleźć w pliku [SECURITY.md](/SECURITY.md).
|
||||||
|
|
||||||
## Licencja
|
## Licencja
|
||||||
|
|
||||||
- Pliki w katalogu `kernel` są na licencji [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- Pliki w katalogu `kernel` są na licencji [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- Wszystkie inne części poza katalogiem `kernel` są na licencji [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- Wszystkie inne części poza katalogiem `kernel` są na licencji [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## Podziękowania
|
## Podziękowania
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): pomysłodawca KernelSU.
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): pomysłodawca KernelSU.
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): implementacja sepolicy.
|
||||||
- [genuine](https://github.com/brevent/genuine/): walidacja podpisu apk v2.
|
- [genuine](https://github.com/brevent/genuine/): walidacja podpisu apk v2.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): cenna znajomość rootkitów.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): cenna znajomość rootkitów.
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): implementacja sepolicy.
|
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | **Português (Brasil)** | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | **Português (Brasil)** | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Uma solução root baseada em kernel para dispositivos Android.
|
Uma solução root baseada em kernel para dispositivos Android.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Características
|
## Características
|
||||||
|
|
||||||
1. `su` e gerenciamento de acesso root baseado em kernel.
|
1. `su` e gerenciamento de acesso root baseado em kernel.
|
||||||
|
2. Sistema modular baseado em [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
2. Sistema modular baseado em overlayfs.
|
|
||||||
|
|
||||||
3. [Perfil do Aplicativo](https://kernelsu.org/pt_BR/guide/app-profile.html): Tranque o poder root em uma gaiola.
|
3. [Perfil do Aplicativo](https://kernelsu.org/pt_BR/guide/app-profile.html): Tranque o poder root em uma gaiola.
|
||||||
|
|
||||||
## Estado de Compatibilidade
|
## Estado de compatibilidade
|
||||||
|
|
||||||
O KernelSU oferece suporte oficial a dispositivos Android GKI 2.0 (kernel 5.10+). Kernels mais antigos (4.14+) também são compatíveis, mas o kernel terá que ser construído manualmente.
|
O KernelSU oferece suporte oficial a dispositivos Android GKI 2.0 (kernel 5.10+). Kernels mais antigos (4.14+) também são compatíveis, mas o kernel terá que ser construído manualmente.
|
||||||
|
|
||||||
@@ -21,22 +27,27 @@ Com isso, WSA, ChromeOS e Android baseado em contêiner são todos suportados.
|
|||||||
Atualmente, apenas `arm64-v8a` e `x86_64` são suportados.
|
Atualmente, apenas `arm64-v8a` e `x86_64` são suportados.
|
||||||
|
|
||||||
## Uso
|
## Uso
|
||||||
|
|
||||||
- [Instalação](https://kernelsu.org/pt_BR/guide/installation.html)
|
- [Instalação](https://kernelsu.org/pt_BR/guide/installation.html)
|
||||||
- [Como construir o KernelSU?](https://kernelsu.org/pt_BR/guide/how-to-build.html)
|
- [Como construir o KernelSU?](https://kernelsu.org/pt_BR/guide/how-to-build.html)
|
||||||
- [Site oficial](https://kernelsu.org/pt_BR/)
|
- [Site oficial](https://kernelsu.org/pt_BR/)
|
||||||
|
|
||||||
## Tradução
|
## Tradução
|
||||||
Para ajudar a traduzir o KernelSU ou melhorar as traduções existentes, use o [Weblate](https://hosted.weblate.org/engage/kernelsu/), por favor.
|
|
||||||
|
Para contribuir com a tradução do KernelSU ou aprimorar traduções existentes, por favor, utilize o [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR para a tradução do Gerenciador não são mais aceitas, pois podem entrar em conflito com o Weblate.
|
||||||
|
|
||||||
## Discussão
|
## Discussão
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
|
## Segurança
|
||||||
|
|
||||||
|
Para obter informações sobre como relatar vulnerabilidades de segurança do KernelSU, consulte [SECURITY.md](/SECURITY.md).
|
||||||
|
|
||||||
## Licença
|
## Licença
|
||||||
|
|
||||||
- Os arquivos no diretório `kernel` são [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- Os arquivos no diretório `kernel` são [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
|
- Todas as outras partes, exceto o diretório `kernel` são [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
- Todas as outras partes, exceto o diretório `kernel` são [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
|
||||||
|
|
||||||
## Créditos
|
## Créditos
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | **Русский** | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | **Русский** | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Решение на основе ядра root для Android-устройств.
|
Решение на основе ядра root для Android-устройств.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Особенности
|
## Особенности
|
||||||
|
|
||||||
1. Управление `su` и root-доступом на основе ядра.
|
1. Управление `su` и root-доступом на основе ядра.
|
||||||
2. Система модулей на основе overlayfs.
|
2. Система модулей на основе [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
|
3. [Профиль приложений](https://kernelsu.org/ru_RU/guide/app-profile.html): Запри корневую силу в клетке.
|
||||||
|
|
||||||
## Совместимость
|
## Совместимость
|
||||||
|
|
||||||
@@ -19,11 +28,9 @@ WSA и Android на основе контейнеров также должны
|
|||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
|
|
||||||
[Установка](https://kernelsu.org/ru_RU/guide/installation.html)
|
- [Установка](https://kernelsu.org/ru_RU/guide/installation.html)
|
||||||
|
- [Как собрать?](https://kernelsu.org/ru_RU/guide/how-to-build.html)
|
||||||
## Сборка
|
- [официальный сайт](https://kernelsu.org/ru_RU/)
|
||||||
|
|
||||||
[Как собрать?](https://kernelsu.org/ru_RU/guide/how-to-build.html)
|
|
||||||
|
|
||||||
## Обсуждение
|
## Обсуждение
|
||||||
|
|
||||||
@@ -31,12 +38,12 @@ WSA и Android на основе контейнеров также должны
|
|||||||
|
|
||||||
## Лицензия
|
## Лицензия
|
||||||
|
|
||||||
- Файлы в директории `kernel` - [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- Файлы в директории `kernel` [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- Все остальные части, кроме директории `kernel` - [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- Все остальные части, кроме директории `kernel` [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## Благодарности
|
## Благодарности
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): идея KernelSU.
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): идея KernelSU.
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk): реализация sepolicy.
|
||||||
- [genuine](https://github.com/brevent/genuine/): проверка подписи apk v2.
|
- [genuine](https://github.com/brevent/genuine/): проверка подписи apk v2.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): некоторые навыки руткита.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): некоторые навыки руткита.
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): реализация sepolicy.
|
|
||||||
|
|||||||
@@ -1,45 +1,57 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | **Türkçe** | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | **Türkçe** | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
Android cihazlar için kernel tabanlı bir root çözümü.
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
|
Android cihazlar için kernel tabanlı root çözümü.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Özellikler
|
## Özellikler
|
||||||
|
|
||||||
1. Kernel-tabanlı `su` ve root erişimi yönetimi.
|
1. Kernel-tabanlı `su` ve root erişimi yönetimi.
|
||||||
2. Overlayfs'ye dayalı modül sistemi.
|
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS)'ye dayalı modül sistemi.
|
||||||
3. [Uygulama profili](https://kernelsu.org/guide/app-profile.html): Root gücünü bir kafese kapatın.
|
3. [Uygulama profili](https://kernelsu.org/guide/app-profile.html): Root gücünü bir kafese kapatın.
|
||||||
|
|
||||||
## Uyumluluk Durumu
|
## Uyumluluk Durumu
|
||||||
|
|
||||||
KernelSU resmi olarak Android GKI 2.0 cihazlarını ( 5.10+ kernelli) destekler, eski kernellerle de (4.14+) uyumludur, ancak kerneli kendinizin inşaa etmesi gerekir.
|
KernelSU resmi olarak Android GKI 2.0 cihazlarını (5.10+ kernelli) destekler, eski kernellerle de (4.14+) uyumludur, ancak kerneli kendinizin derlemeniz gerekir.
|
||||||
|
|
||||||
WSA ve konteyner tabanlı Android'in de, KernelSU ile entegre olarak da çalışması gerekmektedir.
|
Bununla birlikte; WSA, ChromeOS ve konteyner tabanlı Android'in tamamı desteklenmektedir.
|
||||||
|
|
||||||
Ve desteklenen mevcut ABI'ler : `arm64-v8a` ve `x86_64`
|
Şimdilik sadece `arm64-v8a` ve `x86_64` desteklenmektedir.
|
||||||
|
|
||||||
## Kullanım
|
## Kullanım
|
||||||
|
|
||||||
- [Yükleme](https://kernelsu.org/guide/installation.html)
|
- [Yükleme yönergeleri](https://kernelsu.org/guide/installation.html)
|
||||||
- [Nasıl inşa edilir?](https://kernelsu.org/guide/how-to-build.html)
|
- [Nasıl derlenir?](https://kernelsu.org/guide/how-to-build.html)
|
||||||
- [Resmi WEB sitesi](https://kernelsu.org/)
|
- [Resmi WEB sitesi](https://kernelsu.org/)
|
||||||
|
|
||||||
## Çeviri
|
## Çeviri
|
||||||
|
|
||||||
KernelSU'yu kendi dilinize çevirmek veya varolan bir çeviriyi geliştirmek istiyorsanız, lütfen [Weblate](https://hosted.weblate.org/engage/kernelsu/)'i kullanın.
|
KernelSU'nun çevirisine veya mevcut çevirilerin iyileştirilmesine yardımcı olmak için lütfen [Weblate](https://hosted.weblate.org/engage/kernelsu/) kullanın. Yönetici uygulamasının PR ile çevirisi, Weblate ile çakışacağından artık kabul edilmeyecektir.
|
||||||
|
|
||||||
## Tartışma
|
## Tartışma
|
||||||
|
|
||||||
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
- Telegram: [@KernelSU](https://t.me/KernelSU)
|
||||||
|
|
||||||
|
## Güvenlik
|
||||||
|
|
||||||
|
KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için, bkz [SECURITY.md](/SECURITY.md).
|
||||||
|
|
||||||
## Lisans
|
## Lisans
|
||||||
|
|
||||||
- `kernel` klasöründeki dosyalar [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır.
|
- `kernel` klasöründeki dosyalar [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır.
|
||||||
- `kernel` klasörü dışındaki bütün diğer bölümler [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır.
|
- `kernel` klasörü dışındaki bütün diğer bölümler [GPL-3-veya-sonraki](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır.
|
||||||
|
|
||||||
## Krediler
|
## Krediler
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri.
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri.
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): güçlü root aracı.
|
- [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ğrulaması.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): bazı rootkit becerileri.
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): bazı rootkit becerileri.
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | **繁體中文** | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | **繁體中文** | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
一個基於核心的 Android 裝置 Root 解決方案
|
一個基於核心的 Android 裝置 Root 解決方案
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
- 基於核心的 Su 和 Root 存取權管理。
|
- 基於核心的 `su` 和 Root 存取權管理。
|
||||||
- 基於 Overlayfs 的模組系統。
|
- 基於 [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模組系統。
|
||||||
|
|
||||||
## 相容性狀態
|
## 相容性狀態
|
||||||
|
|
||||||
@@ -15,15 +23,12 @@ KernelSU 官方支援 Android GKI 2.0 的裝置 (核心版本 5.10+);舊版核
|
|||||||
|
|
||||||
WSA 和執行在容器中的 Android 也可以與 KernelSU 一同運作。
|
WSA 和執行在容器中的 Android 也可以與 KernelSU 一同運作。
|
||||||
|
|
||||||
目前支援架構:`arm64-v8a` 和 `x86_64`
|
目前支援架構:`arm64-v8a` 和 `x86_64`。
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
[安裝教學](https://kernelsu.org/zh_TW/guide/installation.html)
|
- [安裝教學](https://kernelsu.org/zh_TW/guide/installation.html)
|
||||||
|
- [如何建置?](https://kernelsu.org/zh_TW/guide/how-to-build.html)
|
||||||
## 建置
|
|
||||||
|
|
||||||
[如何建置?](https://kernelsu.org/zh_TW/guide/how-to-build.html)
|
|
||||||
|
|
||||||
### 討論
|
### 討論
|
||||||
|
|
||||||
@@ -31,12 +36,12 @@ WSA 和執行在容器中的 Android 也可以與 KernelSU 一同運作。
|
|||||||
|
|
||||||
## 授權
|
## 授權
|
||||||
|
|
||||||
- 目錄 `kernel` 下所有檔案為 [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- 目錄 `kernel` 下所有檔案為 [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
|
||||||
- 除 `kernel` 目錄的其他部分均為 [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- 除 `kernel` 目錄的其他部分均為 [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。
|
||||||
|
|
||||||
## 致謝
|
## 致謝
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU 的靈感。
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU 的靈感。
|
||||||
|
- [Magisk](https://github.com/topjohnwu/Magisk):sepolicy 實作。
|
||||||
- [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 技巧。
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk):sepolicy 實作。
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Portuguese-Brazil](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | **Tiếng Việt** | [Indonesia](README_ID.md) | [עברית](README_iw.md) | [हिंदी](README_IN.md)
|
[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | **Tiếng Việt** | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md)
|
||||||
|
|
||||||
# KernelSU
|
# KernelSU
|
||||||
|
|
||||||
|
<img src="https://kernelsu.org/logo.png" style="width: 96px;" alt="logo">
|
||||||
|
|
||||||
Giải pháp root thông qua thay đổi trên Kernel hệ điều hành cho các thiết bị Android.
|
Giải pháp root thông qua thay đổi trên Kernel hệ điều hành cho các thiết bị Android.
|
||||||
|
|
||||||
|
[](https://github.com/tiann/KernelSU/releases/latest)
|
||||||
|
[](https://hosted.weblate.org/engage/kernelsu)
|
||||||
|
[](https://t.me/KernelSU)
|
||||||
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](/LICENSE)
|
||||||
|
|
||||||
## Tính năng
|
## Tính năng
|
||||||
|
|
||||||
1. Hỗ trợ gói thực thi `su` và quản lý quyền root.
|
1. Hỗ trợ gói thực thi `su` và quản lý quyền root.
|
||||||
2. Hệ thống mô-đun thông qua overlayfs.
|
2. Hệ thống mô-đun thông qua [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
|
||||||
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Hạn chế quyền root của ứng dụng.
|
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Hạn chế quyền root của ứng dụng.
|
||||||
|
|
||||||
## Tình trạng tương thích
|
## Tình trạng tương thích
|
||||||
@@ -16,7 +24,7 @@ KernelSU chính thức hỗ trợ các thiết bị Android với kernel GKI 2.0
|
|||||||
|
|
||||||
WSA, ChromeOS và Android dựa trên container(container-based) cũng được hỗ trợ bởi KernelSU.
|
WSA, ChromeOS và Android dựa trên container(container-based) cũng được hỗ trợ bởi KernelSU.
|
||||||
|
|
||||||
Hiên tại Giao diện nhị phân của ứng dụng (ABI) được hỗ trợ bao gồm `arm64-v8a` và `x86_64`
|
Hiên tại Giao diện nhị phân của ứng dụng (ABI) được hỗ trợ bao gồm `arm64-v8a` và `x86_64`.
|
||||||
|
|
||||||
## Sử dụng
|
## Sử dụng
|
||||||
|
|
||||||
@@ -34,12 +42,12 @@ Nếu bạn muốn hỗ trợ dịch KernelSU sang một ngôn ngữ khác hoặ
|
|||||||
|
|
||||||
## Giấy phép
|
## Giấy phép
|
||||||
|
|
||||||
- Tất cả các file trong thư mục `kernel` dùng giấy phép [GPL-2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
- Tất cả các file trong thư mục `kernel` dùng giấy phép [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||||
- Tất cả các thành phần khác ngoại trừ thư mục `kernel` dùng giấy phép [GPL-3](https://www.gnu.org/licenses/gpl-3.0.html)
|
- Tất cả các thành phần khác ngoại trừ thư mục `kernel` dùng giấy phép [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||||
|
|
||||||
## Lời cảm ơn
|
## Lời cảm ơn
|
||||||
|
|
||||||
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ý tưởng cho KernelSU.
|
- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ý tưởng cho KernelSU.
|
||||||
- [Magisk](https://github.com/topjohnwu/Magisk): công cụ root mạnh mẽ.
|
- [Magisk](https://github.com/topjohnwu/Magisk): công cụ root mạnh mẽ.
|
||||||
- [genuine](https://github.com/brevent/genuine/): phương pháp xác thực apk v2.
|
- [genuine](https://github.com/brevent/genuine/): phương pháp xác thực apk v2.
|
||||||
- [Diamorphine](https://github.com/m0nad/Diamorphine): các phương pháp ẩn của rootkit .
|
- [Diamorphine](https://github.com/m0nad/Diamorphine): các phương pháp ẩn của rootkit.
|
||||||
|
|||||||
111
js/README.md
Normal file
111
js/README.md
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Library for KernelSU's module WebUI
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add kernelsu
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### exec
|
||||||
|
|
||||||
|
Spawns a **root** shell and runs a command within that shell, passing the `stdout` and `stderr` to a Promise when complete.
|
||||||
|
|
||||||
|
- `command` `<string>` The command to run, with space-separated arguments.
|
||||||
|
- `options` `<Object>`
|
||||||
|
- `cwd` - Current working directory of the child process
|
||||||
|
- `env` - Environment key-value pairs
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { exec } from 'kernelsu';
|
||||||
|
|
||||||
|
const { errno, stdout, stderr } = await exec('ls -l', { cwd: '/tmp' });
|
||||||
|
if (errno === 0) {
|
||||||
|
// success
|
||||||
|
console.log(stdout);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### spawn
|
||||||
|
|
||||||
|
Spawns a new process using the given `command` in **root** shell, with command-line arguments in `args`. If omitted, `args` defaults to an empty array.
|
||||||
|
|
||||||
|
Returns a `ChildProcess`, Instances of the ChildProcess represent spawned child processes.
|
||||||
|
|
||||||
|
- `command` `<string>` The command to run.
|
||||||
|
- `args` `<string[]>` List of string arguments.
|
||||||
|
- `options` `<Object>`:
|
||||||
|
- `cwd` `<string>` - Current working directory of the child process
|
||||||
|
- `env` `<Object>` - Environment key-value pairs
|
||||||
|
|
||||||
|
Example of running `ls -lh /data`, capturing `stdout`, `stderr`, and the exit code:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { spawn } from 'kernelsu';
|
||||||
|
|
||||||
|
const ls = spawn('ls', ['-lh', '/data']);
|
||||||
|
|
||||||
|
ls.stdout.on('data', (data) => {
|
||||||
|
console.log(`stdout: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
ls.stderr.on('data', (data) => {
|
||||||
|
console.log(`stderr: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
ls.on('exit', (code) => {
|
||||||
|
console.log(`child process exited with code ${code}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ChildProcess
|
||||||
|
|
||||||
|
##### Event 'exit'
|
||||||
|
|
||||||
|
- `code` `<number>` The exit code if the child exited on its own.
|
||||||
|
|
||||||
|
The `'exit'` event is emitted after the child process ends. If the process exited, `code` is the final exit code of the process, otherwise null
|
||||||
|
|
||||||
|
##### Event 'error'
|
||||||
|
|
||||||
|
- `err` `<Error>` The error.
|
||||||
|
|
||||||
|
The `'error'` event is emitted whenever:
|
||||||
|
|
||||||
|
- The process could not be spawned.
|
||||||
|
- The process could not be killed.
|
||||||
|
|
||||||
|
##### `stdout`
|
||||||
|
|
||||||
|
A `Readable Stream` that represents the child process's `stdout`.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const subprocess = spawn('ls');
|
||||||
|
|
||||||
|
subprocess.stdout.on('data', (data) => {
|
||||||
|
console.log(`Received chunk ${data}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `stderr`
|
||||||
|
|
||||||
|
A `Readable Stream` that represents the child process's `stderr`.
|
||||||
|
|
||||||
|
### fullScreen
|
||||||
|
|
||||||
|
Request the WebView enter/exit full screen.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { fullScreen } from 'kernelsu';
|
||||||
|
fullScreen(true);
|
||||||
|
```
|
||||||
|
|
||||||
|
### toast
|
||||||
|
|
||||||
|
Show a toast message.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { toast } from 'kernelsu';
|
||||||
|
toast('Hello, world!');
|
||||||
|
```
|
||||||
115
js/index.js
Normal file
115
js/index.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
let callbackCounter = 0;
|
||||||
|
function getUniqueCallbackName(prefix) {
|
||||||
|
return `${prefix}_callback_${Date.now()}_${callbackCounter++}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exec(command, options) {
|
||||||
|
if (typeof options === "undefined") {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Generate a unique callback function name
|
||||||
|
const callbackFuncName = getUniqueCallbackName("exec");
|
||||||
|
|
||||||
|
// Define the success callback function
|
||||||
|
window[callbackFuncName] = (errno, stdout, stderr) => {
|
||||||
|
resolve({ errno, stdout, stderr });
|
||||||
|
cleanup(callbackFuncName);
|
||||||
|
};
|
||||||
|
|
||||||
|
function cleanup(successName) {
|
||||||
|
delete window[successName];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ksu.exec(command, JSON.stringify(options), callbackFuncName);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
cleanup(callbackFuncName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stdio() {
|
||||||
|
this.listeners = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Stdio.prototype.on = function (event, listener) {
|
||||||
|
if (!this.listeners[event]) {
|
||||||
|
this.listeners[event] = [];
|
||||||
|
}
|
||||||
|
this.listeners[event].push(listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
Stdio.prototype.emit = function (event, ...args) {
|
||||||
|
if (this.listeners[event]) {
|
||||||
|
this.listeners[event].forEach((listener) => listener(...args));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function ChildProcess() {
|
||||||
|
this.listeners = {};
|
||||||
|
this.stdin = new Stdio();
|
||||||
|
this.stdout = new Stdio();
|
||||||
|
this.stderr = new Stdio();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChildProcess.prototype.on = function (event, listener) {
|
||||||
|
if (!this.listeners[event]) {
|
||||||
|
this.listeners[event] = [];
|
||||||
|
}
|
||||||
|
this.listeners[event].push(listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
ChildProcess.prototype.emit = function (event, ...args) {
|
||||||
|
if (this.listeners[event]) {
|
||||||
|
this.listeners[event].forEach((listener) => listener(...args));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function spawn(command, args, options) {
|
||||||
|
if (typeof args === "undefined") {
|
||||||
|
args = [];
|
||||||
|
} else if (typeof args === "object") {
|
||||||
|
// allow for (command, options) signature
|
||||||
|
options = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options === "undefined") {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const child = new ChildProcess();
|
||||||
|
const childCallbackName = getUniqueCallbackName("spawn");
|
||||||
|
window[childCallbackName] = child;
|
||||||
|
|
||||||
|
function cleanup(name) {
|
||||||
|
delete window[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
child.on("exit", code => {
|
||||||
|
cleanup(childCallbackName);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
ksu.spawn(
|
||||||
|
command,
|
||||||
|
JSON.stringify(args),
|
||||||
|
JSON.stringify(options),
|
||||||
|
childCallbackName
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
child.emit("error", error);
|
||||||
|
cleanup(childCallbackName);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fullScreen(isFullScreen) {
|
||||||
|
ksu.fullScreen(isFullScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toast(message) {
|
||||||
|
ksu.toast(message);
|
||||||
|
}
|
||||||
25
js/package.json
Normal file
25
js/package.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "kernelsu",
|
||||||
|
"version": "1.0.6",
|
||||||
|
"description": "Library for KernelSU's module WebUI",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm run test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/tiann/KernelSU.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"su",
|
||||||
|
"kernelsu",
|
||||||
|
"module",
|
||||||
|
"webui"
|
||||||
|
],
|
||||||
|
"author": "weishu",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/tiann/KernelSU/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/tiann/KernelSU#readme"
|
||||||
|
}
|
||||||
10
justfile
Normal file
10
justfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
alias bk := build_ksud
|
||||||
|
alias bm := build_manager
|
||||||
|
|
||||||
|
build_ksud:
|
||||||
|
cross build --target aarch64-linux-android --release --manifest-path ./userspace/ksud/Cargo.toml
|
||||||
|
|
||||||
|
build_manager: build_ksud
|
||||||
|
cp userspace/ksud/target/aarch64-linux-android/release/ksud manager/app/src/main/jniLibs/arm64-v8a/libksud.so
|
||||||
|
cd manager && ./gradlew aDebug
|
||||||
|
|
||||||
@@ -32,6 +32,11 @@ ifndef KSU_EXPECTED_HASH
|
|||||||
KSU_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6
|
KSU_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef KSU_MANAGER_PACKAGE
|
||||||
|
ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\"
|
||||||
|
$(info -- KernelSU Manager package name: $(KSU_MANAGER_PACKAGE))
|
||||||
|
endif
|
||||||
|
|
||||||
$(info -- KernelSU Manager signature size: $(KSU_EXPECTED_SIZE))
|
$(info -- KernelSU Manager signature size: $(KSU_EXPECTED_SIZE))
|
||||||
$(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
|
$(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
|
||||||
|
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ void do_save_allow_list(struct work_struct *work)
|
|||||||
loff_t off = 0;
|
loff_t off = 0;
|
||||||
|
|
||||||
struct file *fp =
|
struct file *fp =
|
||||||
ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT, 0644);
|
ksu_filp_open_compat(KERNEL_SU_ALLOWLIST, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp));
|
pr_err("save_allow_list create file failed: %ld\n", PTR_ERR(fp));
|
||||||
return;
|
return;
|
||||||
@@ -441,7 +441,7 @@ exit:
|
|||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data)
|
void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data)
|
||||||
{
|
{
|
||||||
struct perm_data *np = NULL;
|
struct perm_data *np = NULL;
|
||||||
struct perm_data *n = NULL;
|
struct perm_data *n = NULL;
|
||||||
@@ -451,13 +451,16 @@ void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data)
|
|||||||
mutex_lock(&allowlist_mutex);
|
mutex_lock(&allowlist_mutex);
|
||||||
list_for_each_entry_safe (np, n, &allow_list, list) {
|
list_for_each_entry_safe (np, n, &allow_list, list) {
|
||||||
uid_t uid = np->profile.current_uid;
|
uid_t uid = np->profile.current_uid;
|
||||||
|
char *package = np->profile.key;
|
||||||
// we use this uid for special cases, don't prune it!
|
// we use this uid for special cases, don't prune it!
|
||||||
bool is_preserved_uid = uid == KSU_APP_PROFILE_PRESERVE_UID;
|
bool is_preserved_uid = uid == KSU_APP_PROFILE_PRESERVE_UID;
|
||||||
if (!is_preserved_uid && !is_uid_exist(uid, data)) {
|
if (!is_preserved_uid && !is_uid_valid(uid, package, data)) {
|
||||||
modified = true;
|
modified = true;
|
||||||
pr_info("prune uid: %d\n", uid);
|
pr_info("prune uid: %d, package: %s\n", uid, package);
|
||||||
list_del(&np->list);
|
list_del(&np->list);
|
||||||
allow_list_bitmap[uid / BITS_PER_BYTE] &= ~(1 << (uid % BITS_PER_BYTE));
|
if (likely(uid <= BITMAP_UID_MAX)) {
|
||||||
|
allow_list_bitmap[uid / BITS_PER_BYTE] &= ~(1 << (uid % BITS_PER_BYTE));
|
||||||
|
}
|
||||||
remove_uid_from_arr(uid);
|
remove_uid_from_arr(uid);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
kfree(np);
|
kfree(np);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ bool __ksu_is_allow_uid(uid_t uid);
|
|||||||
|
|
||||||
bool ksu_get_allow_list(int *array, int *length, bool allow);
|
bool ksu_get_allow_list(int *array, int *length, bool allow);
|
||||||
|
|
||||||
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data);
|
void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, char *, void *), void *data);
|
||||||
|
|
||||||
bool ksu_get_app_profile(struct app_profile *);
|
bool ksu_get_app_profile(struct app_profile *);
|
||||||
bool ksu_set_app_profile(struct app_profile *, bool persist);
|
bool ksu_set_app_profile(struct app_profile *, bool persist);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static int calc_hash(struct crypto_shash *alg, const unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ksu_sha256(const unsigned char *data, unsigned int datalen,
|
static int ksu_sha256(const unsigned char *data, unsigned int datalen,
|
||||||
unsigned char *digest)
|
unsigned char *digest)
|
||||||
{
|
{
|
||||||
struct crypto_shash *alg;
|
struct crypto_shash *alg;
|
||||||
char *hash_alg_name = "sha256";
|
char *hash_alg_name = "sha256";
|
||||||
@@ -70,7 +70,7 @@ static int ksu_sha256(const unsigned char *data, unsigned int datalen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
||||||
unsigned expected_size, const char* expected_sha256)
|
unsigned expected_size, const char *expected_sha256)
|
||||||
{
|
{
|
||||||
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
|
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
|
||||||
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
|
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
|
||||||
@@ -90,7 +90,7 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
|||||||
if (*size4 == expected_size) {
|
if (*size4 == expected_size) {
|
||||||
*offset += *size4;
|
*offset += *size4;
|
||||||
|
|
||||||
#define CERT_MAX_LENGTH 1024
|
#define CERT_MAX_LENGTH 1024
|
||||||
char cert[CERT_MAX_LENGTH];
|
char cert[CERT_MAX_LENGTH];
|
||||||
if (*size4 > CERT_MAX_LENGTH) {
|
if (*size4 > CERT_MAX_LENGTH) {
|
||||||
pr_info("cert length overlimit\n");
|
pr_info("cert length overlimit\n");
|
||||||
@@ -107,7 +107,8 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
|||||||
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
|
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
|
||||||
|
|
||||||
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
|
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
|
||||||
pr_info("sha256: %s, expected: %s\n", hash_str, expected_sha256);
|
pr_info("sha256: %s, expected: %s\n", hash_str,
|
||||||
|
expected_sha256);
|
||||||
if (strcmp(expected_sha256, hash_str) == 0) {
|
if (strcmp(expected_sha256, hash_str) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -115,8 +116,62 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline bool
|
struct zip_entry_header {
|
||||||
check_v2_signature(char *path, unsigned expected_size, const char *expected_sha256)
|
uint32_t signature;
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t compression;
|
||||||
|
uint16_t mod_time;
|
||||||
|
uint16_t mod_date;
|
||||||
|
uint32_t crc32;
|
||||||
|
uint32_t compressed_size;
|
||||||
|
uint32_t uncompressed_size;
|
||||||
|
uint16_t file_name_length;
|
||||||
|
uint16_t extra_field_length;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
// This is a necessary but not sufficient condition, but it is enough for us
|
||||||
|
static bool has_v1_signature_file(struct file *fp)
|
||||||
|
{
|
||||||
|
struct zip_entry_header header;
|
||||||
|
const char MANIFEST[] = "META-INF/MANIFEST.MF";
|
||||||
|
|
||||||
|
loff_t pos = 0;
|
||||||
|
|
||||||
|
while (ksu_kernel_read_compat(fp, &header,
|
||||||
|
sizeof(struct zip_entry_header), &pos) ==
|
||||||
|
sizeof(struct zip_entry_header)) {
|
||||||
|
if (header.signature != 0x04034b50) {
|
||||||
|
// ZIP magic: 'PK'
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Read the entry file name
|
||||||
|
if (header.file_name_length == sizeof(MANIFEST) - 1) {
|
||||||
|
char fileName[sizeof(MANIFEST)];
|
||||||
|
ksu_kernel_read_compat(fp, fileName,
|
||||||
|
header.file_name_length, &pos);
|
||||||
|
fileName[header.file_name_length] = '\0';
|
||||||
|
|
||||||
|
// Check if the entry matches META-INF/MANIFEST.MF
|
||||||
|
if (strncmp(MANIFEST, fileName, sizeof(MANIFEST) - 1) ==
|
||||||
|
0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip the entry file name
|
||||||
|
pos += header.file_name_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip to the next entry
|
||||||
|
pos += header.extra_field_length + header.compressed_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline bool check_v2_signature(char *path,
|
||||||
|
unsigned expected_size,
|
||||||
|
const char *expected_sha256)
|
||||||
{
|
{
|
||||||
unsigned char buffer[0x11] = { 0 };
|
unsigned char buffer[0x11] = { 0 };
|
||||||
u32 size4;
|
u32 size4;
|
||||||
@@ -125,6 +180,7 @@ check_v2_signature(char *path, unsigned expected_size, const char *expected_sha2
|
|||||||
loff_t pos;
|
loff_t pos;
|
||||||
|
|
||||||
bool v2_signing_valid = false;
|
bool v2_signing_valid = false;
|
||||||
|
int v2_signing_blocks = 0;
|
||||||
bool v3_signing_exist = false;
|
bool v3_signing_exist = false;
|
||||||
bool v3_1_signing_exist = false;
|
bool v3_1_signing_exist = false;
|
||||||
|
|
||||||
@@ -185,8 +241,10 @@ check_v2_signature(char *path, unsigned expected_size, const char *expected_sha2
|
|||||||
offset = 4;
|
offset = 4;
|
||||||
pr_info("id: 0x%08x\n", id);
|
pr_info("id: 0x%08x\n", id);
|
||||||
if (id == 0x7109871au) {
|
if (id == 0x7109871au) {
|
||||||
v2_signing_valid = check_block(fp, &size4, &pos, &offset,
|
v2_signing_blocks++;
|
||||||
expected_size, expected_sha256);
|
v2_signing_valid =
|
||||||
|
check_block(fp, &size4, &pos, &offset,
|
||||||
|
expected_size, expected_sha256);
|
||||||
} else if (id == 0xf05368c0u) {
|
} else if (id == 0xf05368c0u) {
|
||||||
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73
|
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73
|
||||||
v3_signing_exist = true;
|
v3_signing_exist = true;
|
||||||
@@ -197,6 +255,20 @@ check_v2_signature(char *path, unsigned expected_size, const char *expected_sha2
|
|||||||
pos += (size8 - offset);
|
pos += (size8 - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v2_signing_blocks != 1) {
|
||||||
|
pr_err("Unexpected v2 signature count: %d\n",
|
||||||
|
v2_signing_blocks);
|
||||||
|
v2_signing_valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v2_signing_valid) {
|
||||||
|
int has_v1_signing = has_v1_signature_file(fp);
|
||||||
|
if (has_v1_signing) {
|
||||||
|
pr_err("Unexpected v1 signature scheme found!\n");
|
||||||
|
filp_close(fp, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
clean:
|
clean:
|
||||||
filp_close(fp, 0);
|
filp_close(fp, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
#include "uid_observer.h"
|
#include "uid_observer.h"
|
||||||
#include "kernel_compat.h"
|
#include "kernel_compat.h"
|
||||||
|
|
||||||
|
static bool ksu_module_mounted = false;
|
||||||
|
|
||||||
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
|
||||||
|
|
||||||
static inline bool is_allow_su()
|
static inline bool is_allow_su()
|
||||||
@@ -123,8 +125,12 @@ void escape_to_root(void)
|
|||||||
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
|
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
|
||||||
sizeof(kernel_cap_t));
|
sizeof(kernel_cap_t));
|
||||||
|
|
||||||
// capabilities
|
// setup capabilities
|
||||||
memcpy(&cred->cap_effective, &profile->capabilities.effective,
|
// we need CAP_DAC_READ_SEARCH becuase `/data/adb/ksud` is not accessible for non root process
|
||||||
|
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
|
||||||
|
u64 cap_for_ksud =
|
||||||
|
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
|
||||||
|
memcpy(&cred->cap_effective, &cap_for_ksud,
|
||||||
sizeof(cred->cap_effective));
|
sizeof(cred->cap_effective));
|
||||||
memcpy(&cred->cap_inheritable, &profile->capabilities.effective,
|
memcpy(&cred->cap_inheritable, &profile->capabilities.effective,
|
||||||
sizeof(cred->cap_inheritable));
|
sizeof(cred->cap_inheritable));
|
||||||
@@ -233,11 +239,12 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
// someone wants to be root manager, just check it!
|
// someone wants to be root manager, just check it!
|
||||||
// arg3 should be `/data/user/<userId>/<manager_package_name>`
|
// arg3 should be `/data/user/<userId>/<manager_package_name>`
|
||||||
char param[128];
|
char param[128];
|
||||||
if (ksu_strncpy_from_user_nofault(param, arg3, sizeof(param)) == -EFAULT) {
|
if (ksu_strncpy_from_user_nofault(param, arg3, sizeof(param)) ==
|
||||||
|
-EFAULT) {
|
||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
pr_err("become_manager: copy param err\n");
|
pr_err("become_manager: copy param err\n");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
goto block;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for user 0, it is /data/data
|
// for user 0, it is /data/data
|
||||||
@@ -255,7 +262,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
|
|
||||||
if (startswith(param, (char *)prefix) != 0) {
|
if (startswith(param, (char *)prefix) != 0) {
|
||||||
pr_info("become_manager: invalid param: %s\n", param);
|
pr_info("become_manager: invalid param: %s\n", param);
|
||||||
return 0;
|
goto block;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stat the param, app must have permission to do this
|
// stat the param, app must have permission to do this
|
||||||
@@ -263,12 +270,13 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
struct path path;
|
struct path path;
|
||||||
if (kern_path(param, LOOKUP_DIRECTORY, &path)) {
|
if (kern_path(param, LOOKUP_DIRECTORY, &path)) {
|
||||||
pr_err("become_manager: kern_path err\n");
|
pr_err("become_manager: kern_path err\n");
|
||||||
return 0;
|
goto block;
|
||||||
}
|
}
|
||||||
if (path.dentry->d_inode->i_uid.val != current_uid().val) {
|
uid_t inode_uid = path.dentry->d_inode->i_uid.val;
|
||||||
|
path_put(&path);
|
||||||
|
if (inode_uid != current_uid().val) {
|
||||||
pr_err("become_manager: path uid != current uid\n");
|
pr_err("become_manager: path uid != current uid\n");
|
||||||
path_put(&path);
|
goto block;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
char *pkg = param + strlen(prefix);
|
char *pkg = param + strlen(prefix);
|
||||||
pr_info("become_manager: param pkg: %s\n", pkg);
|
pr_info("become_manager: param pkg: %s\n", pkg);
|
||||||
@@ -278,14 +286,16 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("become_manager: prctl reply error\n");
|
pr_err("become_manager: prctl reply error\n");
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
path_put(&path);
|
block:
|
||||||
|
last_failed_uid = current_uid().val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg2 == CMD_GRANT_ROOT) {
|
if (arg2 == CMD_GRANT_ROOT) {
|
||||||
if (is_allow_su()) {
|
if (is_allow_su()) {
|
||||||
pr_info("allow root for: %d\n", current_uid());
|
pr_info("allow root for: %d\n", current_uid().val);
|
||||||
escape_to_root();
|
escape_to_root();
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("grant_root: prctl reply error\n");
|
pr_err("grant_root: prctl reply error\n");
|
||||||
@@ -299,7 +309,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
if (is_manager() || 0 == current_uid().val) {
|
if (is_manager() || 0 == current_uid().val) {
|
||||||
u32 version = KERNEL_SU_VERSION;
|
u32 version = KERNEL_SU_VERSION;
|
||||||
if (copy_to_user(arg3, &version, sizeof(version))) {
|
if (copy_to_user(arg3, &version, sizeof(version))) {
|
||||||
pr_err("prctl reply error, cmd: %d\n", arg2);
|
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -327,6 +337,11 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVENT_MODULE_MOUNTED: {
|
||||||
|
ksu_module_mounted = true;
|
||||||
|
pr_info("module mounted!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -373,7 +388,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
sizeof(u32) * array_length)) {
|
sizeof(u32) * array_length)) {
|
||||||
if (copy_to_user(result, &reply_ok,
|
if (copy_to_user(result, &reply_ok,
|
||||||
sizeof(reply_ok))) {
|
sizeof(reply_ok))) {
|
||||||
pr_err("prctl reply error, cmd: %d\n",
|
pr_err("prctl reply error, cmd: %lu\n",
|
||||||
arg2);
|
arg2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -393,16 +408,16 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
} else if (arg2 == CMD_UID_SHOULD_UMOUNT) {
|
} else if (arg2 == CMD_UID_SHOULD_UMOUNT) {
|
||||||
allow = ksu_uid_should_umount(target_uid);
|
allow = ksu_uid_should_umount(target_uid);
|
||||||
} else {
|
} else {
|
||||||
pr_err("unknown cmd: %d\n", arg2);
|
pr_err("unknown cmd: %lu\n", arg2);
|
||||||
}
|
}
|
||||||
if (!copy_to_user(arg4, &allow, sizeof(allow))) {
|
if (!copy_to_user(arg4, &allow, sizeof(allow))) {
|
||||||
if (copy_to_user(result, &reply_ok,
|
if (copy_to_user(result, &reply_ok,
|
||||||
sizeof(reply_ok))) {
|
sizeof(reply_ok))) {
|
||||||
pr_err("prctl reply error, cmd: %d\n",
|
pr_err("prctl reply error, cmd: %lu\n",
|
||||||
arg2);
|
arg2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_err("prctl copy err, cmd: %d\n", arg2);
|
pr_err("prctl copy err, cmd: %lu\n", arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -429,7 +444,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("prctl reply error, cmd: %d\n", arg2);
|
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -445,7 +460,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
// todo: validate the params
|
// todo: validate the params
|
||||||
if (ksu_set_app_profile(&profile, true)) {
|
if (ksu_set_app_profile(&profile, true)) {
|
||||||
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
|
||||||
pr_err("prctl reply error, cmd: %d\n", arg2);
|
pr_err("prctl reply error, cmd: %lu\n", arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -483,7 +498,8 @@ static bool should_umount(struct path *path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ksu_umount_mnt(struct path *path, int flags) {
|
static void ksu_umount_mnt(struct path *path, int flags)
|
||||||
|
{
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||||
int err = path_umount(path, flags);
|
int err = path_umount(path, flags);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -502,6 +518,11 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path.dentry != path.mnt->mnt_root) {
|
||||||
|
// it is not root mountpoint, maybe umounted by others already.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// we are only interest in some specific mounts
|
// we are only interest in some specific mounts
|
||||||
if (check_mnt && !should_umount(&path)) {
|
if (check_mnt && !should_umount(&path)) {
|
||||||
return;
|
return;
|
||||||
@@ -512,6 +533,11 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
|||||||
|
|
||||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||||
{
|
{
|
||||||
|
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
|
||||||
|
if (!ksu_module_mounted) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!new || !old) {
|
if (!new || !old) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -524,8 +550,6 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: check old process's selinux context, if it is not zygote, ignore it!
|
|
||||||
|
|
||||||
if (!is_appuid(new_uid) || is_isolated_uid(new_uid.val)) {
|
if (!is_appuid(new_uid) || is_isolated_uid(new_uid.val)) {
|
||||||
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
|
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -544,8 +568,18 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check old process's selinux context, if it is not zygote, ignore it!
|
||||||
|
// because some su apps may setuid to untrusted_app but they are in global mount namespace
|
||||||
|
// when we umount for such process, that is a disaster!
|
||||||
|
bool is_zygote_child = is_zygote(old->security);
|
||||||
|
if (!is_zygote_child) {
|
||||||
|
pr_info("handle umount ignore non zygote child: %d\n",
|
||||||
|
current->pid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
// umount the target mnt
|
// umount the target mnt
|
||||||
pr_info("handle umount for uid: %d\n", new_uid.val);
|
pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val,
|
||||||
|
current->pid);
|
||||||
|
|
||||||
// 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`
|
||||||
@@ -554,6 +588,10 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
|||||||
try_umount("/product", true, 0);
|
try_umount("/product", true, 0);
|
||||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||||
|
|
||||||
|
// try umount ksu temp path
|
||||||
|
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||||
|
try_umount("/sbin", false, MNT_DETACH);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#define EVENT_POST_FS_DATA 1
|
#define EVENT_POST_FS_DATA 1
|
||||||
#define EVENT_BOOT_COMPLETED 2
|
#define EVENT_BOOT_COMPLETED 2
|
||||||
|
#define EVENT_MODULE_MOUNTED 3
|
||||||
|
|
||||||
#define KSU_APP_PROFILE_VER 2
|
#define KSU_APP_PROFILE_VER 2
|
||||||
#define KSU_MAX_PACKAGE_NAME 256
|
#define KSU_MAX_PACKAGE_NAME 256
|
||||||
|
|||||||
@@ -138,9 +138,9 @@ static int __maybe_unused count(struct user_arg_ptr argv, int max)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the call from execve_handler_pre won't provided correct value for __never_use_argument, use them after fix execve_handler_pre, keeping them for consistence for manually patched code
|
// IMPORTANT NOTE: the call from execve_handler_pre WON'T provided correct value for envp and flags in GKI version
|
||||||
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||||
struct user_arg_ptr *argv, struct user_arg_ptr *envp, int *__never_use_flags)
|
struct user_arg_ptr *argv, struct user_arg_ptr *envp, int *flags)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_KPROBES
|
#ifndef CONFIG_KPROBES
|
||||||
if (!ksu_execveat_hook) {
|
if (!ksu_execveat_hook) {
|
||||||
@@ -167,7 +167,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!memcmp(filename->name, system_bin_init,
|
if (unlikely(!memcmp(filename->name, system_bin_init,
|
||||||
sizeof(system_bin_init) - 1))) {
|
sizeof(system_bin_init) - 1) && argv)) {
|
||||||
// /system/bin/init executed
|
// /system/bin/init executed
|
||||||
int argc = count(*argv, MAX_ARG_STRINGS);
|
int argc = count(*argv, MAX_ARG_STRINGS);
|
||||||
pr_info("/system/bin/init argc: %d\n", argc);
|
pr_info("/system/bin/init argc: %d\n", argc);
|
||||||
@@ -188,7 +188,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (unlikely(!memcmp(filename->name, old_system_init,
|
} else if (unlikely(!memcmp(filename->name, old_system_init,
|
||||||
sizeof(old_system_init) - 1))) {
|
sizeof(old_system_init) - 1) && argv)) {
|
||||||
// /init executed
|
// /init executed
|
||||||
int argc = count(*argv, MAX_ARG_STRINGS);
|
int argc = count(*argv, MAX_ARG_STRINGS);
|
||||||
pr_info("/init argc: %d\n", argc);
|
pr_info("/init argc: %d\n", argc);
|
||||||
@@ -208,7 +208,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
} else {
|
} else {
|
||||||
pr_err("/init parse args err!\n");
|
pr_err("/init parse args err!\n");
|
||||||
}
|
}
|
||||||
} else if (argc == 1 && !init_second_stage_executed) {
|
} else if (argc == 1 && !init_second_stage_executed && envp) {
|
||||||
/* This applies to versions between Android 8 ~ 9 */
|
/* This applies to versions between Android 8 ~ 9 */
|
||||||
int envc = count(*envp, MAX_ARG_STRINGS);
|
int envc = count(*envp, MAX_ARG_STRINGS);
|
||||||
if (envc > 0) {
|
if (envc > 0) {
|
||||||
@@ -340,17 +340,17 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
|
|||||||
|
|
||||||
size_t rc_count = strlen(KERNEL_SU_RC);
|
size_t rc_count = strlen(KERNEL_SU_RC);
|
||||||
|
|
||||||
pr_info("vfs_read: %s, comm: %s, count: %d, rc_count: %d\n", dpath,
|
pr_info("vfs_read: %s, comm: %s, count: %zu, rc_count: %zu\n", dpath,
|
||||||
current->comm, count, rc_count);
|
current->comm, count, rc_count);
|
||||||
|
|
||||||
if (count < rc_count) {
|
if (count < rc_count) {
|
||||||
pr_err("count: %d < rc_count: %d\n", count, rc_count);
|
pr_err("count: %zu < rc_count: %zu\n", count, rc_count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ret = copy_to_user(buf, KERNEL_SU_RC, rc_count);
|
size_t ret = copy_to_user(buf, KERNEL_SU_RC, rc_count);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("copy ksud.rc failed: %d\n", ret);
|
pr_err("copy ksud.rc failed: %zu\n", ret);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ bool become_manager(char *pkg)
|
|||||||
char *buf;
|
char *buf;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
#ifdef KSU_MANAGER_PACKAGE
|
||||||
|
// pkg is `/<real package>`
|
||||||
|
if (strncmp(pkg + 1, KSU_MANAGER_PACKAGE,
|
||||||
|
sizeof(KSU_MANAGER_PACKAGE)) != 0) {
|
||||||
|
pr_info("manager package is inconsistent with kernel build: %s\n",
|
||||||
|
KSU_MANAGER_PACKAGE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// must be zygote's direct child, otherwise any app can fork a new process and
|
// must be zygote's direct child, otherwise any app can fork a new process and
|
||||||
// open manager's apk
|
// open manager's apk
|
||||||
if (task_uid(current->real_parent).val != 0) {
|
if (task_uid(current->real_parent).val != 0) {
|
||||||
@@ -48,7 +57,8 @@ bool become_manager(char *pkg)
|
|||||||
}
|
}
|
||||||
cwd = d_path(&files_path, buf, PATH_MAX);
|
cwd = d_path(&files_path, buf, PATH_MAX);
|
||||||
if (startswith(cwd, "/data/app/") != 0 ||
|
if (startswith(cwd, "/data/app/") != 0 ||
|
||||||
endswith(cwd, "/base.apk") != 0) {
|
endswith(cwd, "==/base.apk") != 0) {
|
||||||
|
// AOSP generate ramdom base64 with 16bit, without NO_PADDING, so it must have two "="
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// we have found the apk!
|
// we have found the apk!
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ void apply_kernelsu_rules()
|
|||||||
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL);
|
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "blk_file", ALL);
|
||||||
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL);
|
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "fifo_file", ALL);
|
||||||
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
|
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
|
||||||
|
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "file", ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to save allowlist in /data/adb/ksu
|
// we need to save allowlist in /data/adb/ksu
|
||||||
@@ -83,6 +84,7 @@ void apply_kernelsu_rules()
|
|||||||
ksu_allow(db, "kernel", "system_data_file", "dir", ALL);
|
ksu_allow(db, "kernel", "system_data_file", "dir", ALL);
|
||||||
// our ksud triggered by init
|
// our ksud triggered by init
|
||||||
ksu_allow(db, "init", "adb_data_file", "file", ALL);
|
ksu_allow(db, "init", "adb_data_file", "file", ALL);
|
||||||
|
ksu_allow(db, "init", "adb_data_file", "dir", ALL); // #1289
|
||||||
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
|
ksu_allow(db, "init", KERNEL_SU_DOMAIN, ALL, ALL);
|
||||||
// we need to umount modules in zygote
|
// we need to umount modules in zygote
|
||||||
ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
|
ksu_allow(db, "zygote", "adb_data_file", "dir", "search");
|
||||||
@@ -129,6 +131,10 @@ void apply_kernelsu_rules()
|
|||||||
ksu_allow(db, "system_server", "untrusted_app_all_devpts", "chr_file",
|
ksu_allow(db, "system_server", "untrusted_app_all_devpts", "chr_file",
|
||||||
"write");
|
"write");
|
||||||
|
|
||||||
|
// Allow system server kill su process
|
||||||
|
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid");
|
||||||
|
ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill");
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +182,8 @@ static int get_object(char *buf, char __user *user_object, size_t buf_sz,
|
|||||||
// reset avc cache table, otherwise the new rules will not take effect if already denied
|
// reset avc cache table, otherwise the new rules will not take effect if already denied
|
||||||
static void reset_avc_cache()
|
static void reset_avc_cache()
|
||||||
{
|
{
|
||||||
#ifndef KSU_COMPAT_USE_SELINUX_STATE
|
#if ((!defined(KSU_COMPAT_USE_SELINUX_STATE)) || \
|
||||||
|
LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
|
||||||
avc_ss_reset(0);
|
avc_ss_reset(0);
|
||||||
selnl_notify_policyload(0);
|
selnl_notify_policyload(0);
|
||||||
selinux_status_update_policyload(0);
|
selinux_status_update_policyload(0);
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#define KERNEL_SU_DOMAIN "u:r:su:s0"
|
#define KERNEL_SU_DOMAIN "u:r:su:s0"
|
||||||
|
|
||||||
static u32 ksu_sid;
|
|
||||||
|
|
||||||
static int transive_to_domain(const char *domain)
|
static int transive_to_domain(const char *domain)
|
||||||
{
|
{
|
||||||
struct cred *cred;
|
struct cred *cred;
|
||||||
@@ -27,12 +25,10 @@ static int transive_to_domain(const char *domain)
|
|||||||
|
|
||||||
error = security_secctx_to_secid(domain, strlen(domain), &sid);
|
error = security_secctx_to_secid(domain, strlen(domain), &sid);
|
||||||
if (error) {
|
if (error) {
|
||||||
pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n", domain, sid, error);
|
pr_info("security_secctx_to_secid %s -> sid: %d, error: %d\n",
|
||||||
|
domain, sid, error);
|
||||||
}
|
}
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (!ksu_sid)
|
|
||||||
ksu_sid = sid;
|
|
||||||
|
|
||||||
tsec->sid = sid;
|
tsec->sid = sid;
|
||||||
tsec->create_sid = 0;
|
tsec->create_sid = 0;
|
||||||
tsec->keycreate_sid = 0;
|
tsec->keycreate_sid = 0;
|
||||||
@@ -105,5 +101,32 @@ static inline u32 current_sid(void)
|
|||||||
|
|
||||||
bool is_ksu_domain()
|
bool is_ksu_domain()
|
||||||
{
|
{
|
||||||
return ksu_sid && current_sid() == ksu_sid;
|
char *domain;
|
||||||
|
u32 seclen;
|
||||||
|
bool result;
|
||||||
|
int err = security_secid_to_secctx(current_sid(), &domain, &seclen);
|
||||||
|
if (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result = strncmp(KERNEL_SU_DOMAIN, domain, seclen) == 0;
|
||||||
|
security_release_secctx(domain, seclen);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_zygote(void *sec)
|
||||||
|
{
|
||||||
|
struct task_security_struct *tsec = (struct task_security_struct *)sec;
|
||||||
|
if (!tsec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *domain;
|
||||||
|
u32 seclen;
|
||||||
|
bool result;
|
||||||
|
int err = security_secid_to_secctx(tsec->sid, &domain, &seclen);
|
||||||
|
if (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result = strncmp("u:r:zygote:s0", domain, seclen) == 0;
|
||||||
|
security_release_secctx(domain, seclen);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -16,6 +16,8 @@ bool getenforce();
|
|||||||
|
|
||||||
bool is_ksu_domain();
|
bool is_ksu_domain();
|
||||||
|
|
||||||
|
bool is_zygote(void *cred);
|
||||||
|
|
||||||
void apply_kernelsu_rules();
|
void apply_kernelsu_rules();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ echo '[+] Add kernel su driver to Makefile'
|
|||||||
|
|
||||||
DRIVER_MAKEFILE=$DRIVER_DIR/Makefile
|
DRIVER_MAKEFILE=$DRIVER_DIR/Makefile
|
||||||
DRIVER_KCONFIG=$DRIVER_DIR/Kconfig
|
DRIVER_KCONFIG=$DRIVER_DIR/Kconfig
|
||||||
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "obj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
|
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"
|
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
|
||||||
|
|
||||||
echo '[+] Done.'
|
echo '[+] Done.'
|
||||||
|
|||||||
@@ -75,12 +75,26 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
|
|||||||
|
|
||||||
char path[sizeof(su) + 1];
|
char path[sizeof(su) + 1];
|
||||||
memset(path, 0, sizeof(path));
|
memset(path, 0, sizeof(path));
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
|
||||||
|
// it becomes a `struct filename *` after 5.18
|
||||||
|
// https://elixir.bootlin.com/linux/v5.18/source/fs/stat.c#L216
|
||||||
|
const char sh[] = SH_PATH;
|
||||||
|
struct filename *filename = * ((struct filename **) filename_user);
|
||||||
|
if (IS_ERR(filename)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (likely(memcmp(filename->name, su, sizeof(su))))
|
||||||
|
return 0;
|
||||||
|
pr_info("vfs_statx su->sh!\n");
|
||||||
|
memcpy((void *)filename->name, sh, sizeof(sh));
|
||||||
|
#else
|
||||||
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
|
||||||
|
|
||||||
if (unlikely(!memcmp(path, su, sizeof(su)))) {
|
if (unlikely(!memcmp(path, su, sizeof(su)))) {
|
||||||
pr_info("newfstatat su->sh!\n");
|
pr_info("newfstatat su->sh!\n");
|
||||||
*filename_user = sh_user_path();
|
*filename_user = sh_user_path();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,18 @@ static struct work_struct ksu_update_uid_work;
|
|||||||
struct uid_data {
|
struct uid_data {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
u32 uid;
|
u32 uid;
|
||||||
|
char package[KSU_MAX_PACKAGE_NAME];
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool is_uid_exist(uid_t uid, void *data)
|
static bool is_uid_exist(uid_t uid, char *package, void *data)
|
||||||
{
|
{
|
||||||
struct list_head *list = (struct list_head *)data;
|
struct list_head *list = (struct list_head *)data;
|
||||||
struct uid_data *np;
|
struct uid_data *np;
|
||||||
|
|
||||||
bool exist = false;
|
bool exist = false;
|
||||||
list_for_each_entry (np, list, list) {
|
list_for_each_entry (np, list, list) {
|
||||||
if (np->uid == uid % 100000) {
|
if (np->uid == uid % 100000 &&
|
||||||
|
strncmp(np->package, package, KSU_MAX_PACKAGE_NAME) == 0) {
|
||||||
exist = true;
|
exist = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -39,10 +41,11 @@ static bool is_uid_exist(uid_t uid, void *data)
|
|||||||
|
|
||||||
static void do_update_uid(struct work_struct *work)
|
static void do_update_uid(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct file *fp = ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
struct file *fp =
|
||||||
|
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
pr_err("do_update_uid, open " SYSTEM_PACKAGES_LIST_PATH
|
pr_err("do_update_uid, open " SYSTEM_PACKAGES_LIST_PATH
|
||||||
" failed: %d\n",
|
" failed: %ld\n",
|
||||||
PTR_ERR(fp));
|
PTR_ERR(fp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -53,7 +56,7 @@ static void do_update_uid(struct work_struct *work)
|
|||||||
char chr = 0;
|
char chr = 0;
|
||||||
loff_t pos = 0;
|
loff_t pos = 0;
|
||||||
loff_t line_start = 0;
|
loff_t line_start = 0;
|
||||||
char buf[128];
|
char buf[KSU_MAX_PACKAGE_NAME];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t count =
|
ssize_t count =
|
||||||
ksu_kernel_read_compat(fp, &chr, sizeof(chr), &pos);
|
ksu_kernel_read_compat(fp, &chr, sizeof(chr), &pos);
|
||||||
@@ -66,26 +69,27 @@ static void do_update_uid(struct work_struct *work)
|
|||||||
&line_start);
|
&line_start);
|
||||||
|
|
||||||
struct uid_data *data =
|
struct uid_data *data =
|
||||||
kmalloc(sizeof(struct uid_data), GFP_ATOMIC);
|
kzalloc(sizeof(struct uid_data), GFP_ATOMIC);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *tmp = buf;
|
char *tmp = buf;
|
||||||
const char *delim = " ";
|
const char *delim = " ";
|
||||||
strsep(&tmp, delim); // skip package
|
char *package = strsep(&tmp, delim);
|
||||||
char *uid = strsep(&tmp, delim);
|
char *uid = strsep(&tmp, delim);
|
||||||
if (!uid) {
|
if (!uid || !package) {
|
||||||
pr_err("update_uid: uid is NULL!\n");
|
pr_err("update_uid: package or uid is NULL!\n");
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 res;
|
u32 res;
|
||||||
if (kstrtou32(uid, 10, &res)) {
|
if (kstrtou32(uid, 10, &res)) {
|
||||||
pr_err("update_uid: uid parse err\n");
|
pr_err("update_uid: uid parse err\n");
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
data->uid = res;
|
data->uid = res;
|
||||||
|
strncpy(data->package, package, KSU_MAX_PACKAGE_NAME);
|
||||||
list_add_tail(&data->list, &uid_list);
|
list_add_tail(&data->list, &uid_list);
|
||||||
// reset line start
|
// reset line start
|
||||||
line_start = pos;
|
line_start = pos;
|
||||||
|
|||||||
@@ -93,12 +93,14 @@ dependencies {
|
|||||||
implementation(libs.com.google.accompanist.drawablepainter)
|
implementation(libs.com.google.accompanist.drawablepainter)
|
||||||
implementation(libs.com.google.accompanist.navigation.animation)
|
implementation(libs.com.google.accompanist.navigation.animation)
|
||||||
implementation(libs.com.google.accompanist.systemuicontroller)
|
implementation(libs.com.google.accompanist.systemuicontroller)
|
||||||
|
implementation(libs.com.google.accompanist.webview)
|
||||||
|
|
||||||
implementation(libs.compose.destinations.animations.core)
|
implementation(libs.compose.destinations.animations.core)
|
||||||
ksp(libs.compose.destinations.ksp)
|
ksp(libs.compose.destinations.ksp)
|
||||||
|
|
||||||
implementation(libs.com.github.topjohnwu.libsu.core)
|
implementation(libs.com.github.topjohnwu.libsu.core)
|
||||||
implementation(libs.com.github.topjohnwu.libsu.service)
|
implementation(libs.com.github.topjohnwu.libsu.service)
|
||||||
|
implementation(libs.com.github.topjohnwu.libsu.io)
|
||||||
|
|
||||||
implementation(libs.dev.rikka.rikkax.parcelablelist)
|
implementation(libs.dev.rikka.rikkax.parcelablelist)
|
||||||
|
|
||||||
@@ -113,4 +115,5 @@ dependencies {
|
|||||||
implementation(libs.sheet.compose.dialogs.input)
|
implementation(libs.sheet.compose.dialogs.input)
|
||||||
|
|
||||||
implementation(libs.markdown)
|
implementation(libs.markdown)
|
||||||
|
implementation(libs.androidx.webkit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:theme="@style/Theme.KernelSU"
|
android:theme="@style/Theme.KernelSU"
|
||||||
tools:targetApi="33">
|
tools:targetApi="33">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -156,13 +156,6 @@ Java_me_weishu_kernelsu_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg,
|
|||||||
env->SetBooleanField(obj, allowSuField, false);
|
env->SetBooleanField(obj, allowSuField, false);
|
||||||
env->SetBooleanField(obj, nonRootUseDefaultField, true);
|
env->SetBooleanField(obj, nonRootUseDefaultField, true);
|
||||||
|
|
||||||
jobject capList = env->GetObjectField(obj, capabilitiesField);
|
|
||||||
int DEFAULT_CAPS[] = {CAP_DAC_READ_SEARCH};
|
|
||||||
|
|
||||||
for (auto i: DEFAULT_CAPS) {
|
|
||||||
addIntToList(env, capList, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import coil.Coil
|
|||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
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 java.io.File
|
||||||
|
|
||||||
lateinit var ksuApp: KernelSUApplication
|
lateinit var ksuApp: KernelSUApplication
|
||||||
|
|
||||||
@@ -24,6 +25,11 @@ class KernelSUApplication : Application() {
|
|||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val webroot = File(dataDir, "webroot")
|
||||||
|
if (!webroot.exists()) {
|
||||||
|
webroot.mkdir()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ object Natives {
|
|||||||
// 11071: Fix the issue of failing to set a custom SELinux type.
|
// 11071: Fix the issue of failing to set a custom SELinux type.
|
||||||
const val MINIMAL_SUPPORTED_KERNEL = 11071
|
const val MINIMAL_SUPPORTED_KERNEL = 11071
|
||||||
|
|
||||||
|
const val KERNEL_SU_DOMAIN = "u:r:su:s0"
|
||||||
|
|
||||||
|
const val ROOT_UID = 0
|
||||||
|
const val ROOT_GID = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
System.loadLibrary("kernelsu")
|
System.loadLibrary("kernelsu")
|
||||||
}
|
}
|
||||||
@@ -45,7 +50,6 @@ object Natives {
|
|||||||
external fun setAppProfile(profile: Profile?): Boolean
|
external fun setAppProfile(profile: Profile?): Boolean
|
||||||
|
|
||||||
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
|
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
|
||||||
private const val ROOT_DEFAULT_PROFILE_KEY = "#"
|
|
||||||
private const val NOBODY_UID = 9999
|
private const val NOBODY_UID = 9999
|
||||||
|
|
||||||
fun setDefaultUmountModules(umountModules: Boolean): Boolean {
|
fun setDefaultUmountModules(umountModules: Boolean): Boolean {
|
||||||
@@ -85,21 +89,21 @@ object Natives {
|
|||||||
// these are used for root profile
|
// these are used for root profile
|
||||||
val rootUseDefault: Boolean = true,
|
val rootUseDefault: Boolean = true,
|
||||||
val rootTemplate: String? = null,
|
val rootTemplate: String? = null,
|
||||||
val uid: Int = 0,
|
val uid: Int = ROOT_UID,
|
||||||
val gid: Int = 0,
|
val gid: Int = ROOT_GID,
|
||||||
val groups: List<Int> = mutableListOf(),
|
val groups: List<Int> = mutableListOf(),
|
||||||
val capabilities: List<Int> = mutableListOf(),
|
val capabilities: List<Int> = mutableListOf(),
|
||||||
val context: String = "u:r:su:s0",
|
val context: String = KERNEL_SU_DOMAIN,
|
||||||
val namespace: Int = Namespace.Inherited.ordinal,
|
val namespace: Int = Namespace.INHERITED.ordinal,
|
||||||
|
|
||||||
val nonRootUseDefault: Boolean = true,
|
val nonRootUseDefault: Boolean = true,
|
||||||
val umountModules: Boolean = true,
|
val umountModules: Boolean = true,
|
||||||
var rules: String = "", // this field is save in ksud!!
|
var rules: String = "", // this field is save in ksud!!
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
enum class Namespace {
|
enum class Namespace {
|
||||||
Inherited,
|
INHERITED,
|
||||||
Global,
|
GLOBAL,
|
||||||
Individual,
|
INDIVIDUAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() : this("")
|
constructor() : this("")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package me.weishu.kernelsu.profile
|
package me.weishu.kernelsu.profile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* https://cs.android.com/android/platform/superproject/main/+/main:system/core/libcutils/include/private/android_filesystem_config.h
|
||||||
* @author weishu
|
* @author weishu
|
||||||
* @date 2023/6/3.
|
* @date 2023/6/3.
|
||||||
*/
|
*/
|
||||||
@@ -60,17 +61,55 @@ enum class Groups(val gid: Int, val display: String, val desc: String) {
|
|||||||
FIREWALL(1048, "firewall", "firewall process"),
|
FIREWALL(1048, "firewall", "firewall process"),
|
||||||
TRUNKS(1049, "trunks", "trunksd process"),
|
TRUNKS(1049, "trunks", "trunksd process"),
|
||||||
NVRAM(1050, "nvram", "nvram daemon"),
|
NVRAM(1050, "nvram", "nvram daemon"),
|
||||||
DNS_TETHER(1051, "dns_tether", "dns_tether device"),
|
DNS(1051, "dns", "DNS resolution daemon (system: netd)"),
|
||||||
DNS_TETHER_RESERVED(1052, "dns_tether_reserved", "Reserved range for dns_tether"),
|
DNS_TETHER(1052, "dns_tether", "DNS resolution daemon (tether: dnsmasq)"),
|
||||||
WEBVIEW_ZYGOTE(1053, "webview_zygote", "zygote process"),
|
WEBVIEW_ZYGOTE(1053, "webview_zygote", "WebView zygote process"),
|
||||||
WEBVIEW_USER(1054, "webview_user", "webview chromium user"),
|
VEHICLE_NETWORK(1054, "vehicle_network", "Vehicle network service"),
|
||||||
ETHERNET(1055, "ethernet", "Ethernet"),
|
MEDIA_AUDIO(1055, "media_audio", "GID for audio files on internal media storage"),
|
||||||
TOMBSTONED(1056, "tombstoned", "tombstoned process"),
|
MEDIA_VIDEO(1056, "media_video", "GID for video files on internal media storage"),
|
||||||
GRAPHICS_RW(1057, "graphics_rw", "graphics devices"),
|
MEDIA_IMAGE(1057, "media_image", "GID for image files on internal media storage"),
|
||||||
|
TOMBSTONED(1058, "tombstoned", "tombstoned user"),
|
||||||
|
MEDIA_OBB(1059, "media_obb", "GID for OBB files on internal media storage"),
|
||||||
|
ESE(1060, "ese", "embedded secure element (eSE) subsystem"),
|
||||||
|
OTA_UPDATE(1061, "ota_update", "resource tracking UID for OTA updates"),
|
||||||
|
AUTOMOTIVE_EVS(1062, "automotive_evs", "Automotive rear and surround view system"),
|
||||||
|
LOWPAN(1063, "lowpan", "LoWPAN subsystem"),
|
||||||
|
HSM(1064, "lowpan", "hardware security module subsystem"),
|
||||||
|
RESERVED_DISK(1065, "reserved_disk", "GID that has access to reserved disk space"),
|
||||||
|
STATSD(1066, "statsd", "statsd daemon"),
|
||||||
|
INCIDENTD(1067, "incidentd", "incidentd daemon"),
|
||||||
|
SECURE_ELEMENT(1068, "secure_element", "secure element subsystem"),
|
||||||
|
LMKD(1069, "lmkd", "low memory killer daemon"),
|
||||||
|
LLKD(1070, "llkd", "live lock daemon"),
|
||||||
|
IORAPD(1071, "iorapd", "input/output readahead and pin daemon"),
|
||||||
|
GPU_SERVICE(1072, "gpu_service", "GPU service daemon"),
|
||||||
|
NETWORK_STACK(1073, "network_stack", "network stack service"),
|
||||||
|
GSID(1074, "GSID", "GSI service daemon"),
|
||||||
|
FSVERITY_CERT(1075, "fsverity_cert", "fs-verity key ownership in keystore"),
|
||||||
|
CREDSTORE(1076, "credstore", "identity credential manager service"),
|
||||||
|
EXTERNAL_STORAGE(1077, "external_storage", "Full external storage access including USB OTG volumes"),
|
||||||
|
EXT_DATA_RW(1078, "ext_data_rw", "GID for app-private data directories on external storage"),
|
||||||
|
EXT_OBB_RW(1079, "ext_obb_rw", "GID for OBB directories on external storage"),
|
||||||
|
CONTEXT_HUB(1080, "context_hub", "GID for access to the Context Hub"),
|
||||||
|
VIRTUALIZATIONSERVICE(1081, "virtualizationservice", "VirtualizationService daemon"),
|
||||||
|
ARTD(1082, "artd", "ART Service daemon"),
|
||||||
|
UWB(1083, "uwb", "UWB subsystem"),
|
||||||
|
THREAD_NETWORK(1084, "thread_network", "Thread Network subsystem"),
|
||||||
|
DICED(1085, "diced", "Android's DICE daemon"),
|
||||||
|
DMESGD(1086, "dmesgd", "dmesg parsing daemon for kernel report collection"),
|
||||||
|
JC_WEAVER(1087, "jc_weaver", "Javacard Weaver HAL - to manage omapi ARA rules"),
|
||||||
|
JC_STRONGBOX(1088, "jc_strongbox", "Javacard Strongbox HAL - to manage omapi ARA rules"),
|
||||||
|
JC_IDENTITYCRED(1089, "jc_identitycred", "Javacard Identity Cred HAL - to manage omapi ARA rules"),
|
||||||
|
SDK_SANDBOX(1090, "sdk_sandbox", "SDK sandbox virtual UID"),
|
||||||
|
SECURITY_LOG_WRITER(1091, "security_log_writer", "write to security log"),
|
||||||
|
PRNG_SEEDER(1092, "prng_seeder", "PRNG seeder daemon"),
|
||||||
|
|
||||||
SHELL(2000, "shell", "adb and debug shell user"),
|
SHELL(2000, "shell", "adb and debug shell user"),
|
||||||
CACHE(2001, "cache", "cache access"),
|
CACHE(2001, "cache", "cache access"),
|
||||||
DIAG(2002, "diag", "diagnostics"),
|
DIAG(2002, "diag", "access to diagnostic resources"),
|
||||||
|
|
||||||
|
/* The 3000 series are intended for use as supplemental group id's only.
|
||||||
|
* They indicate special Android capabilities that the kernel is aware of. */
|
||||||
NET_BT_ADMIN(3001, "net_bt_admin", "bluetooth: create any socket"),
|
NET_BT_ADMIN(3001, "net_bt_admin", "bluetooth: create any socket"),
|
||||||
NET_BT(3002, "net_bt", "bluetooth: create sco, rfcomm or l2cap sockets"),
|
NET_BT(3002, "net_bt", "bluetooth: create sco, rfcomm or l2cap sockets"),
|
||||||
INET(3003, "inet", "can create AF_INET and AF_INET6 sockets"),
|
INET(3003, "inet", "can create AF_INET and AF_INET6 sockets"),
|
||||||
@@ -79,7 +118,11 @@ enum class Groups(val gid: Int, val display: String, val desc: String) {
|
|||||||
NET_BW_STATS(3006, "net_bw_stats", "read bandwidth statistics"),
|
NET_BW_STATS(3006, "net_bw_stats", "read bandwidth statistics"),
|
||||||
NET_BW_ACCT(3007, "net_bw_acct", "change bandwidth statistics accounting"),
|
NET_BW_ACCT(3007, "net_bw_acct", "change bandwidth statistics accounting"),
|
||||||
NET_BT_STACK(3008, "net_bt_stack", "access to various bluetooth management functions"),
|
NET_BT_STACK(3008, "net_bt_stack", "access to various bluetooth management functions"),
|
||||||
QCOM_DIAG(3009, "qcom_diag", "allow msm specific diag commands"),
|
READPROC(3009, "readproc", "Allow /proc read access"),
|
||||||
|
WAKELOCK(3010, "wakelock", "Allow system wakelock read/write access"),
|
||||||
|
UHID(3011, "uhid", "Allow read/write to /dev/uhid node"),
|
||||||
|
READTRACEFS(3012, "readtracefs", "Allow tracefs read"),
|
||||||
|
|
||||||
EVERYBODY(9997, "everybody", "Shared external storage read/write"),
|
EVERYBODY(9997, "everybody", "Shared external storage read/write"),
|
||||||
MISC(9998, "misc", "Access to misc storage"),
|
MISC(9998, "misc", "Access to misc storage"),
|
||||||
NOBODY(9999, "nobody", "Reserved"),
|
NOBODY(9999, "nobody", "Reserved"),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||||
import com.ramcosta.composedestinations.DestinationsNavHost
|
import com.ramcosta.composedestinations.DestinationsNavHost
|
||||||
import com.ramcosta.composedestinations.navigation.popBackStack
|
import com.ramcosta.composedestinations.navigation.popBackStack
|
||||||
@@ -32,6 +33,7 @@ import me.weishu.kernelsu.ui.screen.NavGraphs
|
|||||||
import me.weishu.kernelsu.ui.theme.KernelSUTheme
|
import me.weishu.kernelsu.ui.theme.KernelSUTheme
|
||||||
import me.weishu.kernelsu.ui.util.LocalDialogHost
|
import me.weishu.kernelsu.ui.util.LocalDialogHost
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
|
import me.weishu.kernelsu.ui.util.rootAvailable
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@@ -43,8 +45,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
KernelSUTheme {
|
KernelSUTheme {
|
||||||
val navController = rememberAnimatedNavController()
|
val navController = rememberAnimatedNavController()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val route = navBackStackEntry?.destination?.route
|
||||||
|
val showBottomBar = route == null || !route.startsWith("web_screen")
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = { BottomBar(navController) },
|
bottomBar = { if (showBottomBar) BottomBar(navController) },
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
snackbarHost = { SnackbarHost(snackbarHostState) }
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
@@ -66,7 +71,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun BottomBar(navController: NavHostController) {
|
private fun BottomBar(navController: NavHostController) {
|
||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
val fullFeatured = isManager && !Natives.requireNewKernel()
|
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
||||||
NavigationBar(tonalElevation = 8.dp) {
|
NavigationBar(tonalElevation = 8.dp) {
|
||||||
BottomBarDestination.values().forEach { destination ->
|
BottomBarDestination.values().forEach { destination ->
|
||||||
if (!fullFeatured && destination.rootRequired) return@forEach
|
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ fun RootProfileConfig(
|
|||||||
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
val currentNamespace = when (profile.namespace) {
|
val currentNamespace = when (profile.namespace) {
|
||||||
Natives.Profile.Namespace.Inherited.ordinal -> stringResource(R.string.profile_namespace_inherited)
|
Natives.Profile.Namespace.INHERITED.ordinal -> stringResource(R.string.profile_namespace_inherited)
|
||||||
Natives.Profile.Namespace.Global.ordinal -> stringResource(R.string.profile_namespace_global)
|
Natives.Profile.Namespace.GLOBAL.ordinal -> stringResource(R.string.profile_namespace_global)
|
||||||
Natives.Profile.Namespace.Individual.ordinal -> stringResource(R.string.profile_namespace_individual)
|
Natives.Profile.Namespace.INDIVIDUAL.ordinal -> stringResource(R.string.profile_namespace_individual)
|
||||||
else -> stringResource(R.string.profile_namespace_inherited)
|
else -> stringResource(R.string.profile_namespace_inherited)
|
||||||
}
|
}
|
||||||
ListItem(headlineContent = {
|
ListItem(headlineContent = {
|
||||||
@@ -104,21 +104,21 @@ fun RootProfileConfig(
|
|||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.profile_namespace_inherited)) },
|
text = { Text(stringResource(R.string.profile_namespace_inherited)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.Inherited.ordinal))
|
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.INHERITED.ordinal))
|
||||||
expanded = false
|
expanded = false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.profile_namespace_global)) },
|
text = { Text(stringResource(R.string.profile_namespace_global)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.Global.ordinal))
|
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.GLOBAL.ordinal))
|
||||||
expanded = false
|
expanded = false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(R.string.profile_namespace_individual)) },
|
text = { Text(stringResource(R.string.profile_namespace_individual)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.Individual.ordinal))
|
onProfileChange(profile.copy(namespace = Natives.Profile.Namespace.INDIVIDUAL.ordinal))
|
||||||
expanded = false
|
expanded = false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -191,7 +191,19 @@ fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>)
|
|||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val groups = Groups.values()
|
val groups = Groups.values().sortedWith(
|
||||||
|
compareBy<Groups> { if (selected.contains(it)) 0 else 1 }
|
||||||
|
.then(compareBy {
|
||||||
|
when (it) {
|
||||||
|
Groups.ROOT -> 0
|
||||||
|
Groups.SYSTEM -> 1
|
||||||
|
Groups.SHELL -> 2
|
||||||
|
else -> Int.MAX_VALUE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(compareBy { it.name })
|
||||||
|
|
||||||
|
)
|
||||||
val options = groups.map { value ->
|
val options = groups.map { value ->
|
||||||
ListOption(
|
ListOption(
|
||||||
titleText = value.display,
|
titleText = value.display,
|
||||||
@@ -257,7 +269,10 @@ fun CapsPanel(
|
|||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
val caps = Capabilities.values()
|
val caps = Capabilities.values().sortedWith(
|
||||||
|
compareBy<Capabilities> { if (selected.contains(it)) 0 else 1 }
|
||||||
|
.then(compareBy { it.name })
|
||||||
|
)
|
||||||
val options = caps.map { value ->
|
val options = caps.map { value ->
|
||||||
ListOption(
|
ListOption(
|
||||||
titleText = value.display,
|
titleText = value.display,
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package me.weishu.kernelsu.ui.component.profile
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||||
|
import androidx.compose.material.icons.filled.ArrowDropUp
|
||||||
|
import androidx.compose.material.icons.filled.Create
|
||||||
|
import androidx.compose.material.icons.filled.ReadMore
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import me.weishu.kernelsu.Natives
|
||||||
|
import me.weishu.kernelsu.R
|
||||||
|
import me.weishu.kernelsu.ui.util.listAppProfileTemplates
|
||||||
|
import me.weishu.kernelsu.ui.util.setSepolicy
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.getTemplateInfoById
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author weishu
|
||||||
|
* @date 2023/10/21.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun TemplateConfig(
|
||||||
|
profile: Natives.Profile,
|
||||||
|
onViewTemplate: (id: String) -> Unit = {},
|
||||||
|
onManageTemplate: () -> Unit = {},
|
||||||
|
onProfileChange: (Natives.Profile) -> Unit
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
var template by rememberSaveable {
|
||||||
|
mutableStateOf(profile.rootTemplate ?: "")
|
||||||
|
}
|
||||||
|
val profileTemplates = listAppProfileTemplates()
|
||||||
|
val noTemplates = profileTemplates.isEmpty()
|
||||||
|
|
||||||
|
ListItem(headlineContent = {
|
||||||
|
ExposedDropdownMenuBox(
|
||||||
|
expanded = expanded,
|
||||||
|
onExpandedChange = { expanded = it },
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.menuAnchor()
|
||||||
|
.fillMaxWidth(),
|
||||||
|
readOnly = true,
|
||||||
|
label = { Text(stringResource(R.string.profile_template)) },
|
||||||
|
value = template.ifEmpty { "None" },
|
||||||
|
onValueChange = {},
|
||||||
|
trailingIcon = {
|
||||||
|
if (noTemplates) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onManageTemplate
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.Create, null)
|
||||||
|
}
|
||||||
|
} else if (expanded) Icon(Icons.Filled.ArrowDropUp, null)
|
||||||
|
else Icon(Icons.Filled.ArrowDropDown, null)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if (profileTemplates.isEmpty()) {
|
||||||
|
return@ExposedDropdownMenuBox
|
||||||
|
}
|
||||||
|
ExposedDropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
profileTemplates.forEach { tid ->
|
||||||
|
val templateInfo =
|
||||||
|
getTemplateInfoById(tid) ?: return@forEach
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(tid) },
|
||||||
|
onClick = {
|
||||||
|
template = tid
|
||||||
|
if (setSepolicy(tid, templateInfo.rules.joinToString("\n"))) {
|
||||||
|
onProfileChange(
|
||||||
|
profile.copy(
|
||||||
|
rootTemplate = tid,
|
||||||
|
rootUseDefault = false,
|
||||||
|
uid = templateInfo.uid,
|
||||||
|
gid = templateInfo.gid,
|
||||||
|
groups = templateInfo.groups,
|
||||||
|
capabilities = templateInfo.capabilities,
|
||||||
|
context = templateInfo.context,
|
||||||
|
namespace = templateInfo.namespace,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
expanded = false
|
||||||
|
},
|
||||||
|
trailingIcon = {
|
||||||
|
IconButton(onClick = {
|
||||||
|
onViewTemplate(tid)
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Filled.ReadMore, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -18,19 +18,15 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.AccountCircle
|
import androidx.compose.material.icons.filled.AccountCircle
|
||||||
import androidx.compose.material.icons.filled.Android
|
import androidx.compose.material.icons.filled.Android
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
|
||||||
import androidx.compose.material.icons.filled.ArrowDropUp
|
|
||||||
import androidx.compose.material.icons.filled.Security
|
import androidx.compose.material.icons.filled.Security
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
|
||||||
import androidx.compose.material3.FilterChip
|
import androidx.compose.material3.FilterChip
|
||||||
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.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
@@ -61,6 +57,9 @@ import me.weishu.kernelsu.R
|
|||||||
import me.weishu.kernelsu.ui.component.SwitchItem
|
import me.weishu.kernelsu.ui.component.SwitchItem
|
||||||
import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
|
import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
|
||||||
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
||||||
|
import me.weishu.kernelsu.ui.component.profile.TemplateConfig
|
||||||
|
import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination
|
||||||
|
import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
import me.weishu.kernelsu.ui.util.forceStopApp
|
import me.weishu.kernelsu.ui.util.forceStopApp
|
||||||
import me.weishu.kernelsu.ui.util.getSepolicy
|
import me.weishu.kernelsu.ui.util.getSepolicy
|
||||||
@@ -68,6 +67,7 @@ import me.weishu.kernelsu.ui.util.launchApp
|
|||||||
import me.weishu.kernelsu.ui.util.restartApp
|
import me.weishu.kernelsu.ui.util.restartApp
|
||||||
import me.weishu.kernelsu.ui.util.setSepolicy
|
import me.weishu.kernelsu.ui.util.setSepolicy
|
||||||
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.getTemplateInfoById
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author weishu
|
* @author weishu
|
||||||
@@ -107,9 +107,7 @@ fun AppProfileScreen(
|
|||||||
appLabel = appInfo.label,
|
appLabel = appInfo.label,
|
||||||
appIcon = {
|
appIcon = {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = ImageRequest.Builder(context)
|
model = ImageRequest.Builder(context).data(appInfo.packageInfo).crossfade(true)
|
||||||
.data(appInfo.packageInfo)
|
|
||||||
.crossfade(true)
|
|
||||||
.build(),
|
.build(),
|
||||||
contentDescription = appInfo.label,
|
contentDescription = appInfo.label,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -119,6 +117,14 @@ fun AppProfileScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
profile = profile,
|
profile = profile,
|
||||||
|
onViewTemplate = {
|
||||||
|
getTemplateInfoById(it)?.let { info ->
|
||||||
|
navigator.navigate(TemplateEditorScreenDestination(info))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onManageTemplate = {
|
||||||
|
navigator.navigate(AppProfileTemplateScreenDestination())
|
||||||
|
},
|
||||||
onProfileChange = {
|
onProfileChange = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
if (it.allowSu && !it.rootUseDefault && it.rules.isNotEmpty()) {
|
if (it.allowSu && !it.rootUseDefault && it.rules.isNotEmpty()) {
|
||||||
@@ -138,7 +144,6 @@ fun AppProfileScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AppProfileInner(
|
private fun AppProfileInner(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@@ -146,6 +151,8 @@ private fun AppProfileInner(
|
|||||||
appLabel: String,
|
appLabel: String,
|
||||||
appIcon: @Composable () -> Unit,
|
appIcon: @Composable () -> Unit,
|
||||||
profile: Natives.Profile,
|
profile: Natives.Profile,
|
||||||
|
onViewTemplate: (id: String) -> Unit = {},
|
||||||
|
onManageTemplate: () -> Unit = {},
|
||||||
onProfileChange: (Natives.Profile) -> Unit,
|
onProfileChange: (Natives.Profile) -> Unit,
|
||||||
) {
|
) {
|
||||||
val isRootGranted = profile.allowSu
|
val isRootGranted = profile.allowSu
|
||||||
@@ -179,7 +186,7 @@ private fun AppProfileInner(
|
|||||||
var mode by remember {
|
var mode by remember {
|
||||||
mutableStateOf(initialMode)
|
mutableStateOf(initialMode)
|
||||||
}
|
}
|
||||||
ProfileBox(mode, false) {
|
ProfileBox(mode, true) {
|
||||||
// template mode shouldn't change profile here!
|
// template mode shouldn't change profile here!
|
||||||
if (it == Mode.Default || it == Mode.Custom) {
|
if (it == Mode.Default || it == Mode.Custom) {
|
||||||
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
|
onProfileChange(profile.copy(rootUseDefault = it == Mode.Default))
|
||||||
@@ -188,43 +195,12 @@ private fun AppProfileInner(
|
|||||||
}
|
}
|
||||||
Crossfade(targetState = mode, label = "") { currentMode ->
|
Crossfade(targetState = mode, label = "") { currentMode ->
|
||||||
if (currentMode == Mode.Template) {
|
if (currentMode == Mode.Template) {
|
||||||
var expanded by remember { mutableStateOf(false) }
|
TemplateConfig(
|
||||||
val templateNone = "None"
|
profile = profile,
|
||||||
var template by rememberSaveable {
|
onViewTemplate = onViewTemplate,
|
||||||
mutableStateOf(
|
onManageTemplate = onManageTemplate,
|
||||||
profile.rootTemplate
|
onProfileChange = onProfileChange
|
||||||
?: templateNone
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
ListItem(headlineContent = {
|
|
||||||
ExposedDropdownMenuBox(
|
|
||||||
expanded = expanded,
|
|
||||||
onExpandedChange = { expanded = it },
|
|
||||||
) {
|
|
||||||
OutlinedTextField(
|
|
||||||
modifier = Modifier.menuAnchor(),
|
|
||||||
readOnly = true,
|
|
||||||
label = { Text(stringResource(R.string.profile_template)) },
|
|
||||||
value = template,
|
|
||||||
onValueChange = {
|
|
||||||
if (template != templateNone) {
|
|
||||||
onProfileChange(
|
|
||||||
profile.copy(
|
|
||||||
rootTemplate = it,
|
|
||||||
rootUseDefault = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
template = it
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trailingIcon = {
|
|
||||||
if (expanded) Icon(Icons.Filled.ArrowDropUp, null)
|
|
||||||
else Icon(Icons.Filled.ArrowDropDown, null)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// TODO: Template
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (mode == Mode.Custom) {
|
} else if (mode == Mode.Custom) {
|
||||||
RootProfileConfig(
|
RootProfileConfig(
|
||||||
fixedName = true,
|
fixedName = true,
|
||||||
@@ -254,9 +230,7 @@ private fun AppProfileInner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum class Mode(@StringRes private val res: Int) {
|
private enum class Mode(@StringRes private val res: Int) {
|
||||||
Default(R.string.profile_default),
|
Default(R.string.profile_default), Template(R.string.profile_template), Custom(R.string.profile_custom);
|
||||||
Template(R.string.profile_template),
|
|
||||||
Custom(R.string.profile_custom);
|
|
||||||
|
|
||||||
val text: String
|
val text: String
|
||||||
@Composable get() = stringResource(res)
|
@Composable get() = stringResource(res)
|
||||||
@@ -292,8 +266,7 @@ private fun ProfileBox(
|
|||||||
Divider(thickness = Dp.Hairline)
|
Divider(thickness = Dp.Hairline)
|
||||||
ListItem(headlineContent = {
|
ListItem(headlineContent = {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly
|
|
||||||
) {
|
) {
|
||||||
FilterChip(
|
FilterChip(
|
||||||
selected = mode == Mode.Default,
|
selected = mode == Mode.Default,
|
||||||
@@ -331,8 +304,7 @@ private fun AppMenuBox(packageName: String, content: @Composable () -> Unit) {
|
|||||||
touchPoint = it
|
touchPoint = it
|
||||||
expanded = true
|
expanded = true
|
||||||
}
|
}
|
||||||
}
|
}) {
|
||||||
) {
|
|
||||||
|
|
||||||
content()
|
content()
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,17 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
UpdateCard()
|
if (!rootAvailable()) {
|
||||||
|
WarningCard(
|
||||||
|
stringResource(id = R.string.grant_root_failed)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val checkUpdate =
|
||||||
|
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
.getBoolean("check_update", true)
|
||||||
|
if (checkUpdate) {
|
||||||
|
UpdateCard()
|
||||||
|
}
|
||||||
InfoCard()
|
InfoCard()
|
||||||
DonateCard()
|
DonateCard()
|
||||||
LearnMoreCard()
|
LearnMoreCard()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.util.Log
|
|||||||
import android.widget.Toast
|
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.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -43,6 +44,7 @@ import me.weishu.kernelsu.ui.component.ConfirmDialog
|
|||||||
import me.weishu.kernelsu.ui.component.ConfirmResult
|
import me.weishu.kernelsu.ui.component.ConfirmResult
|
||||||
import me.weishu.kernelsu.ui.component.LoadingDialog
|
import me.weishu.kernelsu.ui.component.LoadingDialog
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.InstallScreenDestination
|
import me.weishu.kernelsu.ui.screen.destinations.InstallScreenDestination
|
||||||
|
import me.weishu.kernelsu.ui.screen.destinations.WebScreenDestination
|
||||||
import me.weishu.kernelsu.ui.util.*
|
import me.weishu.kernelsu.ui.util.*
|
||||||
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
|
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -122,10 +124,15 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
ModuleList(
|
ModuleList(
|
||||||
viewModel = viewModel, modifier = Modifier
|
viewModel = viewModel, modifier = Modifier
|
||||||
.padding(innerPadding)
|
.padding(innerPadding)
|
||||||
.fillMaxSize()
|
.fillMaxSize(),
|
||||||
) {
|
onInstallModule =
|
||||||
navigator.navigate(InstallScreenDestination(it))
|
{
|
||||||
}
|
navigator.navigate(InstallScreenDestination(it))
|
||||||
|
}, onClickModule = { id, name, hasWebUi ->
|
||||||
|
if (hasWebUi) {
|
||||||
|
navigator.navigate(WebScreenDestination(id, name))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +141,10 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun ModuleList(
|
private fun ModuleList(
|
||||||
viewModel: ModuleViewModel, modifier: Modifier = Modifier, onInstallModule: (Uri) -> Unit
|
viewModel: ModuleViewModel,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onInstallModule: (Uri) -> Unit,
|
||||||
|
onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
val failedEnable = stringResource(R.string.module_failed_to_enable)
|
val failedEnable = stringResource(R.string.module_failed_to_enable)
|
||||||
val failedDisable = stringResource(R.string.module_failed_to_disable)
|
val failedDisable = stringResource(R.string.module_failed_to_disable)
|
||||||
@@ -150,6 +160,7 @@ private fun ModuleList(
|
|||||||
val changelogText = stringResource(R.string.module_changelog)
|
val changelogText = stringResource(R.string.module_changelog)
|
||||||
val downloadingText = stringResource(R.string.module_downloading)
|
val downloadingText = stringResource(R.string.module_downloading)
|
||||||
val startDownloadingText = stringResource(R.string.module_start_downloading)
|
val startDownloadingText = stringResource(R.string.module_start_downloading)
|
||||||
|
val fetchChangeLogFailed = stringResource(R.string.module_changelog_failed)
|
||||||
|
|
||||||
val dialogHost = LocalDialogHost.current
|
val dialogHost = LocalDialogHost.current
|
||||||
val snackBarHost = LocalSnackbarHost.current
|
val snackBarHost = LocalSnackbarHost.current
|
||||||
@@ -161,36 +172,48 @@ private fun ModuleList(
|
|||||||
downloadUrl: String,
|
downloadUrl: String,
|
||||||
fileName: String
|
fileName: String
|
||||||
) {
|
) {
|
||||||
val changelog = dialogHost.withLoading {
|
val changelogResult = dialogHost.withLoading {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
OkHttpClient().newCall(
|
runCatching {
|
||||||
okhttp3.Request.Builder().url(changelogUrl).build()
|
OkHttpClient().newCall(
|
||||||
).execute().body!!.string()
|
okhttp3.Request.Builder().url(changelogUrl).build()
|
||||||
|
).execute().body!!.string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changelog.isNotEmpty()) {
|
val showToast: suspend (String) -> Unit = { msg ->
|
||||||
// changelog is not empty, show it and wait for confirm
|
withContext(Dispatchers.Main) {
|
||||||
val confirmResult = dialogHost.showConfirm(
|
Toast.makeText(
|
||||||
changelogText,
|
context,
|
||||||
content = changelog,
|
msg,
|
||||||
markdown = true,
|
Toast.LENGTH_SHORT
|
||||||
confirm = updateText,
|
).show()
|
||||||
)
|
|
||||||
|
|
||||||
if (confirmResult != ConfirmResult.Confirmed) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
val changelog = changelogResult.getOrElse {
|
||||||
Toast.makeText(
|
showToast(fetchChangeLogFailed.format(it.message))
|
||||||
context,
|
return
|
||||||
startDownloadingText.format(module.name),
|
}.ifBlank {
|
||||||
Toast.LENGTH_SHORT
|
showToast(fetchChangeLogFailed.format(module.name))
|
||||||
).show()
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// changelog is not empty, show it and wait for confirm
|
||||||
|
val confirmResult = dialogHost.showConfirm(
|
||||||
|
changelogText,
|
||||||
|
content = changelog,
|
||||||
|
markdown = true,
|
||||||
|
confirm = updateText,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (confirmResult != ConfirmResult.Confirmed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showToast(startDownloadingText.format(module.name))
|
||||||
|
|
||||||
val downloading = downloadingText.format(module.name)
|
val downloading = downloadingText.format(module.name)
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
download(
|
download(
|
||||||
@@ -333,6 +356,8 @@ private fun ModuleList(
|
|||||||
"${module.name}-${updatedModule.second}.zip"
|
"${module.name}-${updatedModule.second}.zip"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}, onClick = {
|
||||||
|
onClickModule(it.id, it.name, it.hasWebUi)
|
||||||
})
|
})
|
||||||
|
|
||||||
// fix last item shadow incomplete in LazyColumn
|
// fix last item shadow incomplete in LazyColumn
|
||||||
@@ -366,9 +391,12 @@ private fun ModuleItem(
|
|||||||
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
|
onUninstall: (ModuleViewModel.ModuleInfo) -> Unit,
|
||||||
onCheckChanged: (Boolean) -> Unit,
|
onCheckChanged: (Boolean) -> Unit,
|
||||||
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
|
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
|
||||||
|
onClick: (ModuleViewModel.ModuleInfo) -> Unit
|
||||||
) {
|
) {
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onClick(module) },
|
||||||
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface)
|
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -474,6 +502,18 @@ private fun ModuleItem(
|
|||||||
text = stringResource(R.string.uninstall),
|
text = stringResource(R.string.uninstall),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (module.hasWebUi) {
|
||||||
|
TextButton(
|
||||||
|
onClick = { onClick(module) },
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
|
||||||
|
fontSize = MaterialTheme.typography.labelMedium.fontSize,
|
||||||
|
text = stringResource(R.string.open),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,7 +532,8 @@ fun ModuleItemPreview() {
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
update = true,
|
update = true,
|
||||||
remove = true,
|
remove = true,
|
||||||
updateJson = ""
|
updateJson = "",
|
||||||
|
hasWebUi = false,
|
||||||
)
|
)
|
||||||
ModuleItem(module, true, "", {}, {}, {})
|
ModuleItem(module, true, "", {}, {}, {}, {})
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.weishu.kernelsu.ui.screen
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -8,7 +9,10 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.BugReport
|
import androidx.compose.material.icons.filled.BugReport
|
||||||
import androidx.compose.material.icons.filled.ContactPage
|
import androidx.compose.material.icons.filled.ContactPage
|
||||||
|
import androidx.compose.material.icons.filled.Fence
|
||||||
import androidx.compose.material.icons.filled.RemoveModerator
|
import androidx.compose.material.icons.filled.RemoveModerator
|
||||||
|
import androidx.compose.material.icons.filled.Update
|
||||||
|
import androidx.compose.material.icons.filled.Upgrade
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
@@ -27,6 +31,7 @@ import me.weishu.kernelsu.R
|
|||||||
import me.weishu.kernelsu.ui.component.AboutDialog
|
import me.weishu.kernelsu.ui.component.AboutDialog
|
||||||
import me.weishu.kernelsu.ui.component.LoadingDialog
|
import me.weishu.kernelsu.ui.component.LoadingDialog
|
||||||
import me.weishu.kernelsu.ui.component.SwitchItem
|
import me.weishu.kernelsu.ui.component.SwitchItem
|
||||||
|
import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination
|
||||||
import me.weishu.kernelsu.ui.util.LocalDialogHost
|
import me.weishu.kernelsu.ui.util.LocalDialogHost
|
||||||
import me.weishu.kernelsu.ui.util.getBugreportFile
|
import me.weishu.kernelsu.ui.util.getBugreportFile
|
||||||
|
|
||||||
@@ -56,6 +61,16 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val dialogHost = LocalDialogHost.current
|
val dialogHost = LocalDialogHost.current
|
||||||
|
|
||||||
|
val profileTemplate = stringResource(id = R.string.settings_profile_template)
|
||||||
|
ListItem(
|
||||||
|
leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) },
|
||||||
|
headlineContent = { Text(profileTemplate) },
|
||||||
|
supportingContent = { Text(stringResource(id = R.string.settings_profile_template_summary)) },
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
navigator.navigate(AppProfileTemplateScreenDestination)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
var umountChecked by rememberSaveable {
|
var umountChecked by rememberSaveable {
|
||||||
mutableStateOf(Natives.isDefaultUmountModules())
|
mutableStateOf(Natives.isDefaultUmountModules())
|
||||||
}
|
}
|
||||||
@@ -70,8 +85,30 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||||
|
var checkUpdate by rememberSaveable {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getBoolean("check_update", true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SwitchItem(
|
||||||
|
icon = Icons.Filled.Update,
|
||||||
|
title = stringResource(id = R.string.settings_check_update),
|
||||||
|
summary = stringResource(id = R.string.settings_check_update_summary),
|
||||||
|
checked = checkUpdate
|
||||||
|
) {
|
||||||
|
prefs.edit().putBoolean("check_update", it).apply()
|
||||||
|
checkUpdate = it
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ListItem(
|
ListItem(
|
||||||
leadingContent = { Icon(Icons.Filled.BugReport, stringResource(id = R.string.send_log)) },
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.BugReport,
|
||||||
|
stringResource(id = R.string.send_log)
|
||||||
|
)
|
||||||
|
},
|
||||||
headlineContent = { Text(stringResource(id = R.string.send_log)) },
|
headlineContent = { Text(stringResource(id = R.string.send_log)) },
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -105,7 +142,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
val about = stringResource(id = R.string.about)
|
val about = stringResource(id = R.string.about)
|
||||||
ListItem(
|
ListItem(
|
||||||
leadingContent = { Icon(Icons.Filled.ContactPage, stringResource(id = R.string.about)) },
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.ContactPage,
|
||||||
|
stringResource(id = R.string.about)
|
||||||
|
)
|
||||||
|
},
|
||||||
headlineContent = { Text(about) },
|
headlineContent = { Text(about) },
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
showAboutDialog.value = true
|
showAboutDialog.value = true
|
||||||
|
|||||||
@@ -0,0 +1,255 @@
|
|||||||
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.ImportExport
|
||||||
|
import androidx.compose.material.icons.filled.Sync
|
||||||
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
|
import com.ramcosta.composedestinations.result.ResultRecipient
|
||||||
|
import com.ramcosta.composedestinations.result.getOr
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.weishu.kernelsu.R
|
||||||
|
import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author weishu
|
||||||
|
* @date 2023/10/20.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
@Destination
|
||||||
|
@Composable
|
||||||
|
fun AppProfileTemplateScreen(
|
||||||
|
navigator: DestinationsNavigator,
|
||||||
|
resultRecipient: ResultRecipient<TemplateEditorScreenDestination, Boolean>
|
||||||
|
) {
|
||||||
|
val viewModel = viewModel<TemplateViewModel>()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
if (viewModel.templateList.isEmpty()) {
|
||||||
|
viewModel.fetchTemplates()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle result from TemplateEditorScreen, refresh if needed
|
||||||
|
resultRecipient.onNavResult { result ->
|
||||||
|
if (result.getOr { false }) {
|
||||||
|
scope.launch { viewModel.fetchTemplates() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
val clipboardManager = LocalClipboardManager.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
val showToast = fun(msg: String) {
|
||||||
|
scope.launch(Dispatchers.Main) {
|
||||||
|
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TopBar(onBack = { navigator.popBackStack() },
|
||||||
|
onSync = {
|
||||||
|
scope.launch { viewModel.fetchTemplates(true) }
|
||||||
|
},
|
||||||
|
onImport = {
|
||||||
|
clipboardManager.getText()?.text?.let {
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
showToast(context.getString(R.string.app_profile_template_import_empty))
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
scope.launch {
|
||||||
|
viewModel.importTemplates(
|
||||||
|
it, {
|
||||||
|
showToast(context.getString(R.string.app_profile_template_import_success))
|
||||||
|
viewModel.fetchTemplates(false)
|
||||||
|
},
|
||||||
|
showToast
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onExport = {
|
||||||
|
scope.launch {
|
||||||
|
viewModel.exportTemplates(
|
||||||
|
{
|
||||||
|
showToast(context.getString(R.string.app_profile_template_export_empty))
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
clipboardManager.setText(AnnotatedString(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
floatingActionButton = {
|
||||||
|
ExtendedFloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
navigator.navigate(
|
||||||
|
TemplateEditorScreenDestination(
|
||||||
|
TemplateViewModel.TemplateInfo(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
icon = { Icon(Icons.Filled.Add, null) },
|
||||||
|
text = { Text(stringResource(id = R.string.app_profile_template_create)) },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { innerPadding ->
|
||||||
|
val refreshState = rememberPullRefreshState(
|
||||||
|
refreshing = viewModel.isRefreshing,
|
||||||
|
onRefresh = { scope.launch { viewModel.fetchTemplates() } },
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.pullRefresh(refreshState)
|
||||||
|
) {
|
||||||
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
|
items(viewModel.templateList, key = { it.id }) { app ->
|
||||||
|
TemplateItem(navigator, app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PullRefreshIndicator(
|
||||||
|
refreshing = viewModel.isRefreshing,
|
||||||
|
state = refreshState,
|
||||||
|
modifier = Modifier.align(Alignment.TopCenter)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun TemplateItem(
|
||||||
|
navigator: DestinationsNavigator,
|
||||||
|
template: TemplateViewModel.TemplateInfo
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable {
|
||||||
|
navigator.navigate(TemplateEditorScreenDestination(template, !template.local))
|
||||||
|
},
|
||||||
|
headlineContent = { Text(template.name) },
|
||||||
|
supportingContent = {
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "${template.id}${if (template.author.isEmpty()) "" else "@${template.author}"}",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
)
|
||||||
|
Text(template.description)
|
||||||
|
FlowRow {
|
||||||
|
LabelText(label = "UID: ${template.uid}")
|
||||||
|
LabelText(label = "GID: ${template.gid}")
|
||||||
|
LabelText(label = template.context)
|
||||||
|
if (template.local) {
|
||||||
|
LabelText(label = "local")
|
||||||
|
} else {
|
||||||
|
LabelText(label = "remote")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun TopBar(
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onSync: () -> Unit = {},
|
||||||
|
onImport: () -> Unit = {},
|
||||||
|
onExport: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(stringResource(R.string.settings_profile_template))
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBack
|
||||||
|
) { Icon(Icons.Filled.ArrowBack, contentDescription = null) }
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(onClick = onSync) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.Sync,
|
||||||
|
contentDescription = stringResource(id = R.string.app_profile_template_sync)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var showDropdown by remember { mutableStateOf(false) }
|
||||||
|
IconButton(onClick = {
|
||||||
|
showDropdown = true
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ImportExport,
|
||||||
|
contentDescription = stringResource(id = R.string.app_profile_import_export)
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenu(expanded = showDropdown, onDismissRequest = {
|
||||||
|
showDropdown = false
|
||||||
|
}) {
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(stringResource(id = R.string.app_profile_import_from_clipboard))
|
||||||
|
}, onClick = {
|
||||||
|
onImport()
|
||||||
|
showDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(stringResource(id = R.string.app_profile_export_to_clipboard))
|
||||||
|
}, onClick = {
|
||||||
|
onExport()
|
||||||
|
showDropdown = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,327 @@
|
|||||||
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.DeleteForever
|
||||||
|
import androidx.compose.material.icons.filled.Save
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.pointer.pointerInteropFilter
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.result.ResultBackNavigator
|
||||||
|
import me.weishu.kernelsu.Natives
|
||||||
|
import me.weishu.kernelsu.R
|
||||||
|
import me.weishu.kernelsu.profile.Capabilities
|
||||||
|
import me.weishu.kernelsu.profile.Groups
|
||||||
|
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
||||||
|
import me.weishu.kernelsu.ui.util.deleteAppProfileTemplate
|
||||||
|
import me.weishu.kernelsu.ui.util.getAppProfileTemplate
|
||||||
|
import me.weishu.kernelsu.ui.util.setAppProfileTemplate
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.toJSON
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author weishu
|
||||||
|
* @date 2023/10/20.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
@Destination
|
||||||
|
@Composable
|
||||||
|
fun TemplateEditorScreen(
|
||||||
|
navigator: ResultBackNavigator<Boolean>,
|
||||||
|
initialTemplate: TemplateViewModel.TemplateInfo,
|
||||||
|
readOnly: Boolean = true,
|
||||||
|
) {
|
||||||
|
|
||||||
|
val isCreation = initialTemplate.id.isBlank()
|
||||||
|
val autoSave = !isCreation
|
||||||
|
|
||||||
|
var template by rememberSaveable {
|
||||||
|
mutableStateOf(initialTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
BackHandler {
|
||||||
|
navigator.navigateBack(result = !readOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
val author =
|
||||||
|
if (initialTemplate.author.isNotEmpty()) "@${initialTemplate.author}" else ""
|
||||||
|
val readOnlyHint = if (readOnly) {
|
||||||
|
" - ${stringResource(id = R.string.app_profile_template_readonly)}"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
val titleSummary = "${initialTemplate.id}$author$readOnlyHint"
|
||||||
|
val saveTemplateFailed = stringResource(id = R.string.app_profile_template_save_failed)
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
TopBar(
|
||||||
|
title = if (isCreation) {
|
||||||
|
stringResource(R.string.app_profile_template_create)
|
||||||
|
} else if (readOnly) {
|
||||||
|
stringResource(R.string.app_profile_template_view)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.app_profile_template_edit)
|
||||||
|
},
|
||||||
|
readOnly = readOnly,
|
||||||
|
summary = titleSummary,
|
||||||
|
onBack = { navigator.navigateBack(result = !readOnly) },
|
||||||
|
onDelete = {
|
||||||
|
if (deleteAppProfileTemplate(template.id)) {
|
||||||
|
navigator.navigateBack(result = true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSave = {
|
||||||
|
if (saveTemplate(template, isCreation)) {
|
||||||
|
navigator.navigateBack(result = true)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, saveTemplateFailed, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.pointerInteropFilter {
|
||||||
|
// disable click and ripple if readOnly
|
||||||
|
readOnly
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (isCreation) {
|
||||||
|
var errorHint by remember {
|
||||||
|
mutableStateOf("")
|
||||||
|
}
|
||||||
|
val idConflictError = stringResource(id = R.string.app_profile_template_id_exist)
|
||||||
|
val idInvalidError = stringResource(id = R.string.app_profile_template_id_invalid)
|
||||||
|
TextEdit(
|
||||||
|
label = stringResource(id = R.string.app_profile_template_id),
|
||||||
|
text = template.id,
|
||||||
|
errorHint = errorHint,
|
||||||
|
isError = errorHint.isNotEmpty()
|
||||||
|
) { value ->
|
||||||
|
errorHint = if (isTemplateExist(value)) {
|
||||||
|
idConflictError
|
||||||
|
} else if (!isValidTemplateId(value)) {
|
||||||
|
idInvalidError
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
template = template.copy(id = value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEdit(
|
||||||
|
label = stringResource(id = R.string.app_profile_template_name),
|
||||||
|
text = template.name
|
||||||
|
) { value ->
|
||||||
|
template.copy(name = value).run {
|
||||||
|
if (autoSave) {
|
||||||
|
if (!saveTemplate(this)) {
|
||||||
|
// failed
|
||||||
|
return@run
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextEdit(
|
||||||
|
label = stringResource(id = R.string.app_profile_template_description),
|
||||||
|
text = template.description
|
||||||
|
) { value ->
|
||||||
|
template.copy(description = value).run {
|
||||||
|
if (autoSave) {
|
||||||
|
if (!saveTemplate(this)) {
|
||||||
|
// failed
|
||||||
|
return@run
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RootProfileConfig(fixedName = true,
|
||||||
|
profile = toNativeProfile(template),
|
||||||
|
onProfileChange = {
|
||||||
|
template.copy(
|
||||||
|
uid = it.uid,
|
||||||
|
gid = it.gid,
|
||||||
|
groups = it.groups,
|
||||||
|
capabilities = it.capabilities,
|
||||||
|
context = it.context,
|
||||||
|
namespace = it.namespace,
|
||||||
|
rules = it.rules.split("\n")
|
||||||
|
).run {
|
||||||
|
if (autoSave) {
|
||||||
|
if (!saveTemplate(this)) {
|
||||||
|
// failed
|
||||||
|
return@run
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template = this
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toNativeProfile(templateInfo: TemplateViewModel.TemplateInfo): Natives.Profile {
|
||||||
|
return Natives.Profile().copy(rootTemplate = templateInfo.id,
|
||||||
|
uid = templateInfo.uid,
|
||||||
|
gid = templateInfo.gid,
|
||||||
|
groups = templateInfo.groups,
|
||||||
|
capabilities = templateInfo.capabilities,
|
||||||
|
context = templateInfo.context,
|
||||||
|
namespace = templateInfo.namespace,
|
||||||
|
rules = templateInfo.rules.joinToString("\n").ifBlank { "" })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isTemplateValid(template: TemplateViewModel.TemplateInfo): Boolean {
|
||||||
|
if (template.id.isBlank()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidTemplateId(template.id)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveTemplate(template: TemplateViewModel.TemplateInfo, isCreation: Boolean = false): Boolean {
|
||||||
|
if (!isTemplateValid(template)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCreation && isTemplateExist(template.id)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val json = template.toJSON()
|
||||||
|
json.put("local", true)
|
||||||
|
return setAppProfileTemplate(template.id, json.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun TopBar(
|
||||||
|
title: String,
|
||||||
|
readOnly: Boolean,
|
||||||
|
summary: String = "",
|
||||||
|
onBack: () -> Unit,
|
||||||
|
onDelete: () -> Unit = {},
|
||||||
|
onSave: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
TopAppBar(title = {
|
||||||
|
Column {
|
||||||
|
Text(title)
|
||||||
|
if (summary.isNotBlank()) {
|
||||||
|
Text(
|
||||||
|
text = summary,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBack
|
||||||
|
) { Icon(Icons.Filled.ArrowBack, contentDescription = null) }
|
||||||
|
}, actions = {
|
||||||
|
if (readOnly) {
|
||||||
|
return@TopAppBar
|
||||||
|
}
|
||||||
|
IconButton(onClick = onDelete) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.DeleteForever,
|
||||||
|
contentDescription = stringResource(id = R.string.app_profile_template_delete)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
IconButton(onClick = onSave) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Save,
|
||||||
|
contentDescription = stringResource(id = R.string.app_profile_template_save)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun TextEdit(
|
||||||
|
label: String,
|
||||||
|
text: String,
|
||||||
|
errorHint: String = "",
|
||||||
|
isError: Boolean = false,
|
||||||
|
onValueChange: (String) -> Unit = {}
|
||||||
|
) {
|
||||||
|
ListItem(headlineContent = {
|
||||||
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
OutlinedTextField(
|
||||||
|
value = text,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
label = { Text(label) },
|
||||||
|
suffix =
|
||||||
|
if (errorHint.isNotBlank()) {
|
||||||
|
{
|
||||||
|
Text(
|
||||||
|
text = if (isError) errorHint else "",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
isError = isError,
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Next
|
||||||
|
),
|
||||||
|
keyboardActions = KeyboardActions(onDone = {
|
||||||
|
keyboardController?.hide()
|
||||||
|
}),
|
||||||
|
onValueChange = onValueChange
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isValidTemplateId(id: String): Boolean {
|
||||||
|
return Regex("""^([A-Za-z]{1}[A-Za-z\d_]*\.)*[A-Za-z][A-Za-z\d_]*$""").matches(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isTemplateExist(id: String): Boolean {
|
||||||
|
return getAppProfileTemplate(id).isNotBlank()
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebResourceResponse
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.webkit.WebViewAssetLoader
|
||||||
|
import com.google.accompanist.web.AccompanistWebViewClient
|
||||||
|
import com.google.accompanist.web.WebView
|
||||||
|
import com.google.accompanist.web.rememberWebViewState
|
||||||
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
|
import me.weishu.kernelsu.ui.webui.SuFilePathHandler
|
||||||
|
import me.weishu.kernelsu.ui.webui.WebViewInterface
|
||||||
|
import me.weishu.kernelsu.ui.webui.showSystemUI
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
@Destination
|
||||||
|
@Composable
|
||||||
|
fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: String) {
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
DisposableEffect(Unit) {
|
||||||
|
onDispose {
|
||||||
|
if (WebViewInterface.isHideSystemUI && context is Activity) {
|
||||||
|
showSystemUI(context.window)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold { innerPadding ->
|
||||||
|
val webRoot = File("/data/adb/modules/${moduleId}/webroot")
|
||||||
|
val webViewAssetLoader = WebViewAssetLoader.Builder()
|
||||||
|
.setDomain("mui.kernelsu.org")
|
||||||
|
.addPathHandler("/",
|
||||||
|
SuFilePathHandler(context, webRoot)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val webViewClient = object : AccompanistWebViewClient() {
|
||||||
|
override fun shouldInterceptRequest(
|
||||||
|
view: WebView,
|
||||||
|
request: WebResourceRequest
|
||||||
|
): WebResourceResponse? {
|
||||||
|
return webViewAssetLoader.shouldInterceptRequest(request.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebView(
|
||||||
|
state = rememberWebViewState(url = "https://mui.kernelsu.org/index.html"),
|
||||||
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(innerPadding),
|
||||||
|
client = webViewClient,
|
||||||
|
factory = { context ->
|
||||||
|
WebView(context).apply {
|
||||||
|
settings.javaScriptEnabled = true
|
||||||
|
settings.domStorageEnabled = true
|
||||||
|
settings.allowFileAccess = false
|
||||||
|
addJavascriptInterface(WebViewInterface(context, this), "ksu")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,17 +25,24 @@ private fun getKsuDaemonPath(): String {
|
|||||||
|
|
||||||
object KsuCli {
|
object KsuCli {
|
||||||
val SHELL: Shell = createRootShell()
|
val SHELL: Shell = createRootShell()
|
||||||
|
val GLOBAL_MNT_SHELL: Shell = createRootShell(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRootShell(): Shell {
|
fun getRootShell(globalMnt: Boolean = false): Shell {
|
||||||
return KsuCli.SHELL
|
return if (globalMnt) KsuCli.GLOBAL_MNT_SHELL else {
|
||||||
|
KsuCli.SHELL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createRootShell(): Shell {
|
fun createRootShell(globalMnt: Boolean = false): Shell {
|
||||||
Shell.enableVerboseLogging = BuildConfig.DEBUG
|
Shell.enableVerboseLogging = BuildConfig.DEBUG
|
||||||
val builder = Shell.Builder.create()
|
val builder = Shell.Builder.create()
|
||||||
return try {
|
return try {
|
||||||
builder.build(getKsuDaemonPath(), "debug", "su")
|
if (globalMnt) {
|
||||||
|
builder.build(getKsuDaemonPath(), "debug", "su", "-g")
|
||||||
|
} else {
|
||||||
|
builder.build(getKsuDaemonPath(), "debug", "su")
|
||||||
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Log.e(TAG, "su failed: ", e)
|
Log.e(TAG, "su failed: ", e)
|
||||||
builder.build("sh")
|
builder.build("sh")
|
||||||
@@ -91,7 +98,12 @@ fun uninstallModule(id: String): Boolean {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun installModule(uri: Uri, onFinish: (Boolean) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit): Boolean {
|
fun installModule(
|
||||||
|
uri: Uri,
|
||||||
|
onFinish: (Boolean) -> Unit,
|
||||||
|
onStdout: (String) -> Unit,
|
||||||
|
onStderr: (String) -> Unit
|
||||||
|
): Boolean {
|
||||||
val resolver = ksuApp.contentResolver
|
val resolver = ksuApp.contentResolver
|
||||||
with(resolver.openInputStream(uri)) {
|
with(resolver.openInputStream(uri)) {
|
||||||
val file = File(ksuApp.cacheDir, "module.zip")
|
val file = File(ksuApp.cacheDir, "module.zip")
|
||||||
@@ -100,7 +112,7 @@ fun installModule(uri: Uri, onFinish: (Boolean) -> Unit, onStdout: (String) -> U
|
|||||||
}
|
}
|
||||||
val cmd = "module install ${file.absolutePath}"
|
val cmd = "module install ${file.absolutePath}"
|
||||||
|
|
||||||
val shell = getRootShell()
|
val shell = createRootShell()
|
||||||
|
|
||||||
val stdoutCallback: CallbackList<String?> = object : CallbackList<String?>() {
|
val stdoutCallback: CallbackList<String?> = object : CallbackList<String?>() {
|
||||||
override fun onAddElement(s: String?) {
|
override fun onAddElement(s: String?) {
|
||||||
@@ -115,7 +127,8 @@ fun installModule(uri: Uri, onFinish: (Boolean) -> Unit, onStdout: (String) -> U
|
|||||||
}
|
}
|
||||||
|
|
||||||
val result =
|
val result =
|
||||||
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback).exec()
|
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(stdoutCallback, stderrCallback)
|
||||||
|
.exec()
|
||||||
Log.i("KernelSU", "install module $uri result: $result")
|
Log.i("KernelSU", "install module $uri result: $result")
|
||||||
|
|
||||||
file.delete()
|
file.delete()
|
||||||
@@ -134,6 +147,11 @@ fun reboot(reason: String = "") {
|
|||||||
ShellUtils.fastCmd(shell, "/system/bin/svc power reboot $reason || /system/bin/reboot $reason")
|
ShellUtils.fastCmd(shell, "/system/bin/svc power reboot $reason || /system/bin/reboot $reason")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun rootAvailable(): Boolean {
|
||||||
|
val shell = getRootShell()
|
||||||
|
return shell.isRoot
|
||||||
|
}
|
||||||
|
|
||||||
fun overlayFsAvailable(): Boolean {
|
fun overlayFsAvailable(): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
// check /proc/filesystems
|
// check /proc/filesystems
|
||||||
@@ -141,8 +159,8 @@ fun overlayFsAvailable(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasMagisk(): Boolean {
|
fun hasMagisk(): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell(true)
|
||||||
val result = shell.newJob().add("nsenter --mount=/proc/1/ns/mnt which magisk").exec()
|
val result = shell.newJob().add("which magisk").exec()
|
||||||
Log.i(TAG, "has magisk: ${result.isSuccess}")
|
Log.i(TAG, "has magisk: ${result.isSuccess}")
|
||||||
return result.isSuccess
|
return result.isSuccess
|
||||||
}
|
}
|
||||||
@@ -153,14 +171,16 @@ fun isSepolicyValid(rules: String?): Boolean {
|
|||||||
}
|
}
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result =
|
val result =
|
||||||
shell.newJob().add("${getKsuDaemonPath()} sepolicy check '$rules'").to(ArrayList(), null).exec()
|
shell.newJob().add("${getKsuDaemonPath()} sepolicy check '$rules'").to(ArrayList(), null)
|
||||||
|
.exec()
|
||||||
return result.isSuccess
|
return result.isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSepolicy(pkg: String): String {
|
fun getSepolicy(pkg: String): String {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result =
|
val result =
|
||||||
shell.newJob().add("${getKsuDaemonPath()} profile get-sepolicy $pkg").to(ArrayList(), null).exec()
|
shell.newJob().add("${getKsuDaemonPath()} profile get-sepolicy $pkg").to(ArrayList(), null)
|
||||||
|
.exec()
|
||||||
Log.i(TAG, "code: ${result.code}, out: ${result.out}, err: ${result.err}")
|
Log.i(TAG, "code: ${result.code}, out: ${result.out}, err: ${result.err}")
|
||||||
return result.out.joinToString("\n")
|
return result.out.joinToString("\n")
|
||||||
}
|
}
|
||||||
@@ -168,11 +188,39 @@ fun getSepolicy(pkg: String): String {
|
|||||||
fun setSepolicy(pkg: String, rules: String): Boolean {
|
fun setSepolicy(pkg: String, rules: String): Boolean {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result =
|
val result =
|
||||||
shell.newJob().add("${getKsuDaemonPath()} profile set-sepolicy $pkg '$rules'").to(ArrayList(), null).exec()
|
shell.newJob().add("${getKsuDaemonPath()} profile set-sepolicy $pkg '$rules'")
|
||||||
|
.to(ArrayList(), null).exec()
|
||||||
Log.i(TAG, "set sepolicy result: ${result.code}")
|
Log.i(TAG, "set sepolicy result: ${result.code}")
|
||||||
return result.isSuccess
|
return result.isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun listAppProfileTemplates(): List<String> {
|
||||||
|
val shell = getRootShell()
|
||||||
|
return shell.newJob().add("${getKsuDaemonPath()} profile list-templates").to(ArrayList(), null)
|
||||||
|
.exec().out
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAppProfileTemplate(id: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
return shell.newJob().add("${getKsuDaemonPath()} profile get-template '${id}'")
|
||||||
|
.to(ArrayList(), null)
|
||||||
|
.exec().out.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAppProfileTemplate(id: String, template: String): Boolean {
|
||||||
|
val shell = getRootShell()
|
||||||
|
return shell.newJob().add("${getKsuDaemonPath()} profile set-template '${id}' '${template}'")
|
||||||
|
.to(ArrayList(), null)
|
||||||
|
.exec().isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteAppProfileTemplate(id: String): Boolean {
|
||||||
|
val shell = getRootShell()
|
||||||
|
return shell.newJob().add("${getKsuDaemonPath()} profile delete-template '${id}'")
|
||||||
|
.to(ArrayList(), null)
|
||||||
|
.exec().isSuccess
|
||||||
|
}
|
||||||
|
|
||||||
fun forceStopApp(packageName: String) {
|
fun forceStopApp(packageName: String) {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result = shell.newJob().add("am force-stop $packageName").exec()
|
val result = shell.newJob().add("am force-stop $packageName").exec()
|
||||||
@@ -182,7 +230,8 @@ fun forceStopApp(packageName: String) {
|
|||||||
fun launchApp(packageName: String) {
|
fun launchApp(packageName: String) {
|
||||||
|
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
val result = shell.newJob().add("monkey -p $packageName -c android.intent.category.LAUNCHER 1").exec()
|
val result =
|
||||||
|
shell.newJob().add("monkey -p $packageName -c android.intent.category.LAUNCHER 1").exec()
|
||||||
Log.i(TAG, "launch $packageName result: $result")
|
Log.i(TAG, "launch $packageName result: $result")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,17 @@ fun getBugreportFile(context: Context): File {
|
|||||||
val bootlogFile = File(bugreportDir, "bootlog.tar.gz")
|
val bootlogFile = File(bugreportDir, "bootlog.tar.gz")
|
||||||
val mountsFile = File(bugreportDir, "mounts.txt")
|
val mountsFile = File(bugreportDir, "mounts.txt")
|
||||||
val fileSystemsFile = File(bugreportDir, "filesystems.txt")
|
val fileSystemsFile = File(bugreportDir, "filesystems.txt")
|
||||||
val ksuFileTree = File(bugreportDir, "ksu_tree.txt")
|
val adbFileTree = File(bugreportDir, "adb_tree.txt")
|
||||||
|
val adbFileDetails = File(bugreportDir, "adb_details.txt")
|
||||||
|
val ksuFileSize = File(bugreportDir, "ksu_size.txt")
|
||||||
val appListFile = File(bugreportDir, "packages.txt")
|
val appListFile = File(bugreportDir, "packages.txt")
|
||||||
val propFile = File(bugreportDir, "props.txt")
|
val propFile = File(bugreportDir, "props.txt")
|
||||||
val allowListFile = File(bugreportDir, "allowlist.bin")
|
val allowListFile = File(bugreportDir, "allowlist.bin")
|
||||||
|
val procModules = File(bugreportDir, "proc_modules.txt")
|
||||||
|
val bootConfig = File(bugreportDir, "boot_config.txt")
|
||||||
|
val kernelConfig = File(bugreportDir, "defconfig.gz")
|
||||||
|
|
||||||
val shell = getRootShell()
|
val shell = getRootShell(true)
|
||||||
|
|
||||||
shell.newJob().add("dmesg > ${dmesgFile.absolutePath}").exec()
|
shell.newJob().add("dmesg > ${dmesgFile.absolutePath}").exec()
|
||||||
shell.newJob().add("logcat -d > ${logcatFile.absolutePath}").exec()
|
shell.newJob().add("logcat -d > ${logcatFile.absolutePath}").exec()
|
||||||
@@ -43,12 +48,17 @@ fun getBugreportFile(context: Context): File {
|
|||||||
|
|
||||||
shell.newJob().add("cat /proc/1/mountinfo > ${mountsFile.absolutePath}").exec()
|
shell.newJob().add("cat /proc/1/mountinfo > ${mountsFile.absolutePath}").exec()
|
||||||
shell.newJob().add("cat /proc/filesystems > ${fileSystemsFile.absolutePath}").exec()
|
shell.newJob().add("cat /proc/filesystems > ${fileSystemsFile.absolutePath}").exec()
|
||||||
shell.newJob().add("ls -alRZ /data/adb > ${ksuFileTree.absolutePath}").exec()
|
shell.newJob().add("busybox tree /data/adb > ${adbFileTree.absolutePath}").exec()
|
||||||
|
shell.newJob().add("ls -alRZ /data/adb > ${adbFileDetails.absolutePath}").exec()
|
||||||
|
shell.newJob().add("du -sh /data/adb/ksu/* > ${ksuFileSize.absolutePath}").exec()
|
||||||
shell.newJob().add("cp /data/system/packages.list ${appListFile.absolutePath}").exec()
|
shell.newJob().add("cp /data/system/packages.list ${appListFile.absolutePath}").exec()
|
||||||
shell.newJob().add("getprop > ${propFile.absolutePath}").exec()
|
shell.newJob().add("getprop > ${propFile.absolutePath}").exec()
|
||||||
shell.newJob().add("cp /data/adb/ksu/.allowlist ${allowListFile.absolutePath}").exec()
|
shell.newJob().add("cp /data/adb/ksu/.allowlist ${allowListFile.absolutePath}").exec()
|
||||||
|
shell.newJob().add("cp /proc/modules ${procModules.absolutePath}").exec()
|
||||||
|
shell.newJob().add("cp /proc/bootconfig ${bootConfig.absolutePath}").exec()
|
||||||
|
shell.newJob().add("cp /proc/config.gz ${kernelConfig.absolutePath}").exec()
|
||||||
|
|
||||||
val selinux = ShellUtils.fastCmd(shell, "getenforce");
|
val selinux = ShellUtils.fastCmd(shell, "getenforce")
|
||||||
|
|
||||||
// basic information
|
// basic information
|
||||||
val buildInfo = File(bugreportDir, "basic.txt")
|
val buildInfo = File(bugreportDir, "basic.txt")
|
||||||
@@ -68,7 +78,7 @@ fun getBugreportFile(context: Context): File {
|
|||||||
val uname = Os.uname()
|
val uname = Os.uname()
|
||||||
pw.println("KernelRelease: ${uname.release}")
|
pw.println("KernelRelease: ${uname.release}")
|
||||||
pw.println("KernelVersion: ${uname.version}")
|
pw.println("KernelVersion: ${uname.version}")
|
||||||
pw.println("Mahcine: ${uname.machine}")
|
pw.println("Machine: ${uname.machine}")
|
||||||
pw.println("Nodename: ${uname.nodename}")
|
pw.println("Nodename: ${uname.nodename}")
|
||||||
pw.println("Sysname: ${uname.sysname}")
|
pw.println("Sysname: ${uname.sysname}")
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class ModuleViewModel : ViewModel() {
|
|||||||
val update: Boolean,
|
val update: Boolean,
|
||||||
val remove: Boolean,
|
val remove: Boolean,
|
||||||
val updateJson: String,
|
val updateJson: String,
|
||||||
|
val hasWebUi: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class ModuleUpdateInfo(
|
data class ModuleUpdateInfo(
|
||||||
@@ -96,7 +97,8 @@ class ModuleViewModel : ViewModel() {
|
|||||||
obj.getBoolean("enabled"),
|
obj.getBoolean("enabled"),
|
||||||
obj.getBoolean("update"),
|
obj.getBoolean("update"),
|
||||||
obj.getBoolean("remove"),
|
obj.getBoolean("remove"),
|
||||||
obj.optString("updateJson")
|
obj.optString("updateJson"),
|
||||||
|
obj.optBoolean("web")
|
||||||
)
|
)
|
||||||
}.toList()
|
}.toList()
|
||||||
isNeedRefresh = false
|
isNeedRefresh = false
|
||||||
|
|||||||
@@ -0,0 +1,314 @@
|
|||||||
|
package me.weishu.kernelsu.ui.viewmodel
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import me.weishu.kernelsu.Natives
|
||||||
|
import me.weishu.kernelsu.profile.Capabilities
|
||||||
|
import me.weishu.kernelsu.profile.Groups
|
||||||
|
import me.weishu.kernelsu.ui.util.getAppProfileTemplate
|
||||||
|
import me.weishu.kernelsu.ui.util.listAppProfileTemplates
|
||||||
|
import me.weishu.kernelsu.ui.util.setAppProfileTemplate
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.text.Collator
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author weishu
|
||||||
|
* @date 2023/10/20.
|
||||||
|
*/
|
||||||
|
const val TEMPLATE_INDEX_URL = "https://kernelsu.org/templates/index.json"
|
||||||
|
const val TEMPLATE_URL = "https://kernelsu.org/templates/%s"
|
||||||
|
|
||||||
|
const val TAG = "TemplateViewModel"
|
||||||
|
|
||||||
|
class TemplateViewModel : ViewModel() {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private var templates by mutableStateOf<List<TemplateInfo>>(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class TemplateInfo(
|
||||||
|
val id: String = "",
|
||||||
|
val name: String = "",
|
||||||
|
val description: String = "",
|
||||||
|
val author: String = "",
|
||||||
|
val local: Boolean = true,
|
||||||
|
|
||||||
|
val namespace: Int = Natives.Profile.Namespace.INHERITED.ordinal,
|
||||||
|
val uid: Int = Natives.ROOT_UID,
|
||||||
|
val gid: Int = Natives.ROOT_GID,
|
||||||
|
val groups: List<Int> = mutableListOf(),
|
||||||
|
val capabilities: List<Int> = mutableListOf(),
|
||||||
|
val context: String = Natives.KERNEL_SU_DOMAIN,
|
||||||
|
val rules: List<String> = mutableListOf(),
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
var isRefreshing by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
|
||||||
|
val templateList by derivedStateOf {
|
||||||
|
val comparator = compareBy(TemplateInfo::local).reversed().then(
|
||||||
|
compareBy(
|
||||||
|
Collator.getInstance(Locale.getDefault()), TemplateInfo::id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
templates.sortedWith(comparator).apply {
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun fetchTemplates(sync: Boolean = false) {
|
||||||
|
isRefreshing = true
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val localTemplateIds = listAppProfileTemplates()
|
||||||
|
Log.i(TAG, "localTemplateIds: $localTemplateIds")
|
||||||
|
if (localTemplateIds.isEmpty() || sync) {
|
||||||
|
// if no templates, fetch remote templates
|
||||||
|
fetchRemoteTemplates()
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch templates again
|
||||||
|
templates = listAppProfileTemplates().mapNotNull(::getTemplateInfoById)
|
||||||
|
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun importTemplates(
|
||||||
|
templates: String,
|
||||||
|
onSuccess: suspend () -> Unit,
|
||||||
|
onFailure: suspend (String) -> Unit
|
||||||
|
) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
runCatching {
|
||||||
|
JSONArray(templates)
|
||||||
|
}.getOrElse {
|
||||||
|
runCatching {
|
||||||
|
val json = JSONObject(templates)
|
||||||
|
JSONArray().apply { put(json) }
|
||||||
|
}.getOrElse {
|
||||||
|
onFailure("invalid templates: $templates")
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
0.until(it.length()).forEach { i ->
|
||||||
|
runCatching {
|
||||||
|
val template = it.getJSONObject(i)
|
||||||
|
val id = template.getString("id")
|
||||||
|
template.put("local", true)
|
||||||
|
setAppProfileTemplate(id, template.toString())
|
||||||
|
}.onFailure { e ->
|
||||||
|
Log.e(TAG, "ignore invalid template: $it", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun exportTemplates(onTemplateEmpty: () -> Unit, callback: (String) -> Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val templates = listAppProfileTemplates().mapNotNull(::getTemplateInfoById).filter {
|
||||||
|
it.local
|
||||||
|
}
|
||||||
|
templates.ifEmpty {
|
||||||
|
onTemplateEmpty()
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
JSONArray(templates.map {
|
||||||
|
it.toJSON()
|
||||||
|
}).toString().let(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchRemoteTemplates() {
|
||||||
|
runCatching {
|
||||||
|
OkHttpClient().newCall(
|
||||||
|
Request.Builder().url(TEMPLATE_INDEX_URL).build()
|
||||||
|
).execute().use { response ->
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val remoteTemplateIds = JSONArray(response.body!!.string())
|
||||||
|
Log.i(TAG, "fetchRemoteTemplates: $remoteTemplateIds")
|
||||||
|
0.until(remoteTemplateIds.length()).forEach { i ->
|
||||||
|
val id = remoteTemplateIds.getString(i)
|
||||||
|
val templateJson = OkHttpClient().newCall(
|
||||||
|
Request.Builder().url(TEMPLATE_URL.format(id)).build()
|
||||||
|
).runCatching {
|
||||||
|
execute().use { response ->
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
response.body!!.string()
|
||||||
|
}
|
||||||
|
}.getOrNull() ?: return@forEach
|
||||||
|
Log.i(TAG, "template: $templateJson")
|
||||||
|
|
||||||
|
// validate remote template
|
||||||
|
runCatching {
|
||||||
|
val json = JSONObject(templateJson)
|
||||||
|
fromJSON(json)?.let {
|
||||||
|
// force local template
|
||||||
|
json.put("local", false)
|
||||||
|
setAppProfileTemplate(id, json.toString())
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
Log.e(TAG, "ignore invalid template: $it", it)
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.onFailure { Log.e(TAG, "fetchRemoteTemplates: $it", it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun <T, R> JSONArray.mapCatching(
|
||||||
|
transform: (T) -> R, onFail: (Throwable) -> Unit
|
||||||
|
): List<R> {
|
||||||
|
return List(length()) { i -> get(i) as T }.mapNotNull { element ->
|
||||||
|
runCatching {
|
||||||
|
transform(element)
|
||||||
|
}.onFailure(onFail).getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : Enum<T>> getEnumOrdinals(
|
||||||
|
jsonArray: JSONArray?, enumClass: Class<T>
|
||||||
|
): List<T> {
|
||||||
|
return jsonArray?.mapCatching<String, T>({ name ->
|
||||||
|
enumValueOf(name.uppercase())
|
||||||
|
}, {
|
||||||
|
Log.e(TAG, "ignore invalid enum ${enumClass.simpleName}: $it", it)
|
||||||
|
}).orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTemplateInfoById(id: String): TemplateViewModel.TemplateInfo? {
|
||||||
|
return runCatching {
|
||||||
|
fromJSON(JSONObject(getAppProfileTemplate(id)))
|
||||||
|
}.onFailure {
|
||||||
|
Log.e(TAG, "ignore invalid template: $it", it)
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLocaleString(json: JSONObject, key: String): String {
|
||||||
|
val fallback = json.getString(key)
|
||||||
|
val locale = Locale.getDefault()
|
||||||
|
val localeKey = "${locale.language}_${locale.country}"
|
||||||
|
json.optJSONObject("locales")?.let {
|
||||||
|
it.optJSONObject(localeKey)?.let { json->
|
||||||
|
return json.optString(key, fallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fromJSON(templateJson: JSONObject): TemplateViewModel.TemplateInfo? {
|
||||||
|
return runCatching {
|
||||||
|
val groupsJsonArray = templateJson.optJSONArray("groups")
|
||||||
|
val capabilitiesJsonArray = templateJson.optJSONArray("capabilities")
|
||||||
|
val context = templateJson.optString("context").takeIf { it.isNotEmpty() }
|
||||||
|
?: Natives.KERNEL_SU_DOMAIN;
|
||||||
|
val namespace = templateJson.optString("namespace").takeIf { it.isNotEmpty() }
|
||||||
|
?: Natives.Profile.Namespace.INHERITED.name
|
||||||
|
|
||||||
|
val rulesJsonArray = templateJson.optJSONArray("rules")
|
||||||
|
val templateInfo = TemplateViewModel.TemplateInfo(
|
||||||
|
id = templateJson.getString("id"),
|
||||||
|
name = getLocaleString(templateJson, "name"),
|
||||||
|
description = getLocaleString(templateJson, "description"),
|
||||||
|
author = templateJson.optString("author"),
|
||||||
|
local = templateJson.optBoolean("local"),
|
||||||
|
namespace = Natives.Profile.Namespace.valueOf(
|
||||||
|
namespace.uppercase()
|
||||||
|
).ordinal,
|
||||||
|
uid = templateJson.optInt("uid", Natives.ROOT_UID),
|
||||||
|
gid = templateJson.optInt("gid", Natives.ROOT_GID),
|
||||||
|
groups = getEnumOrdinals(groupsJsonArray, Groups::class.java).map { it.gid },
|
||||||
|
capabilities = getEnumOrdinals(
|
||||||
|
capabilitiesJsonArray, Capabilities::class.java
|
||||||
|
).map { it.cap },
|
||||||
|
context = context,
|
||||||
|
rules = rulesJsonArray?.mapCatching<String, String>({ it }, {
|
||||||
|
Log.e(TAG, "ignore invalid rule: $it", it)
|
||||||
|
}).orEmpty()
|
||||||
|
)
|
||||||
|
templateInfo
|
||||||
|
}.onFailure {
|
||||||
|
Log.e(TAG, "ignore invalid template: $it", it)
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TemplateViewModel.TemplateInfo.toJSON(): JSONObject {
|
||||||
|
val template = this
|
||||||
|
return JSONObject().apply {
|
||||||
|
|
||||||
|
put("id", template.id)
|
||||||
|
put("name", template.name.ifBlank { template.id })
|
||||||
|
put("description", template.description.ifBlank { template.id })
|
||||||
|
if (template.author.isNotEmpty()) {
|
||||||
|
put("author", template.author)
|
||||||
|
}
|
||||||
|
put("namespace", Natives.Profile.Namespace.values()[template.namespace].name)
|
||||||
|
put("uid", template.uid)
|
||||||
|
put("gid", template.gid)
|
||||||
|
|
||||||
|
if (template.groups.isNotEmpty()) {
|
||||||
|
put("groups", JSONArray(
|
||||||
|
Groups.values().filter {
|
||||||
|
template.groups.contains(it.gid)
|
||||||
|
}.map {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.capabilities.isNotEmpty()) {
|
||||||
|
put("capabilities", JSONArray(
|
||||||
|
Capabilities.values().filter {
|
||||||
|
template.capabilities.contains(it.cap)
|
||||||
|
}.map {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.context.isNotEmpty()) {
|
||||||
|
put("context", template.context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.rules.isNotEmpty()) {
|
||||||
|
put("rules", JSONArray(template.rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
fun generateTemplates() {
|
||||||
|
val templateJson = JSONObject()
|
||||||
|
templateJson.put("id", "com.example")
|
||||||
|
templateJson.put("name", "Example")
|
||||||
|
templateJson.put("description", "This is an example template")
|
||||||
|
templateJson.put("local", true)
|
||||||
|
templateJson.put("namespace", Natives.Profile.Namespace.INHERITED.name)
|
||||||
|
templateJson.put("uid", 0)
|
||||||
|
templateJson.put("gid", 0)
|
||||||
|
|
||||||
|
templateJson.put("groups", JSONArray().apply { put(Groups.INET.name) })
|
||||||
|
templateJson.put("capabilities", JSONArray().apply { put(Capabilities.CAP_NET_RAW.name) })
|
||||||
|
templateJson.put("context", "u:r:su:s0")
|
||||||
|
Log.i(TAG, "$templateJson")
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.weishu.kernelsu.ui.webui;
|
||||||
|
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
class MimeUtil {
|
||||||
|
|
||||||
|
public static String getMimeFromFileName(String fileName) {
|
||||||
|
if (fileName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copying the logic and mapping that Chromium follows.
|
||||||
|
// First we check against the OS (this is a limited list by default)
|
||||||
|
// but app developers can extend this.
|
||||||
|
// We then check against a list of hardcoded mime types above if the
|
||||||
|
// OS didn't provide a result.
|
||||||
|
String mimeType = URLConnection.guessContentTypeFromName(fileName);
|
||||||
|
|
||||||
|
if (mimeType != null) {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return guessHardcodedMime(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should keep this map in sync with the lists under
|
||||||
|
// //net/base/mime_util.cc in Chromium.
|
||||||
|
// A bunch of the mime types don't really apply to Android land
|
||||||
|
// like word docs so feel free to filter out where necessary.
|
||||||
|
private static String guessHardcodedMime(String fileName) {
|
||||||
|
int finalFullStop = fileName.lastIndexOf('.');
|
||||||
|
if (finalFullStop == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String extension = fileName.substring(finalFullStop + 1).toLowerCase();
|
||||||
|
|
||||||
|
switch (extension) {
|
||||||
|
case "webm":
|
||||||
|
return "video/webm";
|
||||||
|
case "mpeg":
|
||||||
|
case "mpg":
|
||||||
|
return "video/mpeg";
|
||||||
|
case "mp3":
|
||||||
|
return "audio/mpeg";
|
||||||
|
case "wasm":
|
||||||
|
return "application/wasm";
|
||||||
|
case "xhtml":
|
||||||
|
case "xht":
|
||||||
|
case "xhtm":
|
||||||
|
return "application/xhtml+xml";
|
||||||
|
case "flac":
|
||||||
|
return "audio/flac";
|
||||||
|
case "ogg":
|
||||||
|
case "oga":
|
||||||
|
case "opus":
|
||||||
|
return "audio/ogg";
|
||||||
|
case "wav":
|
||||||
|
return "audio/wav";
|
||||||
|
case "m4a":
|
||||||
|
return "audio/x-m4a";
|
||||||
|
case "gif":
|
||||||
|
return "image/gif";
|
||||||
|
case "jpeg":
|
||||||
|
case "jpg":
|
||||||
|
case "jfif":
|
||||||
|
case "pjpeg":
|
||||||
|
case "pjp":
|
||||||
|
return "image/jpeg";
|
||||||
|
case "png":
|
||||||
|
return "image/png";
|
||||||
|
case "apng":
|
||||||
|
return "image/apng";
|
||||||
|
case "svg":
|
||||||
|
case "svgz":
|
||||||
|
return "image/svg+xml";
|
||||||
|
case "webp":
|
||||||
|
return "image/webp";
|
||||||
|
case "mht":
|
||||||
|
case "mhtml":
|
||||||
|
return "multipart/related";
|
||||||
|
case "css":
|
||||||
|
return "text/css";
|
||||||
|
case "html":
|
||||||
|
case "htm":
|
||||||
|
case "shtml":
|
||||||
|
case "shtm":
|
||||||
|
case "ehtml":
|
||||||
|
return "text/html";
|
||||||
|
case "js":
|
||||||
|
case "mjs":
|
||||||
|
return "application/javascript";
|
||||||
|
case "xml":
|
||||||
|
return "text/xml";
|
||||||
|
case "mp4":
|
||||||
|
case "m4v":
|
||||||
|
return "video/mp4";
|
||||||
|
case "ogv":
|
||||||
|
case "ogm":
|
||||||
|
return "video/ogg";
|
||||||
|
case "ico":
|
||||||
|
return "image/x-icon";
|
||||||
|
case "woff":
|
||||||
|
return "application/font-woff";
|
||||||
|
case "gz":
|
||||||
|
case "tgz":
|
||||||
|
return "application/gzip";
|
||||||
|
case "json":
|
||||||
|
return "application/json";
|
||||||
|
case "pdf":
|
||||||
|
return "application/pdf";
|
||||||
|
case "zip":
|
||||||
|
return "application/zip";
|
||||||
|
case "bmp":
|
||||||
|
return "image/bmp";
|
||||||
|
case "tiff":
|
||||||
|
case "tif":
|
||||||
|
return "image/tiff";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package me.weishu.kernelsu.ui.webui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.webkit.WebResourceResponse;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
|
import androidx.webkit.WebViewAssetLoader;
|
||||||
|
|
||||||
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
import com.topjohnwu.superuser.io.SuFile;
|
||||||
|
import com.topjohnwu.superuser.io.SuFileInputStream;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import me.weishu.kernelsu.ui.util.KsuCliKt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler class to open files from file system by root access
|
||||||
|
* For more information about android storage please refer to
|
||||||
|
* <a href="https://developer.android.com/guide/topics/data/data-storage">Android Developers
|
||||||
|
* Docs: Data and file storage overview</a>.
|
||||||
|
* <p class="note">
|
||||||
|
* To avoid leaking user or app data to the web, make sure to choose {@code directory}
|
||||||
|
* carefully, and assume any file under this directory could be accessed by any web page subject
|
||||||
|
* to same-origin rules.
|
||||||
|
* <p>
|
||||||
|
* A typical usage would be like:
|
||||||
|
* <pre class="prettyprint">
|
||||||
|
* File publicDir = new File(context.getFilesDir(), "public");
|
||||||
|
* // Host "files/public/" in app's data directory under:
|
||||||
|
* // http://appassets.androidplatform.net/public/...
|
||||||
|
* WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
|
||||||
|
* .addPathHandler("/public/", new InternalStoragePathHandler(context, publicDir))
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class SuFilePathHandler implements WebViewAssetLoader.PathHandler {
|
||||||
|
private static final String TAG = "SuFilePathHandler";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default value to be used as MIME type if guessing MIME type failed.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_MIME_TYPE = "text/plain";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forbidden subdirectories of {@link Context#getDataDir} that cannot be exposed by this
|
||||||
|
* handler. They are forbidden as they often contain sensitive information.
|
||||||
|
* <p class="note">
|
||||||
|
* Note: Any future addition to this list will be considered breaking changes to the API.
|
||||||
|
*/
|
||||||
|
private static final String[] FORBIDDEN_DATA_DIRS =
|
||||||
|
new String[] {"/data/data", "/data/system"};
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final File mDirectory;
|
||||||
|
|
||||||
|
private final Shell mShell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates PathHandler for app's internal storage.
|
||||||
|
* The directory to be exposed must be inside either the application's internal data
|
||||||
|
* directory {@link Context#getDataDir} or cache directory {@link Context#getCacheDir}.
|
||||||
|
* External storage is not supported for security reasons, as other apps with
|
||||||
|
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} may be able to modify the
|
||||||
|
* files.
|
||||||
|
* <p>
|
||||||
|
* Exposing the entire data or cache directory is not permitted, to avoid accidentally
|
||||||
|
* exposing sensitive application files to the web. Certain existing subdirectories of
|
||||||
|
* {@link Context#getDataDir} are also not permitted as they are often sensitive.
|
||||||
|
* These files are ({@code "app_webview/"}, {@code "databases/"}, {@code "lib/"},
|
||||||
|
* {@code "shared_prefs/"} and {@code "code_cache/"}).
|
||||||
|
* <p>
|
||||||
|
* The application should typically use a dedicated subdirectory for the files it intends to
|
||||||
|
* expose and keep them separate from other files.
|
||||||
|
*
|
||||||
|
* @param context {@link Context} that is used to access app's internal storage.
|
||||||
|
* @param directory the absolute path of the exposed app internal storage directory from
|
||||||
|
* which files can be loaded.
|
||||||
|
* @throws IllegalArgumentException if the directory is not allowed.
|
||||||
|
*/
|
||||||
|
public SuFilePathHandler(@NonNull Context context, @NonNull File directory) {
|
||||||
|
try {
|
||||||
|
mDirectory = new File(getCanonicalDirPath(directory));
|
||||||
|
if (!isAllowedInternalStorageDir(context)) {
|
||||||
|
throw new IllegalArgumentException("The given directory \"" + directory
|
||||||
|
+ "\" doesn't exist under an allowed app internal storage directory");
|
||||||
|
}
|
||||||
|
mShell = KsuCliKt.createRootShell(true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Failed to resolve the canonical path for the given directory: "
|
||||||
|
+ directory.getPath(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAllowedInternalStorageDir(@NonNull Context context) throws IOException {
|
||||||
|
String dir = getCanonicalDirPath(mDirectory);
|
||||||
|
|
||||||
|
for (String forbiddenPath : FORBIDDEN_DATA_DIRS) {
|
||||||
|
if (dir.startsWith(forbiddenPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the requested file from the exposed data directory.
|
||||||
|
* <p>
|
||||||
|
* The matched prefix path used shouldn't be a prefix of a real web path. Thus, if the
|
||||||
|
* requested file cannot be found or is outside the mounted directory a
|
||||||
|
* {@link WebResourceResponse} object with a {@code null} {@link InputStream} will be
|
||||||
|
* returned instead of {@code null}. This saves the time of falling back to network and
|
||||||
|
* trying to resolve a path that doesn't exist. A {@link WebResourceResponse} with
|
||||||
|
* {@code null} {@link InputStream} will be received as an HTTP response with status code
|
||||||
|
* {@code 404} and no body.
|
||||||
|
* <p class="note">
|
||||||
|
* The MIME type for the file will be determined from the file's extension using
|
||||||
|
* {@link java.net.URLConnection#guessContentTypeFromName}. Developers should ensure that
|
||||||
|
* files are named using standard file extensions. If the file does not have a
|
||||||
|
* recognised extension, {@code "text/plain"} will be used by default.
|
||||||
|
*
|
||||||
|
* @param path the suffix path to be handled.
|
||||||
|
* @return {@link WebResourceResponse} for the requested file.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@WorkerThread
|
||||||
|
@NonNull
|
||||||
|
public WebResourceResponse handle(@NonNull String path) {
|
||||||
|
try {
|
||||||
|
File file = getCanonicalFileIfChild(mDirectory, path);
|
||||||
|
if (file != null) {
|
||||||
|
InputStream is = openFile(file, mShell);
|
||||||
|
String mimeType = guessMimeType(path);
|
||||||
|
return new WebResourceResponse(mimeType, null, is);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, String.format(
|
||||||
|
"The requested file: %s is outside the mounted directory: %s", path,
|
||||||
|
mDirectory));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Error opening the requested path: " + path, e);
|
||||||
|
}
|
||||||
|
return new WebResourceResponse(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCanonicalDirPath(@NonNull File file) throws IOException {
|
||||||
|
String canonicalPath = file.getCanonicalPath();
|
||||||
|
if (!canonicalPath.endsWith("/")) canonicalPath += "/";
|
||||||
|
return canonicalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getCanonicalFileIfChild(@NonNull File parent, @NonNull String child)
|
||||||
|
throws IOException {
|
||||||
|
String parentCanonicalPath = getCanonicalDirPath(parent);
|
||||||
|
String childCanonicalPath = new File(parent, child).getCanonicalPath();
|
||||||
|
if (childCanonicalPath.startsWith(parentCanonicalPath)) {
|
||||||
|
return new File(childCanonicalPath);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static InputStream handleSvgzStream(@NonNull String path,
|
||||||
|
@NonNull InputStream stream) throws IOException {
|
||||||
|
return path.endsWith(".svgz") ? new GZIPInputStream(stream) : stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream openFile(@NonNull File file, @NonNull Shell shell) throws FileNotFoundException,
|
||||||
|
IOException {
|
||||||
|
SuFile suFile = new SuFile(file.getAbsolutePath());
|
||||||
|
suFile.setShell(shell);
|
||||||
|
InputStream fis = SuFileInputStream.open(suFile);
|
||||||
|
return handleSvgzStream(file.getPath(), fis);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use {@link MimeUtil#getMimeFromFileName} to guess MIME type or return the
|
||||||
|
* {@link #DEFAULT_MIME_TYPE} if it can't guess.
|
||||||
|
*
|
||||||
|
* @param filePath path of the file to guess its MIME type.
|
||||||
|
* @return MIME type guessed from file extension or {@link #DEFAULT_MIME_TYPE}.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String guessMimeType(@NonNull String filePath) {
|
||||||
|
String mimeType = MimeUtil.getMimeFromFileName(filePath);
|
||||||
|
return mimeType == null ? DEFAULT_MIME_TYPE : mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
package me.weishu.kernelsu.ui.webui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.Window
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
import com.topjohnwu.superuser.CallbackList
|
||||||
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
|
import me.weishu.kernelsu.ui.util.createRootShell
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
|
class WebViewInterface(val context: Context, private val webView: WebView) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
var isHideSystemUI: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun exec(cmd: String): String {
|
||||||
|
val shell = createRootShell()
|
||||||
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun exec(cmd: String, callbackFunc: String) {
|
||||||
|
exec(cmd, null, callbackFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processOptions(sb: StringBuilder, options: String?) {
|
||||||
|
val opts = if (options == null) JSONObject() else {
|
||||||
|
JSONObject(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
val cwd = opts.optString("cwd")
|
||||||
|
if (!TextUtils.isEmpty(cwd)) {
|
||||||
|
sb.append("cd ${cwd};")
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.optJSONObject("env")?.let { env ->
|
||||||
|
env.keys().forEach { key ->
|
||||||
|
sb.append("export ${key}=${env.getString(key)};")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun exec(
|
||||||
|
cmd: String,
|
||||||
|
options: String?,
|
||||||
|
callbackFunc: String
|
||||||
|
) {
|
||||||
|
val finalCommand = StringBuilder()
|
||||||
|
processOptions(finalCommand, options)
|
||||||
|
finalCommand.append(cmd)
|
||||||
|
|
||||||
|
val shell = createRootShell()
|
||||||
|
val result = shell.newJob().add(finalCommand.toString()).to(ArrayList(), ArrayList()).exec()
|
||||||
|
val stdout = result.out.joinToString(separator = "\n")
|
||||||
|
val stderr = result.err.joinToString(separator = "\n")
|
||||||
|
|
||||||
|
val jsCode =
|
||||||
|
"javascript: (function() { try { ${callbackFunc}(${result.code}, ${
|
||||||
|
JSONObject.quote(
|
||||||
|
stdout
|
||||||
|
)
|
||||||
|
}, ${JSONObject.quote(stderr)}); } catch(e) { console.error(e); } })();"
|
||||||
|
webView.post {
|
||||||
|
webView.loadUrl(jsCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun spawn(command: String, args: String, options: String?, callbackFunc: String) {
|
||||||
|
val finalCommand = StringBuilder()
|
||||||
|
|
||||||
|
processOptions(finalCommand, options)
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(args)) {
|
||||||
|
finalCommand.append(command).append(" ")
|
||||||
|
JSONArray(args).let { argsArray ->
|
||||||
|
for (i in 0 until argsArray.length()) {
|
||||||
|
finalCommand.append(argsArray.getString(i))
|
||||||
|
finalCommand.append(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finalCommand.append(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
val shell = createRootShell()
|
||||||
|
|
||||||
|
val emitData = fun(name: String, data: String) {
|
||||||
|
val jsCode =
|
||||||
|
"javascript: (function() { try { ${callbackFunc}.${name}.emit('data', ${
|
||||||
|
JSONObject.quote(
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}); } catch(e) { console.error('emitData', e); } })();"
|
||||||
|
webView.post {
|
||||||
|
webView.loadUrl(jsCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val stdout = object : CallbackList<String>() {
|
||||||
|
override fun onAddElement(s: String) {
|
||||||
|
emitData("stdout", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val stderr = object : CallbackList<String>() {
|
||||||
|
override fun onAddElement(s: String) {
|
||||||
|
emitData("stderr", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val future = shell.newJob().add(finalCommand.toString()).to(stdout, stderr).enqueue()
|
||||||
|
val completableFuture = CompletableFuture.supplyAsync {
|
||||||
|
future.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
completableFuture.thenAccept { result ->
|
||||||
|
val emitExitCode =
|
||||||
|
"javascript: (function() { try { ${callbackFunc}.emit('exit', ${result.code}); } catch(e) { console.error(`emitExit error: \${e}`); } })();"
|
||||||
|
webView.post {
|
||||||
|
webView.loadUrl(emitExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.code != 0) {
|
||||||
|
val emitErrCode =
|
||||||
|
"javascript: (function() { try { var err = new Error(); err.exitCode = ${result.code}; err.message = ${
|
||||||
|
JSONObject.quote(
|
||||||
|
result.err.joinToString(
|
||||||
|
"\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};${callbackFunc}.emit('error', err); } catch(e) { console.error('emitErr', e); } })();"
|
||||||
|
webView.post {
|
||||||
|
webView.loadUrl(emitErrCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun toast(msg: String) {
|
||||||
|
webView.post {
|
||||||
|
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun fullScreen(enable: Boolean) {
|
||||||
|
if (context is Activity) {
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
if (enable) {
|
||||||
|
hideSystemUI(context.window)
|
||||||
|
} else {
|
||||||
|
showSystemUI(context.window)
|
||||||
|
}
|
||||||
|
isHideSystemUI = enable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideSystemUI(window: Window) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||||
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
controller.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showSystemUI(window: Window) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, true)
|
||||||
|
WindowInsetsControllerCompat(
|
||||||
|
window,
|
||||||
|
window.decorView
|
||||||
|
).show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<string name="home_click_to_install">إضغط للتثبيت</string>
|
<string name="home_click_to_install">إضغط للتثبيت</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">المستخدمين الخارقين: %d</string>
|
<string name="home_superuser_count">مستخدمين الجذر: %d</string>
|
||||||
<string name="home_module_count">الوحدات: %d</string>
|
<string name="home_module_count">الوحدات: %d</string>
|
||||||
<string name="home_unsupported">غير مدعوم</string>
|
<string name="home_unsupported">غير مدعوم</string>
|
||||||
<string name="home_unsupported_reason">KernelSU يدعم GKI kernels فقط</string>
|
<string name="home_unsupported_reason">KernelSU يدعم GKI kernels فقط</string>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<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="uninstall">إلغاء التثبيت</string>
|
<string name="uninstall">إلغاء التثبيت</string>
|
||||||
<string name="module_install">تثبيت الوحدة</string>
|
<string name="module_install">تثبيت الوحدة</string>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<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>
|
||||||
<string name="module_uninstall_success">تم إلغاء التثبيت %s</string>
|
<string name="module_uninstall_success">تم إلغاء تثبيتها %s</string>
|
||||||
<string name="module_uninstall_failed">فشل إلغاء التثبيت: %s</string>
|
<string name="module_uninstall_failed">فشل إلغاء التثبيت: %s</string>
|
||||||
<string name="module_version">الإصدار</string>
|
<string name="module_version">الإصدار</string>
|
||||||
<string name="module_author">المطور</string>
|
<string name="module_author">المطور</string>
|
||||||
@@ -80,4 +80,30 @@
|
|||||||
<string name="profile_name">اسم الملف الشخصي</string>
|
<string name="profile_name">اسم الملف الشخصي</string>
|
||||||
<string name="require_kernel_version">إصدار KernelSU الحالي %d منخفض جدًا بحيث لا يعمل المدير بشكل صحيح. الرجاء الترقية إلى الإصدار %d أو أعلى!</string>
|
<string name="require_kernel_version">إصدار KernelSU الحالي %d منخفض جدًا بحيث لا يعمل المدير بشكل صحيح. الرجاء الترقية إلى الإصدار %d أو أعلى!</string>
|
||||||
<string name="module_changelog">سجل التغييرات</string>
|
<string name="module_changelog">سجل التغييرات</string>
|
||||||
|
<string name="app_profile_template_import_success">تم الاستيراد بنجاح</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">تصدير إلى الحافظة</string>
|
||||||
|
<string name="app_profile_template_export_empty">لا يمكن العثور على القالب المحلي للتصدير!</string>
|
||||||
|
<string name="app_profile_template_id_exist">معرف القالب موجود بالفعل!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">استيراد من الحافظة</string>
|
||||||
|
<string name="module_changelog_failed">فشل في جلب سجل التغيير: %s</string>
|
||||||
|
<string name="app_profile_template_name">الاسم</string>
|
||||||
|
<string name="app_profile_template_id_invalid">معرف القالب غير صالح</string>
|
||||||
|
<string name="app_profile_template_sync">مزامنة القوالب عبر الإنترنت</string>
|
||||||
|
<string name="app_profile_template_create">إنشاء قالب</string>
|
||||||
|
<string name="app_profile_template_readonly">للقراءة فقط</string>
|
||||||
|
<string name="app_profile_import_export">استيراد / تصدير</string>
|
||||||
|
<string name="app_profile_template_save_failed">فشل في حفظ القالب</string>
|
||||||
|
<string name="app_profile_template_edit">تحرير القالب</string>
|
||||||
|
<string name="app_profile_template_id">المعرف</string>
|
||||||
|
<string name="settings_profile_template">قالب ملف تعريف التطبيق</string>
|
||||||
|
<string name="app_profile_template_description">الوصف</string>
|
||||||
|
<string name="app_profile_template_save">حفظ</string>
|
||||||
|
<string name="settings_profile_template_summary">إدارة القالب المحلي وعبر الإنترنت لملف تعريف التطبيق</string>
|
||||||
|
<string name="app_profile_template_delete">حذف</string>
|
||||||
|
<string name="app_profile_template_import_empty">الحافظة فارغة!</string>
|
||||||
|
<string name="app_profile_template_view">عرض القالب</string>
|
||||||
|
<string name="grant_root_failed">فشل في منح صلاحية الجذر!</string>
|
||||||
|
<string name="open">فتح</string>
|
||||||
|
<string name="settings_check_update_summary">التحقق تلقائيًا من وجود تحديثات عند فتح التطبيق</string>
|
||||||
|
<string name="settings_check_update">التحقق من التحديث</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<string name="selinux_status_permissive">পারমিসিভ</string>
|
<string name="selinux_status_permissive">পারমিসিভ</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="home_working_version">ভারসন: %d</string>
|
<string name="home_working_version">সংস্করণ: %d</string>
|
||||||
<string name="home_superuser_count">সুপার ইউজার: %d</string>
|
<string name="home_superuser_count">সুপার ইউজার: %d</string>
|
||||||
<string name="profile_namespace">নেইম স্পেস মাউন্ট</string>
|
<string name="profile_namespace">নেইম স্পেস মাউন্ট</string>
|
||||||
<string name="profile_namespace_inherited">ইনহেরিটেড</string>
|
<string name="profile_namespace_inherited">ইনহেরিটেড</string>
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
<string name="home_superuser_count">সুপার ইউজার: %d</string>
|
<string name="home_superuser_count">সুপার ইউজার: %d</string>
|
||||||
<string name="home_module_count">মডিউল: %d</string>
|
<string name="home_module_count">মডিউল: %d</string>
|
||||||
<string name="home_unsupported">অসমর্থিত</string>
|
<string name="home_unsupported">অসমর্থিত</string>
|
||||||
<string name="home_unsupported_reason">কার্নেলএসইউ শুধুমাত্র জিকেআই কার্নেল সমর্থন করে</string>
|
<string name="home_unsupported_reason">KernelSU শুধুমাত্র GKI কার্নেল সমর্থন করে</string>
|
||||||
<string name="home_kernel">কার্নেল</string>
|
<string name="home_kernel">কার্নেল</string>
|
||||||
<string name="home_manager_version">ম্যানেজার সংস্করণ</string>
|
<string name="home_manager_version">ম্যানেজার সংস্করণ</string>
|
||||||
<string name="home_fingerprint">ফিঙ্গারপ্রিন্ট</string>
|
<string name="home_fingerprint">ফিঙ্গারপ্রিন্ট</string>
|
||||||
<string name="home_selinux_status">সেলিনাক্স স্ট্যাটাস</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">কার্যকর</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>
|
||||||
@@ -63,4 +63,5 @@
|
|||||||
<string name="profile_namespace_global">গ্লোবাল</string>
|
<string name="profile_namespace_global">গ্লোবাল</string>
|
||||||
<string name="profile_namespace_individual">আলাদাভাবে</string>
|
<string name="profile_namespace_individual">আলাদাভাবে</string>
|
||||||
<string name="profile_umount_modules">আনমাউন্ট মোডিউল</string>
|
<string name="profile_umount_modules">আনমাউন্ট মোডিউল</string>
|
||||||
|
<string name="require_kernel_version">ম্যানেজার সঠিকভাবে কাজ করার জন্য বর্তমান KernelSU সংস্করণ %d খুবই কম। অনুগ্রহ করে %d বা উচ্চতর সংস্করণে আপগ্রেড করুন!</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<string name="selinux_status_permissive">Permissiv</string>
|
<string name="selinux_status_permissive">Permissiv</string>
|
||||||
<string name="home_working">Funktioniert</string>
|
<string name="home_working">Funktioniert</string>
|
||||||
<string name="home_working_version">Version: %d</string>
|
<string name="home_working_version">Version: %d</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">SuperUser</string>
|
||||||
<string name="home_click_to_install">Tippen zum Installieren</string>
|
<string name="home_click_to_install">Tippen zum Installieren</string>
|
||||||
<string name="home_superuser_count">Superuser: %d</string>
|
<string name="home_superuser_count">Superuser: %d</string>
|
||||||
<string name="selinux_status_unknown">Unbekannt</string>
|
<string name="selinux_status_unknown">Unbekannt</string>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<string name="selinux_status_disabled">Deaktiviert</string>
|
<string name="selinux_status_disabled">Deaktiviert</string>
|
||||||
<string name="module_failed_to_enable">Modulaktivierung fehlgeschlagen: %s</string>
|
<string name="module_failed_to_enable">Modulaktivierung fehlgeschlagen: %s</string>
|
||||||
<string name="module_failed_to_disable">Moduldeaktivierung fehlgeschlagen: %s</string>
|
<string name="module_failed_to_disable">Moduldeaktivierung fehlgeschlagen: %s</string>
|
||||||
<string name="module_empty">Kein Modul installiert</string>
|
<string name="module_empty">Keine Module installiert</string>
|
||||||
<string name="module">Modul</string>
|
<string name="module">Modul</string>
|
||||||
<string name="uninstall">Deinstallieren</string>
|
<string name="uninstall">Deinstallieren</string>
|
||||||
<string name="install">Installieren</string>
|
<string name="install">Installieren</string>
|
||||||
@@ -80,4 +80,26 @@
|
|||||||
<string name="module_uninstall_failed">Deinstallation fehlgeschlagen: %s</string>
|
<string name="module_uninstall_failed">Deinstallation fehlgeschlagen: %s</string>
|
||||||
<string name="require_kernel_version">Die aktuelle Kernel-Version %d ist zu alt für diese Manager-Version. Bitte auf Version %d oder höher upgraden!</string>
|
<string name="require_kernel_version">Die aktuelle Kernel-Version %d ist zu alt für diese Manager-Version. Bitte auf Version %d oder höher upgraden!</string>
|
||||||
<string name="module_changelog">Änderungsprotokoll</string>
|
<string name="module_changelog">Änderungsprotokoll</string>
|
||||||
|
<string name="app_profile_template_import_success">erfolgreich importiert!</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">in Zwischenablage exportieren</string>
|
||||||
|
<string name="app_profile_template_export_empty">Kann lokale Vorlage nicht finden!</string>
|
||||||
|
<string name="app_profile_template_id_exist">Vorlagen ID existiert bereits!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">aus Zwischenablage importieren</string>
|
||||||
|
<string name="module_changelog_failed">Konnte Changelog nicht laden: %s</string>
|
||||||
|
<string name="app_profile_template_name">Name</string>
|
||||||
|
<string name="app_profile_template_id_invalid">ungültige Vorlagen id</string>
|
||||||
|
<string name="app_profile_template_sync">Online Vorlagen synchronisieren</string>
|
||||||
|
<string name="app_profile_template_create">Erstelle Vorlage</string>
|
||||||
|
<string name="app_profile_template_readonly">Nur-Lesen</string>
|
||||||
|
<string name="app_profile_import_export">Import/Export</string>
|
||||||
|
<string name="app_profile_template_save_failed">Fehler beim speichern</string>
|
||||||
|
<string name="app_profile_template_edit">Bearbeite Vorlage</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">App Profil Template</string>
|
||||||
|
<string name="app_profile_template_description">Beschreibung</string>
|
||||||
|
<string name="app_profile_template_save">Speichern</string>
|
||||||
|
<string name="settings_profile_template_summary">verwalte lokale und online Profil Vorlagen</string>
|
||||||
|
<string name="app_profile_template_delete">Löschen</string>
|
||||||
|
<string name="app_profile_template_import_empty">Zwischenablage ist leer!</string>
|
||||||
|
<string name="app_profile_template_view">Vorlage ansehen</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -2,22 +2,22 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="home">Inicio</string>
|
<string name="home">Inicio</string>
|
||||||
<string name="home_not_installed">No instalado</string>
|
<string name="home_not_installed">No instalado</string>
|
||||||
<string name="home_click_to_install">Haga clic para instalar</string>
|
<string name="home_click_to_install">Toca para instalar</string>
|
||||||
<string name="home_working">Activo</string>
|
<string name="home_working">Funcionando</string>
|
||||||
<string name="home_working_version">Versión: %d</string>
|
<string name="home_working_version">Versión: %d</string>
|
||||||
<string name="home_superuser_count">Superusuarios: %d</string>
|
<string name="home_superuser_count">Superusuarios: %d</string>
|
||||||
<string name="home_module_count">Módulos: %d</string>
|
<string name="home_module_count">Módulos: %d</string>
|
||||||
<string name="home_unsupported">No soportado</string>
|
<string name="home_unsupported">No soportado</string>
|
||||||
<string name="home_unsupported_reason">Por el momento, KernelSU solo es compatible con kernels genéricos (GKIs)</string>
|
<string name="home_unsupported_reason">Por el momento, KernelSU solo es compatible con kernels genéricos (GKIs)</string>
|
||||||
<string name="home_kernel">Versión del kernel</string>
|
<string name="home_kernel">Versión del kernel</string>
|
||||||
<string name="home_manager_version">Versión del manager</string>
|
<string name="home_manager_version">Versión del gestor</string>
|
||||||
<string name="home_fingerprint">Huella del dispositivo</string>
|
<string name="home_fingerprint">Huella del dispositivo</string>
|
||||||
<string name="home_selinux_status">Estado de SELinux</string>
|
<string name="home_selinux_status">Estado de SELinux</string>
|
||||||
<!-- It may be better to leave SELinux statuses untranslated -->
|
<!-- It may be better to leave SELinux statuses untranslated -->
|
||||||
<string name="selinux_status_disabled">Disabled</string>
|
<string name="selinux_status_disabled">Desactivado</string>
|
||||||
<string name="selinux_status_enforcing">Enforcing</string>
|
<string name="selinux_status_enforcing">Enforcing de SELinux</string>
|
||||||
<string name="selinux_status_permissive">Permissive</string>
|
<string name="selinux_status_permissive">Permisivo</string>
|
||||||
<string name="selinux_status_unknown">Unknown</string>
|
<string name="selinux_status_unknown">Desconocido</string>
|
||||||
<string name="superuser">Superusuario</string>
|
<string name="superuser">Superusuario</string>
|
||||||
<string name="module_failed_to_enable">No se pudo habilitar el módulo \"%s\"</string>
|
<string name="module_failed_to_enable">No se pudo habilitar el módulo \"%s\"</string>
|
||||||
<string name="module_failed_to_disable">No se pudo deshabilitar el módulo \"%s\"</string>
|
<string name="module_failed_to_disable">No se pudo deshabilitar el módulo \"%s\"</string>
|
||||||
@@ -28,36 +28,36 @@
|
|||||||
<string name="install">Instalar</string>
|
<string name="install">Instalar</string>
|
||||||
<string name="reboot">Reiniciar</string>
|
<string name="reboot">Reiniciar</string>
|
||||||
<string name="settings">Ajustes</string>
|
<string name="settings">Ajustes</string>
|
||||||
<string name="reboot_userspace">Reinicio suave</string>
|
<string name="reboot_userspace">Reinicio minimo</string>
|
||||||
<string name="reboot_recovery">Reiniciar en modo recovery</string>
|
<string name="reboot_recovery">Reiniciar en modo de recuperación</string>
|
||||||
<string name="reboot_bootloader">Reiniciar en modo bootloader</string>
|
<string name="reboot_bootloader">Reiniciar en modo de arranque</string>
|
||||||
<string name="reboot_download">Reiniciar en modo download</string>
|
<string name="reboot_download">Reiniciar en modo Download</string>
|
||||||
<string name="reboot_edl">Reiniciar en modo EDL</string>
|
<string name="reboot_edl">Reiniciar en modo EDL</string>
|
||||||
<string name="about">Acerca de</string>
|
<string name="about">Acerca de</string>
|
||||||
<string name="module_uninstall_confirm">¿Estás seguro de que quieres desinstalar el módulo \"%s\"?</string>
|
<string name="module_uninstall_confirm">¿Estás seguro de que quieres desinstalar el módulo \"%s\"?</string>
|
||||||
<string name="module_uninstall_success">\"%s\" desinstalado</string>
|
<string name="module_uninstall_success">\"%s\" esta desinstalado</string>
|
||||||
<string name="module_uninstall_failed">No se pudo desinstalar \"%s\"</string>
|
<string name="module_uninstall_failed">No se pudo desinstalar \"%s\"</string>
|
||||||
<string name="module_version">Versión</string>
|
<string name="module_version">Versión</string>
|
||||||
<string name="module_author">Autor</string>
|
<string name="module_author">Autor</string>
|
||||||
<string name="module_overlay_fs_not_available">El módulo no puede funcionar ya que OverlayFS no está disponible!</string>
|
<string name="module_overlay_fs_not_available">El módulo no puede funcionar ya que OverlayFS no está disponible!</string>
|
||||||
<string name="refresh">Recargar</string>
|
<string name="refresh">Recargar</string>
|
||||||
<string name="show_system_apps">Mostrar apps del sistema</string>
|
<string name="show_system_apps">Mostrar applicaciones del sistema</string>
|
||||||
<string name="hide_system_apps">Ocultar apps del sistema</string>
|
<string name="hide_system_apps">Ocultar applicaciones del sistema</string>
|
||||||
<string name="send_log">Enviar registro</string>
|
<string name="send_log">Enviar registro de informe</string>
|
||||||
<string name="safe_mode">Modo seguro</string>
|
<string name="safe_mode">Modo seguro</string>
|
||||||
<string name="reboot_to_apply">Reiniciar para aplicar cambios</string>
|
<string name="reboot_to_apply">Reinicia para aplicar cambios</string>
|
||||||
<string name="module_magisk_conflict">Se deshabilitaron los módulos ya que entran en conflicto con Magisk!</string>
|
<string name="module_magisk_conflict">Se deshabilitaron los módulos ya que entran en conflicto con los de Magisk!</string>
|
||||||
<string name="home_learn_kernelsu">Descubre KernelSU</string>
|
<string name="home_learn_kernelsu">Aprende KernelSU</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">Descubre cómo instalar KernelSU y utilizar módulos</string>
|
<string name="home_click_to_learn_kernelsu">Descubre cómo instalar KernelSU y utilizar módulos</string>
|
||||||
<string name="home_support_title">Apóyanos</string>
|
<string name="home_support_title">Apóyanos</string>
|
||||||
<string name="home_support_content">KernelSU es y siempre será, libre y de código abierto. De todas formas, puedes mostrarnos tu apoyo mediante una donación.</string>
|
<string name="home_support_content">KernelSU es y siempre será, libre y de código abierto. De todas formas, puedes mostrarnos tu apoyo mediante una donación.</string>
|
||||||
<string name="about_source_code"><![CDATA[Ver código fuente en %1$s<br/>Únete a nuestro canal de %2$s]]></string>
|
<string name="about_source_code">Mirar el código en %1$s<br/>Únete a nuestro canal de %2$s</string>
|
||||||
<string name="profile_default">Predeterminado</string>
|
<string name="profile_default">Predeterminado</string>
|
||||||
<string name="profile_template">Plantilla</string>
|
<string name="profile_template">Plantilla</string>
|
||||||
<string name="profile_custom">Personalizado</string>
|
<string name="profile_custom">Personalizado</string>
|
||||||
<string name="profile_name">Nombre de perfil</string>
|
<string name="profile_name">Nombre de perfil</string>
|
||||||
<string name="profile_namespace">Modo de montaje del espacio de nombres</string>
|
<string name="profile_namespace">Montaje del espacio de nombres</string>
|
||||||
<string name="profile_namespace_inherited">Heredado</string>
|
<string name="profile_namespace_inherited">Heredado</string>
|
||||||
<string name="profile_namespace_global">Global</string>
|
<string name="profile_namespace_global">Global</string>
|
||||||
<string name="profile_namespace_individual">Individual</string>
|
<string name="profile_namespace_individual">Individual</string>
|
||||||
@@ -65,20 +65,42 @@
|
|||||||
<string name="profile_capabilities">Capacidades</string>
|
<string name="profile_capabilities">Capacidades</string>
|
||||||
<string name="profile_selinux_context">Contexto de SELinux</string>
|
<string name="profile_selinux_context">Contexto de SELinux</string>
|
||||||
<string name="profile_umount_modules">Desmontar módulos</string>
|
<string name="profile_umount_modules">Desmontar módulos</string>
|
||||||
<string name="failed_to_update_app_profile">No se pudo actualizar el perfil de la app para %s</string>
|
<string name="failed_to_update_app_profile">No se pudo actualizar el perfil de la applicación para %s</string>
|
||||||
<string name="settings_umount_modules_default">Desmontar módulos por defecto</string>
|
<string name="settings_umount_modules_default">Desmontar módulos por defecto</string>
|
||||||
<string name="settings_umount_modules_default_summary">El valor global predeterminado para \"Desmontar módulos\" en los perfiles de las aplicaciones. Si la habilitas, se desharán todas las modificaciones al sistema hechas por el módulo para las apps que no tengan un perfil establecido.</string>
|
<string name="settings_umount_modules_default_summary">El valor global predeterminado para \"Desmontar módulos\" en los perfiles de las aplicaciones. Si la habilitas, se desharán todas las modificaciones al sistema hechas por el módulo para las applicaciones que no tengan un perfil establecido.</string>
|
||||||
<string name="profile_umount_modules_summary">Si habilitas esta opción, KernelSU podrá restaurar cualquier archivo modificado por los módulos para esta app.</string>
|
<string name="profile_umount_modules_summary">Si habilitas esta opción, KernelSU podrá restaurar cualquier archivo modificado por los módulos para esta app.</string>
|
||||||
<string name="profile_selinux_domain">Dominio</string>
|
<string name="profile_selinux_domain">Dominio</string>
|
||||||
<string name="profile_selinux_rules">Reglas</string>
|
<string name="profile_selinux_rules">Reglas</string>
|
||||||
<string name="module_update">Actualizar</string>
|
<string name="module_update">Actualizar</string>
|
||||||
<string name="module_downloading">Descargando módulo: \"%s\"</string>
|
<string name="module_downloading">Descargando módulo: \"%s\"</string>
|
||||||
<string name="module_start_downloading">Iniciar descarga: %s</string>
|
<string name="module_start_downloading">Iniciar descarga: %s</string>
|
||||||
<string name="new_version_available">Nueva versión: %s está disponible, haga clic para actualizar</string>
|
<string name="new_version_available">Nueva versión: %s está disponible, toque para actualizar</string>
|
||||||
<string name="launch_app">Lanzar Aplicacion</string>
|
<string name="launch_app">Abrir Aplicacion</string>
|
||||||
<string name="force_stop_app">Forzar cierre de la aplicacion</string>
|
<string name="force_stop_app">Forzar cierre de la aplicacion</string>
|
||||||
<string name="restart_app">Reiniciar aplicacion</string>
|
<string name="restart_app">Reiniciar aplicacion</string>
|
||||||
<string name="failed_to_update_sepolicy">Falló al actualizar reglas de SEpolicy por: %s</string>
|
<string name="failed_to_update_sepolicy">Falló al actualizar reglas de SEpolicy por: %s</string>
|
||||||
<string name="require_kernel_version">La versión actual de KernelSU %d es demasiado baja para que el gestor funcione correctamente. ¡Por favor actualiza a la versión %d o superior!</string>
|
<string name="require_kernel_version">La versión actual de KernelSU %d es demasiado baja para que el gestor funcione correctamente. ¡Por favor actualiza a la versión %d o superior!</string>
|
||||||
<string name="module_changelog">Registro de cambios</string>
|
<string name="module_changelog">Registro de cambios</string>
|
||||||
|
<string name="app_profile_template_import_success">Importado con exíto</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exportar a portapapeles</string>
|
||||||
|
<string name="app_profile_template_export_empty">No se puede encontrar plantilla local para exportar!</string>
|
||||||
|
<string name="app_profile_template_id_exist">Ya existe un ID de la plantilla!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importar desde portapapeles</string>
|
||||||
|
<string name="module_changelog_failed">Error en obtener los registros de cambios: %s</string>
|
||||||
|
<string name="app_profile_template_name">Nombre</string>
|
||||||
|
<string name="app_profile_template_id_invalid">ID de la plantilla es invalido</string>
|
||||||
|
<string name="app_profile_template_sync">Sincronizar plantillas en linea</string>
|
||||||
|
<string name="app_profile_template_create">Crear plantilla</string>
|
||||||
|
<string name="app_profile_template_readonly">sololectura</string>
|
||||||
|
<string name="app_profile_import_export">Importar/Exportar</string>
|
||||||
|
<string name="app_profile_template_save_failed">Fallo en guardar plantilla</string>
|
||||||
|
<string name="app_profile_template_edit">Editar plantilla</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">Plantilla del perfil de la aplicacion</string>
|
||||||
|
<string name="app_profile_template_description">Descripción</string>
|
||||||
|
<string name="app_profile_template_save">Guardar</string>
|
||||||
|
<string name="settings_profile_template_summary">Administrar las plantillas locales y de en linea del perfil de la aplicacion</string>
|
||||||
|
<string name="app_profile_template_delete">Eliminar</string>
|
||||||
|
<string name="app_profile_template_import_empty">El portapapeles esta vacio!</string>
|
||||||
|
<string name="app_profile_template_view">Ver plantilla</string>
|
||||||
</resources>
|
</resources>
|
||||||
105
manager/app/src/main/res/values-et/strings.xml
Normal file
105
manager/app/src/main/res/values-et/strings.xml
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="home_working">Töötamine</string>
|
||||||
|
<string name="home_working_version">Versioon: %d</string>
|
||||||
|
<string name="home_module_count">Mooduleid: %d</string>
|
||||||
|
<string name="home_kernel">Tuum</string>
|
||||||
|
<string name="home_manager_version">Manageri versioon</string>
|
||||||
|
<string name="home_fingerprint">Sõrmejälg</string>
|
||||||
|
<string name="selinux_status_permissive">Lubav</string>
|
||||||
|
<string name="module_failed_to_enable">Mooduli lubamine ebaõnnestus: %s</string>
|
||||||
|
<string name="module_empty">Mooduleid pole paigaldatud</string>
|
||||||
|
<string name="reboot">Taaskäivita</string>
|
||||||
|
<string name="reboot_recovery">Taaskäivita taastusesse</string>
|
||||||
|
<string name="module_uninstall_confirm">Kas soovid kindlasti eemaldada mooduli %s?</string>
|
||||||
|
<string name="module_uninstall_success">%s on eemaldatud</string>
|
||||||
|
<string name="send_log">Raporteeri logi</string>
|
||||||
|
<string name="safe_mode">Turvarežiim</string>
|
||||||
|
<string name="reboot_to_apply">Muudatuste rakendamiseks taaskäivita</string>
|
||||||
|
<string name="home_learn_kernelsu">Õpi KernelSUd</string>
|
||||||
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
|
<string name="profile_default">Vaikimisi</string>
|
||||||
|
<string name="profile_namespace">Haagi nimeruum</string>
|
||||||
|
<string name="profile_umount_modules">Lahtihaagitud moodulid</string>
|
||||||
|
<string name="failed_to_update_app_profile">Rakenduseprofiili uuendamine %s jaoks ebaõnnestus</string>
|
||||||
|
<string name="settings_umount_modules_default">Haagi moodulid vaikimisi lahti</string>
|
||||||
|
<string name="module_start_downloading">Allalaadimise alustamine: %s</string>
|
||||||
|
<string name="failed_to_update_sepolicy">SELinux reeglite uuendamine ebaõnnestus: %s</string>
|
||||||
|
<string name="app_profile_template_edit">Muuda malli</string>
|
||||||
|
<string name="settings_profile_template">Rakenduseprofiili mall</string>
|
||||||
|
<string name="app_profile_template_id">ID</string>
|
||||||
|
<string name="app_profile_template_readonly">vaid lugemiseks</string>
|
||||||
|
<string name="app_profile_template_id_exist">malli ID juba eksisteerib!</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Ekspordi lõikelauale</string>
|
||||||
|
<string name="app_profile_template_sync">Sünkrooni võrgumallid</string>
|
||||||
|
<string name="module_changelog_failed">Muudatuste logi hankimine ebaõnnestus: %s</string>
|
||||||
|
<string name="home">Kodu</string>
|
||||||
|
<string name="home_click_to_install">Klõpsa paigaldamiseks</string>
|
||||||
|
<string name="home_not_installed">Pole paigaldatud</string>
|
||||||
|
<string name="home_unsupported">Mittetoetatud</string>
|
||||||
|
<string name="home_superuser_count">Superkasutajaid: %d</string>
|
||||||
|
<string name="home_unsupported_reason">KernelSU toetab hetkel vaid GSI tuumasid</string>
|
||||||
|
<string name="home_selinux_status">SELinuxi olek</string>
|
||||||
|
<string name="selinux_status_disabled">Keelatud</string>
|
||||||
|
<string name="selinux_status_enforcing">Jõustav</string>
|
||||||
|
<string name="selinux_status_unknown">Teadmata</string>
|
||||||
|
<string name="superuser">Superkasutaja</string>
|
||||||
|
<string name="module_failed_to_disable">Mooduli keelamine ebaõnnestus: %s</string>
|
||||||
|
<string name="module">Moodul</string>
|
||||||
|
<string name="reboot_bootloader">Taaskäivita käivituslaadurisse</string>
|
||||||
|
<string name="uninstall">Eemalda</string>
|
||||||
|
<string name="install">Paigalda</string>
|
||||||
|
<string name="about">Teave</string>
|
||||||
|
<string name="module_install">Paigalda</string>
|
||||||
|
<string name="settings">Seaded</string>
|
||||||
|
<string name="reboot_userspace">Pehme taaskäivitus</string>
|
||||||
|
<string name="reboot_download">Taaskäivita allalaadimisrežiimi</string>
|
||||||
|
<string name="reboot_edl">Taaskäivita EDL-i</string>
|
||||||
|
<string name="refresh">Värskenda</string>
|
||||||
|
<string name="module_author">Autor</string>
|
||||||
|
<string name="module_uninstall_failed">Eemaldamine ebaõnnestus: %s</string>
|
||||||
|
<string name="module_version">Versioon</string>
|
||||||
|
<string name="module_overlay_fs_not_available">overlayfs pole saadaval, moodul ei saa töötada!</string>
|
||||||
|
<string name="show_system_apps">Kuva süsteemirakendused</string>
|
||||||
|
<string name="hide_system_apps">Peida süsteemirakendused</string>
|
||||||
|
<string name="module_magisk_conflict">Moodulid on keelatud, kuna need lähevad konflikti Magiski omadega!</string>
|
||||||
|
<string name="home_click_to_learn_kernelsu">Õpi KernelSUd paigaldama ja mooduleid kasutama</string>
|
||||||
|
<string name="home_support_title">Toeta meid</string>
|
||||||
|
<string name="profile_groups">Grupid</string>
|
||||||
|
<string name="home_support_content">KernelSU on, ja alati jääb, tasuta ning avatud lähtekoodiga kättesaadavaks. Sellegipoolest võid sa näidata, et hoolid, ning teha annetuse.</string>
|
||||||
|
<string name="profile_template">Mall</string>
|
||||||
|
<string name="about_source_code">Vaata lähtekoodi %1$sis<br/>Liitu meie %2$si kanaliga</string>
|
||||||
|
<string name="profile_name">Profiili nimi</string>
|
||||||
|
<string name="profile_custom">Kohandatud</string>
|
||||||
|
<string name="profile_namespace_inherited">Päritud</string>
|
||||||
|
<string name="profile_namespace_global">Globaalne</string>
|
||||||
|
<string name="profile_namespace_individual">Individuaalne</string>
|
||||||
|
<string name="profile_capabilities">Võimekused</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Sobimatu malli ID</string>
|
||||||
|
<string name="profile_selinux_context">SELinux kontekst</string>
|
||||||
|
<string name="require_kernel_version">Praegune KernelSU versioon %d on liiga madal, haldur ei saa konkreetselt toimida. Palun täienda versioonile %d või kõrgem!</string>
|
||||||
|
<string name="profile_selinux_domain">Domeen</string>
|
||||||
|
<string name="launch_app">Käivita</string>
|
||||||
|
<string name="force_stop_app">Sundpeata</string>
|
||||||
|
<string name="profile_selinux_rules">Reeglid</string>
|
||||||
|
<string name="module_update">Uuenda</string>
|
||||||
|
<string name="module_downloading">Mooduli allalaadimine: %s</string>
|
||||||
|
<string name="new_version_available">Uus versioon: %s on saadaval, klõpsa täiendamiseks</string>
|
||||||
|
<string name="restart_app">Taaskäivita</string>
|
||||||
|
<string name="module_changelog">Muudatuste logi</string>
|
||||||
|
<string name="app_profile_template_name">Nimi</string>
|
||||||
|
<string name="app_profile_template_description">Kirjeldus</string>
|
||||||
|
<string name="app_profile_template_import_success">Edukalt imporditud</string>
|
||||||
|
<string name="app_profile_template_save">Salvesta</string>
|
||||||
|
<string name="app_profile_template_import_empty">Lõikelaud on tühi!</string>
|
||||||
|
<string name="app_profile_template_delete">Kustuta</string>
|
||||||
|
<string name="app_profile_template_view">Vaata malli</string>
|
||||||
|
<string name="app_profile_import_export">Impordi/ekspordi</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Impordi lõikelaualt</string>
|
||||||
|
<string name="app_profile_template_save_failed">Malli salvestamine ebaõnnestus</string>
|
||||||
|
<string name="app_profile_template_create">Loo mall</string>
|
||||||
|
<string name="settings_profile_template_summary">Halda kohalikke ja võrgusolevaid rakenduseprofiili malle</string>
|
||||||
|
<string name="profile_umount_modules_summary">Selle valiku lubamine lubab KernelSU-l taastada selle rakenduse moodulite poolt mistahes muudetud faile.</string>
|
||||||
|
<string name="app_profile_template_export_empty">Eksportimiseks kohalikku malli ei leitud!</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">Globaalne vaikeväärtus \"Lahtihaagitud moodulitele\" rakenduseprofiilides. Lubamisel eemaldab see kõik moodulite süsteemimuudatused rakendustele, millel ei ole profiili määratud.</string>
|
||||||
|
</resources>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<string name="home_unsupported_reason">Actuellement, KernelSU ne supporte que les noyaux GKI</string>
|
<string name="home_unsupported_reason">Actuellement, KernelSU ne supporte que les noyaux GKI</string>
|
||||||
<string name="home_kernel">Noyau</string>
|
<string name="home_kernel">Noyau</string>
|
||||||
<string name="home_fingerprint">Empreinte digitale</string>
|
<string name="home_fingerprint">Empreinte digitale</string>
|
||||||
<string name="home_selinux_status">Statut de SELinux</string>
|
<string name="home_selinux_status">Mode SELinux</string>
|
||||||
<string name="selinux_status_disabled">Désactivé</string>
|
<string name="selinux_status_disabled">Désactivé</string>
|
||||||
<string name="selinux_status_permissive">Permissive</string>
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
<string name="selinux_status_unknown">Inconnu</string>
|
<string name="selinux_status_unknown">Inconnu</string>
|
||||||
@@ -29,30 +29,29 @@
|
|||||||
<string name="reboot">Redémarrer</string>
|
<string name="reboot">Redémarrer</string>
|
||||||
<string name="install">Installer</string>
|
<string name="install">Installer</string>
|
||||||
<string name="settings">Paramètres</string>
|
<string name="settings">Paramètres</string>
|
||||||
<string name="reboot_bootloader">Redémarrer vers le bootloader</string>
|
<string name="reboot_bootloader">Redémarrer en mode bootloader</string>
|
||||||
<string name="reboot_userspace">Redémarrage logiciel</string>
|
<string name="reboot_userspace">Redémarrage progressif</string>
|
||||||
<string name="reboot_recovery">Redémarrer en mode récupération</string>
|
<string name="reboot_recovery">Redémarrer en mode de récupération</string>
|
||||||
<string name="reboot_edl">Redémarrer en mode EDL</string>
|
<string name="reboot_edl">Redémarrer en mode EDL</string>
|
||||||
<string name="about">À propos</string>
|
<string name="about">À propos</string>
|
||||||
<string name="module_uninstall_success">%s désinstallé</string>
|
<string name="module_uninstall_success">%s a été désinstallé</string>
|
||||||
<string name="reboot_download">Redémarrer en mode téléchargement</string>
|
<string name="reboot_download">Redémarrer en mode de téléchargement</string>
|
||||||
<string name="module_author">Auteur</string>
|
<string name="module_author">Auteur</string>
|
||||||
<string name="module_uninstall_confirm">Êtes-vous sûr(e) de vouloir désinstaller le module %s \?</string>
|
<string name="module_uninstall_confirm">Êtes-vous sûr(e) de vouloir désinstaller le module %s \?</string>
|
||||||
<string name="home_learn_kernelsu">Découvrir KernelSU</string>
|
<string name="home_learn_kernelsu">Découvrir KernelSU</string>
|
||||||
<string name="module_overlay_fs_not_available">OverlayFS n\'est pas disponible, impossible de faire fonctionner le module !</string>
|
<string name="module_overlay_fs_not_available">OverlayFS est indisponible, impossible de faire fonctionner les modules !</string>
|
||||||
<string name="refresh">Rafraîchir</string>
|
<string name="refresh">Rafraîchir</string>
|
||||||
<string name="show_system_apps">Afficher les applications système</string>
|
<string name="show_system_apps">Afficher les applications système</string>
|
||||||
<string name="hide_system_apps">Masquer les applications système</string>
|
<string name="hide_system_apps">Masquer les applications système</string>
|
||||||
<string name="safe_mode">Mode sans échec</string>
|
<string name="safe_mode">Mode sans échec</string>
|
||||||
<string name="send_log">Envoyer les logs</string>
|
<string name="send_log">Rapport de journal</string>
|
||||||
<string name="reboot_to_apply">Redémarrez pour appliquer les modifications</string>
|
<string name="reboot_to_apply">Redémarrez pour appliquer les modifications</string>
|
||||||
<string name="module_magisk_conflict">Les modules sont désactivés car ils sont en conflit avec ceux de Magisk !</string>
|
<string name="module_magisk_conflict">Les modules sont désactivés car ils sont en conflit avec ceux de Magisk !</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_support_title">Soutenez-nous</string>
|
<string name="home_support_title">Soutenez-nous</string>
|
||||||
<string name="home_click_to_learn_kernelsu">Découvrez comment installer KernelSU et utiliser les modules</string>
|
<string name="home_click_to_learn_kernelsu">Découvrez comment installer KernelSU et utiliser les modules</string>
|
||||||
<string name="home_support_content">KernelSU est et restera toujours gratuit et open source. Vous pouvez cependant nous témoigner de votre soutien en nous faisant un don.</string>
|
<string name="home_support_content">KernelSU est, et restera toujours, gratuit et open source. Vous pouvez cependant nous témoigner de votre soutien en nous faisant un don.</string>
|
||||||
<string name="about_source_code">Voir le code source sur %1$s<br/>
|
<string name="about_source_code">Voir le code source sur %1$s<br/>Rejoindre notre canal %2$s</string>
|
||||||
\nRejoindre notre canal %2$s</string>
|
|
||||||
<string name="profile_template">Modèle</string>
|
<string name="profile_template">Modèle</string>
|
||||||
<string name="profile_default">Par défaut</string>
|
<string name="profile_default">Par défaut</string>
|
||||||
<string name="profile_custom">Personnalisé</string>
|
<string name="profile_custom">Personnalisé</string>
|
||||||
@@ -68,16 +67,41 @@
|
|||||||
<string name="failed_to_update_app_profile">Échec de la modification du profil d\'application de %s</string>
|
<string name="failed_to_update_app_profile">Échec de la modification du profil d\'application de %s</string>
|
||||||
<string name="profile_umount_modules_summary">L\'activation de cette option permettra à KernelSU de restaurer tous les fichiers modifiés par les modules de cette application.</string>
|
<string name="profile_umount_modules_summary">L\'activation de cette option permettra à KernelSU de restaurer tous les fichiers modifiés par les modules de cette application.</string>
|
||||||
<string name="settings_umount_modules_default">Démonter les modules par défaut</string>
|
<string name="settings_umount_modules_default">Démonter les modules par défaut</string>
|
||||||
<string name="settings_umount_modules_default_summary">Valeur globale par défaut pour « Démonter les modules » dans les profils d\'application. Si l\'option est activée, les modifications apportées au système par les modules seront supprimées pour les applications qui n\'ont pas de profil défini.</string>
|
<string name="settings_umount_modules_default_summary">Valeur globale par défaut pour l\'option « Démonter les modules » dans les profils d\'application. Lorsqu\'elle est activée, les modifications apportées au système par les modules seront supprimées pour les applications qui n\'ont pas de profil défini.</string>
|
||||||
<string name="profile_selinux_domain">Domaine</string>
|
<string name="profile_selinux_domain">Domaine</string>
|
||||||
<string name="profile_selinux_rules">Règles</string>
|
<string name="profile_selinux_rules">Règles</string>
|
||||||
<string name="module_update">Mettre à jour</string>
|
<string name="module_update">Mettre à jour</string>
|
||||||
<string name="module_downloading">Téléchargement du module : %s</string>
|
<string name="module_downloading">Téléchargement du module : %s</string>
|
||||||
<string name="launch_app">Lancer</string>
|
<string name="launch_app">Lancer</string>
|
||||||
<string name="new_version_available">Nouvelle version : la %s est disponible, appuyez ici pour la télécharger</string>
|
<string name="new_version_available">La version %s est disponible, appuyez ici pour mettre à jour</string>
|
||||||
<string name="module_start_downloading">Début du téléchargement de : %s</string>
|
<string name="module_start_downloading">Début du téléchargement de : %s</string>
|
||||||
<string name="force_stop_app">Forcer l\'arrêt</string>
|
<string name="force_stop_app">Forcer l\'arrêt</string>
|
||||||
<string name="restart_app">Relancer l\'application</string>
|
<string name="restart_app">Relancer l\'application</string>
|
||||||
<string name="failed_to_update_sepolicy">Échec de la mise à jour des règles de SELinux pour : %s</string>
|
<string name="failed_to_update_sepolicy">Échec de la mise à jour des règles SELinux pour : %s</string>
|
||||||
<string name="require_kernel_version">La version actuelle (%d) de KernelSU est trop ancienne pour que le gestionnaire fonctionne correctement. Veuillez passer à la version %d ou à une version supérieure !</string>
|
<string name="require_kernel_version">La version actuelle de KernelSU (%d) est trop ancienne pour que le gestionnaire fonctionne correctement. Veuillez passer à la version %d ou à une version supérieure !</string>
|
||||||
|
<string name="app_profile_template_import_success">Importation réussie</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exporter vers le presse-papiers</string>
|
||||||
|
<string name="app_profile_template_export_empty">Impossible de trouver un modèle local à exporter !</string>
|
||||||
|
<string name="app_profile_template_id_exist">L\'id du modèle existe déjà !</string>
|
||||||
|
<string name="module_changelog">Journal des modifications</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importer à partir du presse-papiers</string>
|
||||||
|
<string name="module_changelog_failed">Échec de récupération du journal des modifications : %s</string>
|
||||||
|
<string name="app_profile_template_name">Nom</string>
|
||||||
|
<string name="app_profile_template_id_invalid">id de modèle invalide</string>
|
||||||
|
<string name="app_profile_template_sync">Synchroniser les modèles en ligne</string>
|
||||||
|
<string name="app_profile_template_create">Créer un modèle</string>
|
||||||
|
<string name="app_profile_template_readonly">en lecture seule</string>
|
||||||
|
<string name="app_profile_import_export">Importer/exporter</string>
|
||||||
|
<string name="app_profile_template_save_failed">Échec de l\'enregistrement du modèle</string>
|
||||||
|
<string name="app_profile_template_edit">Modifier le modèle</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">Modèles de profils d\'application</string>
|
||||||
|
<string name="app_profile_template_description">Description</string>
|
||||||
|
<string name="app_profile_template_save">Enregistrer</string>
|
||||||
|
<string name="settings_profile_template_summary">Gérer les modèles de profils d\'application locaux et en ligne</string>
|
||||||
|
<string name="app_profile_template_delete">Supprimer</string>
|
||||||
|
<string name="app_profile_template_import_empty">Le presse-papiers est vide !</string>
|
||||||
|
<string name="app_profile_template_view">Voir le modèle</string>
|
||||||
|
<string name="settings_check_update_summary">Vérifier automatiquement les mises à jour à l\'ouverture de l\'application</string>
|
||||||
|
<string name="settings_check_update">Vérifier les mises à jour</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<string name="selinux_status_enforcing">Érvényesítés</string>
|
<string name="selinux_status_enforcing">Érvényesítés</string>
|
||||||
<string name="selinux_status_permissive">Megengedő</string>
|
<string name="selinux_status_permissive">Megengedő</string>
|
||||||
<string name="selinux_status_unknown">Ismeretlen</string>
|
<string name="selinux_status_unknown">Ismeretlen</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">Super user</string>
|
||||||
<string name="module_failed_to_enable">Nem sikerült engedélyezni a következő modult: %s</string>
|
<string name="module_failed_to_enable">Nem sikerült engedélyezni a következő modult: %s</string>
|
||||||
<string name="module_failed_to_disable">Nem sikerült letiltani a következő modulokat: %s</string>
|
<string name="module_failed_to_disable">Nem sikerült letiltani a következő modulokat: %s</string>
|
||||||
<string name="module_empty">Nincs modul telepítve</string>
|
<string name="module_empty">Nincs modul telepítve</string>
|
||||||
@@ -67,16 +67,39 @@
|
|||||||
<string name="reboot_userspace">Android felület újraindítása</string>
|
<string name="reboot_userspace">Android felület újraindítása</string>
|
||||||
<string name="reboot_recovery">Újraindítás recovery-módba</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_bootloader">Újraindítás bootloader-módba</string>
|
||||||
<string name="module_uninstall_success">%s eltávolítva</string>
|
<string name="module_uninstall_success">%s törölve</string>
|
||||||
<string name="module_version">Verzió</string>
|
<string name="module_version">Verzió</string>
|
||||||
<string name="send_log">Fejlesztői napló küldése</string>
|
<string name="send_log">Napló küldése</string>
|
||||||
<string name="reboot_to_apply">Indítsd újra a készüléket hogy érvényesítsd a változást</string>
|
<string name="reboot_to_apply">Indítsd újra a készüléket hogy érvényesítsd a változást</string>
|
||||||
<string name="home_support_content">A KernelSU ingyenes és nyílt forráskódú és mindig is az lesz. Te viszont meg tudod mutatni azt, hogy törődsz ennek a projektnek a sorsával egy adomány formájában.</string>
|
<string name="home_support_content">A KernelSU ingyenes és nyílt forráskódú és mindig is az lesz. Te viszont meg tudod mutatni azt, hogy törődsz ennek a projektnek a sorsával egy adomány formájában.</string>
|
||||||
<string name="profile_namespace_global">Globális</string>
|
<string name="profile_namespace_global">Globális</string>
|
||||||
<string name="profile_umount_modules">Unmountold a modulokat</string>
|
<string name="profile_umount_modules">Unmountold a modulokat</string>
|
||||||
<string name="failed_to_update_app_profile">Nem sikerült frissíteni az App Profilt ehhez %s</string>
|
<string name="failed_to_update_app_profile">Nem sikerült frissíteni az App Profilt ehhez %s</string>
|
||||||
<string name="settings_umount_modules_default_summary">A „Modulok csatlakoztatása” globális alapértelmezett értéke az alkalmazásprofilokban. Ha engedélyezve van, eltávolítja a rendszer összes modul-módosítását azoknál az alkalmazásoknál, amelyeknek nincs beállított profilja.</string>
|
<string name="settings_umount_modules_default_summary">A „Modulok csatlakoztatása” globális alapértelmezett értéke az alkalmazásprofilokban. Ha engedélyezve van, eltávolítja a rendszer összes modul-módosítását azoknál az alkalmazásoknál, amelyeknek nincs beállított profilja.</string>
|
||||||
<string name="new_version_available">Új verzió: %s elérhető, kattints a letöltéséhez</string>
|
<string name="new_version_available">Új verzió: %s elérhető, kattints a frissítéshez</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="failed_to_update_sepolicy">Nem sikerült frissíteni a SELinux szabályait a következőhöz: %s</string>
|
||||||
<string name="require_kernel_version">A jelenlegi KernelSU verzió %d túlságosan elavult. Kérlek frissíts a %d verzióra vagy újabbra!</string>
|
<string name="require_kernel_version">A jelenlegi KernelSU verzió %d túlságosan elavult. Kérlek frissíts a %d verzióra vagy újabbra!</string>
|
||||||
|
<string name="app_profile_template_import_success">Sikeresen importálva</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exportálás a vágólapból</string>
|
||||||
|
<string name="app_profile_template_export_empty">A helyi sablon nem található az exportáláshoz!</string>
|
||||||
|
<string name="app_profile_template_id_exist">A sablon ID már létezik!</string>
|
||||||
|
<string name="module_changelog">Változások</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importálás a vágólapból</string>
|
||||||
|
<string name="module_changelog_failed">A változásnapló lekérése nem sikerült: %s</string>
|
||||||
|
<string name="app_profile_template_name">Név</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Hibás sablon ID</string>
|
||||||
|
<string name="app_profile_template_sync">Online sablonok szinkronizálása</string>
|
||||||
|
<string name="app_profile_template_create">Sablon készítése</string>
|
||||||
|
<string name="app_profile_template_readonly">csak olvasható</string>
|
||||||
|
<string name="app_profile_import_export">Import/Export</string>
|
||||||
|
<string name="app_profile_template_save_failed">A sablon mentése sikertelen</string>
|
||||||
|
<string name="app_profile_template_edit">Sablon szerkesztése</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">Alkalmazásprofil sablon</string>
|
||||||
|
<string name="app_profile_template_description">Leírás</string>
|
||||||
|
<string name="app_profile_template_save">Mentés</string>
|
||||||
|
<string name="settings_profile_template_summary">Az alkalmazásprofil helyi és online sablon kezelése</string>
|
||||||
|
<string name="app_profile_template_delete">Törlés</string>
|
||||||
|
<string name="app_profile_template_import_empty">A vágólap üres!</string>
|
||||||
|
<string name="app_profile_template_view">Sablon megnézése</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -5,19 +5,19 @@
|
|||||||
<string name="home_click_to_install">Klik untuk memasang</string>
|
<string name="home_click_to_install">Klik untuk memasang</string>
|
||||||
<string name="home_working">Bekerja</string>
|
<string name="home_working">Bekerja</string>
|
||||||
<string name="home_working_version">Versi: %d</string>
|
<string name="home_working_version">Versi: %d</string>
|
||||||
<string name="home_superuser_count">Superusers: %d</string>
|
<string name="home_superuser_count">Superuser: %d</string>
|
||||||
<string name="home_module_count">Modul: %d</string>
|
<string name="home_module_count">Modul: %d</string>
|
||||||
<string name="home_unsupported">Tidak didukung</string>
|
<string name="home_unsupported">Tidak didukung</string>
|
||||||
<string name="home_unsupported_reason">KernelSU hanya mendukung kernel GKI saat ini</string>
|
<string name="home_unsupported_reason">KernelSU saat ini hanya mendukung kernel GKI</string>
|
||||||
<string name="home_kernel">Kernel</string>
|
<string name="home_kernel">Kernel</string>
|
||||||
<string name="home_manager_version">Versi Manager</string>
|
<string name="home_manager_version">Versi Manager</string>
|
||||||
<string name="home_fingerprint">Sidik jari</string>
|
<string name="home_fingerprint">Sidik jari</string>
|
||||||
<string name="home_selinux_status">Status SELinux</string>
|
<string name="home_selinux_status">Status SELinux</string>
|
||||||
<string name="selinux_status_disabled">Dinonaktifkan</string>
|
<string name="selinux_status_disabled">Dinonaktifkan</string>
|
||||||
<string name="selinux_status_enforcing">Enforcing</string>
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
<string name="selinux_status_permissive">Permasif</string>
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
<string name="selinux_status_unknown">Tidak dikenal</string>
|
<string name="selinux_status_unknown">Tidak dikenal</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">SuperUser</string>
|
||||||
<string name="module_failed_to_enable">Gagal mengaktifkan modul: %s</string>
|
<string name="module_failed_to_enable">Gagal mengaktifkan modul: %s</string>
|
||||||
<string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string>
|
<string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string>
|
||||||
<string name="module_empty">Tidak ada modul yang terpasang</string>
|
<string name="module_empty">Tidak ada modul yang terpasang</string>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<string name="reboot_edl">Mulai ulang ke EDL</string>
|
<string name="reboot_edl">Mulai ulang ke EDL</string>
|
||||||
<string name="about">Tentang</string>
|
<string name="about">Tentang</string>
|
||||||
<string name="module_uninstall_confirm">Apakah Anda yakin ingin mencopot modul %s?</string>
|
<string name="module_uninstall_confirm">Apakah Anda yakin ingin mencopot modul %s?</string>
|
||||||
<string name="module_uninstall_success">%s Tercopot</string>
|
<string name="module_uninstall_success">%s Telah dicopot</string>
|
||||||
<string name="module_uninstall_failed">Gagal untuk mencopot: %s</string>
|
<string name="module_uninstall_failed">Gagal untuk mencopot: %s</string>
|
||||||
<string name="module_version">Versi</string>
|
<string name="module_version">Versi</string>
|
||||||
<string name="module_author">Pembuat</string>
|
<string name="module_author">Pembuat</string>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<string name="refresh">Segarkan</string>
|
<string name="refresh">Segarkan</string>
|
||||||
<string name="show_system_apps">Tampilkan apl sistem</string>
|
<string name="show_system_apps">Tampilkan apl sistem</string>
|
||||||
<string name="hide_system_apps">Sembunyikan apl sistem</string>
|
<string name="hide_system_apps">Sembunyikan apl sistem</string>
|
||||||
<string name="send_log">Kirim Log</string>
|
<string name="send_log">Laporkan Log</string>
|
||||||
<string name="safe_mode">Mode aman</string>
|
<string name="safe_mode">Mode aman</string>
|
||||||
<string name="reboot_to_apply">Mulai ulang untuk menerapkan</string>
|
<string name="reboot_to_apply">Mulai ulang untuk menerapkan</string>
|
||||||
<string name="module_magisk_conflict">Modul dinonaktifkan karena bertentangan dengan Magisk!</string>
|
<string name="module_magisk_conflict">Modul dinonaktifkan karena bertentangan dengan Magisk!</string>
|
||||||
@@ -81,4 +81,26 @@
|
|||||||
<string name="failed_to_update_sepolicy">Gagal memperbarui aturan SELinux untuk: %s</string>
|
<string name="failed_to_update_sepolicy">Gagal memperbarui aturan SELinux untuk: %s</string>
|
||||||
<string name="require_kernel_version">Versi KernelSU saat ini %d terlalu rendah bagi manajer untuk dapat berfungsi dengan baik. Harap tingkatkan ke versi %d atau yang lebih tinggi!</string>
|
<string name="require_kernel_version">Versi KernelSU saat ini %d terlalu rendah bagi manajer untuk dapat berfungsi dengan baik. Harap tingkatkan ke versi %d atau yang lebih tinggi!</string>
|
||||||
<string name="module_changelog">Catatan Perubahan</string>
|
<string name="module_changelog">Catatan Perubahan</string>
|
||||||
|
<string name="app_profile_template_import_success">Berhasil diimpor</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Expor ke clipboard</string>
|
||||||
|
<string name="app_profile_template_export_empty">Tidak dapat menemukan template lokal untuk di expor!</string>
|
||||||
|
<string name="app_profile_template_id_exist">Id template telah ada sebelumnya!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Impor dari clipboard</string>
|
||||||
|
<string name="module_changelog_failed">Gagal mengambil Changelog: %s</string>
|
||||||
|
<string name="app_profile_template_name">Nama</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Id template tidak valid</string>
|
||||||
|
<string name="app_profile_template_sync">Sinkronkan template online</string>
|
||||||
|
<string name="app_profile_template_create">Buat Template</string>
|
||||||
|
<string name="app_profile_import_export">Impor/Expor</string>
|
||||||
|
<string name="app_profile_template_save_failed">Gagal untuk menyimpan template</string>
|
||||||
|
<string name="app_profile_template_edit">Edit Templat</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">Template Profil Aplikasi</string>
|
||||||
|
<string name="app_profile_template_description">Deskripsi</string>
|
||||||
|
<string name="app_profile_template_save">Simpan</string>
|
||||||
|
<string name="settings_profile_template_summary">Atur template lokal dan online Profil Aplikasi</string>
|
||||||
|
<string name="app_profile_template_delete">Hapus</string>
|
||||||
|
<string name="app_profile_template_import_empty">Clipboard kosong!</string>
|
||||||
|
<string name="app_profile_template_view">Lihat Template</string>
|
||||||
|
<string name="app_profile_template_readonly">Hanya baca</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<string name="module_version">Versione</string>
|
<string name="module_version">Versione</string>
|
||||||
<string name="module_author">Autore</string>
|
<string name="module_author">Autore</string>
|
||||||
<string name="module_overlay_fs_not_available">overlayfs non è disponibile, il modulo non può funzionare!</string>
|
<string name="module_overlay_fs_not_available">overlayfs non è disponibile, il modulo non può funzionare!</string>
|
||||||
<string name="refresh">Aggiorna</string>
|
<string name="refresh">Ricarica</string>
|
||||||
<string name="show_system_apps">Mostra app di sistema</string>
|
<string name="show_system_apps">Mostra app di sistema</string>
|
||||||
<string name="hide_system_apps">Nascondi app di sistema</string>
|
<string name="hide_system_apps">Nascondi app di sistema</string>
|
||||||
<string name="send_log">Invia log</string>
|
<string name="send_log">Invia log</string>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
<string name="profile_selinux_rules">Regole</string>
|
<string name="profile_selinux_rules">Regole</string>
|
||||||
<string name="module_downloading">Sto scaricando il modulo: %s</string>
|
<string name="module_downloading">Sto scaricando il modulo: %s</string>
|
||||||
<string name="module_start_downloading">Inizia a scaricare:%s</string>
|
<string name="module_start_downloading">Inizia a scaricare:%s</string>
|
||||||
<string name="new_version_available">Nuova versione: %s disponibile, tocca per scaricare</string>
|
<string name="new_version_available">Nuova versione: %s disponibile, tocca per aggiornare</string>
|
||||||
<string name="force_stop_app">Arresto forzato</string>
|
<string name="force_stop_app">Arresto forzato</string>
|
||||||
<string name="restart_app">Riavvia</string>
|
<string name="restart_app">Riavvia</string>
|
||||||
<string name="failed_to_update_sepolicy">Aggiornamento regole SELinux per %s fallito</string>
|
<string name="failed_to_update_sepolicy">Aggiornamento regole SELinux per %s fallito</string>
|
||||||
@@ -79,4 +79,31 @@
|
|||||||
<string name="profile_selinux_domain">Dominio</string>
|
<string name="profile_selinux_domain">Dominio</string>
|
||||||
<string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in Profili App. 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 Profili App. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string>
|
||||||
<string name="require_kernel_version">La versione attualmente installata di KernelSU (%d) è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %d o successiva!</string>
|
<string name="require_kernel_version">La versione attualmente installata di KernelSU (%d) è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %d o successiva!</string>
|
||||||
|
<string name="module_changelog">Registro aggiornamenti</string>
|
||||||
|
<string name="app_profile_template_create">Crea modello</string>
|
||||||
|
<string name="app_profile_template_edit">Modifica Modello</string>
|
||||||
|
<string name="app_profile_template_id">identificativo</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Identificativo modello non valido</string>
|
||||||
|
<string name="app_profile_template_name">Nome</string>
|
||||||
|
<string name="app_profile_template_view">Visualizza modello</string>
|
||||||
|
<string name="app_profile_template_readonly">Sola lettura</string>
|
||||||
|
<string name="app_profile_template_id_exist">Esiste già l\'identificativo del modello!</string>
|
||||||
|
<string name="app_profile_import_export">Importa/Esporta</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importa dagli appunti</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Esporta negli appunti</string>
|
||||||
|
<string name="app_profile_template_export_empty">Impossibile trovare profilo locale da esportare!</string>
|
||||||
|
<string name="app_profile_template_import_success">Importato con successo</string>
|
||||||
|
<string name="app_profile_template_sync">Sincronizza i modelli remoti</string>
|
||||||
|
<string name="app_profile_template_import_empty">Gli appunti sono vuoti!</string>
|
||||||
|
<string name="grant_root_failed">Impossibile ottenere l\'accesso root!</string>
|
||||||
|
<string name="settings_profile_template">Modelli Profili App</string>
|
||||||
|
<string name="settings_profile_template_summary">Gestisci i modelli locali e remoti dei Profili App</string>
|
||||||
|
<string name="app_profile_template_delete">Elimina</string>
|
||||||
|
<string name="app_profile_template_description">Descrizione</string>
|
||||||
|
<string name="app_profile_template_save">Salva</string>
|
||||||
|
<string name="app_profile_template_save_failed">Impossibile salvare profilo</string>
|
||||||
|
<string name="open">Apri</string>
|
||||||
|
<string name="module_changelog_failed">Impossibile reperire il changelog: %s</string>
|
||||||
|
<string name="settings_check_update">Controlla aggiornamenti</string>
|
||||||
|
<string name="settings_check_update_summary">Controlla automaticamente la disponibilità di aggiornamenti all\'apertura dell\'applicazione</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<string name="home_unsupported">非対応</string>
|
<string name="home_unsupported">非対応</string>
|
||||||
<string name="home_unsupported_reason">現在、 KernelSU は GKI カーネルにのみ対応しています</string>
|
<string name="home_unsupported_reason">現在、 KernelSU は GKI カーネルにのみ対応しています</string>
|
||||||
<string name="home_kernel">カーネル</string>
|
<string name="home_kernel">カーネル</string>
|
||||||
<string name="home_manager_version">バージョン</string>
|
<string name="home_manager_version">アプリのバージョン</string>
|
||||||
<string name="home_fingerprint">Fingerprint</string>
|
<string name="home_fingerprint">Fingerprint</string>
|
||||||
<string name="home_selinux_status">SELinux の状態</string>
|
<string name="home_selinux_status">SELinux の状態</string>
|
||||||
<string name="selinux_status_disabled">Disabled</string>
|
<string name="selinux_status_disabled">Disabled</string>
|
||||||
@@ -31,10 +31,10 @@
|
|||||||
<string name="reboot_recovery">リカバリーへ再起動</string>
|
<string name="reboot_recovery">リカバリーへ再起動</string>
|
||||||
<string name="reboot_bootloader">ブートローダー へ再起動</string>
|
<string name="reboot_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>
|
||||||
<string name="module_uninstall_success">%sをアンインストールしました</string>
|
<string name="module_uninstall_success">%s はアンインストールされました</string>
|
||||||
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
|
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
|
||||||
<string name="module_version">バージョン</string>
|
<string name="module_version">バージョン</string>
|
||||||
<string name="module_author">制作者</string>
|
<string name="module_author">制作者</string>
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
<string name="send_log">ログを送信</string>
|
<string name="send_log">ログを送信</string>
|
||||||
<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_learn_kernelsu">KernelSU の詳細</string>
|
<string name="home_learn_kernelsu">KernelSU について</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/ja_JP/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/ja_JP/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">KernelSU のインストール方法やモジュールの使い方はこちら</string>
|
<string name="home_click_to_learn_kernelsu">KernelSU のインストール方法やモジュールの使い方はこちら</string>
|
||||||
<string name="home_support_title">支援する</string>
|
<string name="home_support_title">支援する</string>
|
||||||
@@ -64,12 +64,12 @@
|
|||||||
<string name="profile_umount_modules">モジュールのアンマウント</string>
|
<string name="profile_umount_modules">モジュールのアンマウント</string>
|
||||||
<string name="profile_groups">グループ</string>
|
<string name="profile_groups">グループ</string>
|
||||||
<string name="profile_selinux_context">SELinux コンテキスト</string>
|
<string name="profile_selinux_context">SELinux コンテキスト</string>
|
||||||
<string name="failed_to_update_app_profile">%sのアプリのプロファイルの更新をできませでした</string>
|
<string name="failed_to_update_app_profile">%s のアプリのプロファイルの更新をできませでした</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>
|
||||||
<string name="new_version_available">新しいバージョン: %s が利用可能です。タップしてダウンロード</string>
|
<string name="new_version_available">新しいバージョン: %s が利用可能です。タップしてダウンロード</string>
|
||||||
<string name="module_update">アップデート</string>
|
<string name="module_update">アップデート</string>
|
||||||
<string name="module_start_downloading">ダウンロードを開始:%s</string>
|
<string name="module_start_downloading">ダウンロードを開始: %s</string>
|
||||||
<string name="launch_app">起動</string>
|
<string name="launch_app">起動</string>
|
||||||
<string name="force_stop_app">強制停止</string>
|
<string name="force_stop_app">強制停止</string>
|
||||||
<string name="restart_app">再起動</string>
|
<string name="restart_app">再起動</string>
|
||||||
@@ -78,7 +78,33 @@
|
|||||||
<string name="module_downloading">モジュールをダウンロード中: %s</string>
|
<string name="module_downloading">モジュールをダウンロード中: %s</string>
|
||||||
<string name="profile_umount_modules_summary">このオプションを有効にすると、KernelSU はこのアプリのモジュールによって変更されたファイルを復元できるようになります。</string>
|
<string name="profile_umount_modules_summary">このオプションを有効にすると、KernelSU はこのアプリのモジュールによって変更されたファイルを復元できるようになります。</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="require_kernel_version">現在の KernelSU バージョン %d はマネージャーが適切に機能するには低すぎます。 バージョン %d 以降にアップグレードしてください!</string>
|
<string name="require_kernel_version">現在の KernelSU バージョン %d はマネージャーが適切に機能するには低すぎます。 バージョン %d 以降にアップグレードしてください!</string>
|
||||||
<string name="module_changelog">変更履歴</string>
|
<string name="module_changelog">変更履歴</string>
|
||||||
|
<string name="app_profile_template_import_success">インポート成功</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">クリップボードからエクスポート</string>
|
||||||
|
<string name="app_profile_template_export_empty">エクスポートするローカル テンプレートが見つかりません!</string>
|
||||||
|
<string name="app_profile_template_id_exist">テンプレート id はすでに存在します!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">クリップボードからインポート</string>
|
||||||
|
<string name="module_changelog_failed">変更ログの取得に失敗しました: %s</string>
|
||||||
|
<string name="app_profile_template_name">名前</string>
|
||||||
|
<string name="app_profile_template_id_invalid">無効なテンプレート id</string>
|
||||||
|
<string name="app_profile_template_sync">オンラインテンプレートの同期</string>
|
||||||
|
<string name="app_profile_template_create">テンプレートの作成</string>
|
||||||
|
<string name="app_profile_template_readonly">読み取り専用</string>
|
||||||
|
<string name="app_profile_import_export">インポート/エクスポート</string>
|
||||||
|
<string name="app_profile_template_save_failed">テンプレートの保存に失敗しました</string>
|
||||||
|
<string name="app_profile_template_edit">テンプレートの編集</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="settings_profile_template">アプリプロファイルのテンプレート</string>
|
||||||
|
<string name="app_profile_template_description">説明</string>
|
||||||
|
<string name="app_profile_template_save">保存</string>
|
||||||
|
<string name="settings_profile_template_summary">アプリプロファイルのローカルおよびオンラインテンプレートを管理する</string>
|
||||||
|
<string name="app_profile_template_delete">消去</string>
|
||||||
|
<string name="app_profile_template_import_empty">クリップボードが空です!</string>
|
||||||
|
<string name="app_profile_template_view">テンプレートを表示</string>
|
||||||
|
<string name="settings_check_update">アップデートを確認</string>
|
||||||
|
<string name="settings_check_update_summary">アプリを開いたときにアップデートを自動的に確認する</string>
|
||||||
|
<string name="grant_root_failed">root の付与に失敗しました!</string>
|
||||||
|
<string name="open">開ける</string>
|
||||||
</resources>
|
</resources>
|
||||||
104
manager/app/src/main/res/values-lv/strings.xml
Normal file
104
manager/app/src/main/res/values-lv/strings.xml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="profile_umount_modules_summary">Iespējojot šo opciju, KernelSU varēs atjaunot visus moduļos šīs lietojumprogrammas modificētos failus.</string>
|
||||||
|
<string name="failed_to_update_sepolicy">Neizdevās atjaunināt SELinux noteikumus: %s</string>
|
||||||
|
<string name="settings_profile_template_summary">Pārvaldiet vietējo un tiešsaistes lietotņu profila veidni</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Nederīgs veidnes id</string>
|
||||||
|
<string name="app_profile_template_id_exist">veidnes id jau pastāv!</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Eksportēt starpliktuvē</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importēt no starpliktuves</string>
|
||||||
|
<string name="app_profile_template_import_success">Importēts veiksmīgi</string>
|
||||||
|
<string name="app_profile_template_sync">Sinhronizēt tiešsaistes veidnes</string>
|
||||||
|
<string name="home">Sākums</string>
|
||||||
|
<string name="home_not_installed">Nav ieinstalēts</string>
|
||||||
|
<string name="home_click_to_install">Noklikšķiniet, lai instalētu</string>
|
||||||
|
<string name="home_working">Darbojas</string>
|
||||||
|
<string name="home_working_version">Versija: %d</string>
|
||||||
|
<string name="home_superuser_count">Superlietotāji: %d</string>
|
||||||
|
<string name="home_module_count">Moduļi: %d</string>
|
||||||
|
<string name="home_unsupported">Neatbalstīts</string>
|
||||||
|
<string name="home_unsupported_reason">KernelSU tagad atbalsta tikai GKI kodolus</string>
|
||||||
|
<string name="home_kernel">Kodols</string>
|
||||||
|
<string name="home_manager_version">Pārvaldnieka versija</string>
|
||||||
|
<string name="home_fingerprint">Pirkstu nospiedums</string>
|
||||||
|
<string name="home_selinux_status">SELinux statuss</string>
|
||||||
|
<string name="selinux_status_enforcing">Izpildīšana</string>
|
||||||
|
<string name="selinux_status_disabled">Atspējots</string>
|
||||||
|
<string name="selinux_status_unknown">Nezināms</string>
|
||||||
|
<string name="superuser">SuperLietotājs</string>
|
||||||
|
<string name="module_failed_to_disable">Neizdevās atspējot moduli: %s</string>
|
||||||
|
<string name="module_empty">Nav instalētu moduļu</string>
|
||||||
|
<string name="module">Moduļi</string>
|
||||||
|
<string name="uninstall">Atinstalēt</string>
|
||||||
|
<string name="install">Instalēt</string>
|
||||||
|
<string name="reboot">Restartēt</string>
|
||||||
|
<string name="settings">Iestatījumi</string>
|
||||||
|
<string name="reboot_userspace">Ātri restartēt</string>
|
||||||
|
<string name="reboot_bootloader">Restartēt uz Bootloaderu</string>
|
||||||
|
<string name="reboot_recovery">Restartēt uz Recovery</string>
|
||||||
|
<string name="reboot_download">Restartēt uz Download</string>
|
||||||
|
<string name="reboot_edl">Restartēt uz EDL</string>
|
||||||
|
<string name="about">Par</string>
|
||||||
|
<string name="module_uninstall_success">%s ir atinstalēts</string>
|
||||||
|
<string name="module_uninstall_failed">Neizdevās atinstalēt: %s</string>
|
||||||
|
<string name="module_author">Autors</string>
|
||||||
|
<string name="refresh">Atjaunot</string>
|
||||||
|
<string name="show_system_apps">Rādīt sistēmas lietotnes</string>
|
||||||
|
<string name="hide_system_apps">Slēpt sistēmas lietotnes</string>
|
||||||
|
<string name="send_log">Ziņot žurnālu</string>
|
||||||
|
<string name="reboot_to_apply">Restartējiet, lai stātos spēkā</string>
|
||||||
|
<string name="home_learn_kernelsu">Uzzināt par KernelSU</string>
|
||||||
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
|
<string name="home_click_to_learn_kernelsu">Uzzināt, kā instalēt KernelSU un izmantot moduļus</string>
|
||||||
|
<string name="home_support_title">Atbalsti mūs</string>
|
||||||
|
<string name="about_source_code">Skatiet avota kodu vietnē %1$s<br/>Pievienojies mūsu %2$s kanālam</string>
|
||||||
|
<string name="profile_default">Noklusējums</string>
|
||||||
|
<string name="profile_template">Veidne</string>
|
||||||
|
<string name="profile_custom">Pielāgots</string>
|
||||||
|
<string name="profile_name">Profila vārds</string>
|
||||||
|
<string name="profile_namespace">Mount nosaukumvieta</string>
|
||||||
|
<string name="profile_namespace_individual">Individuāls</string>
|
||||||
|
<string name="profile_capabilities">Iespējas</string>
|
||||||
|
<string name="profile_selinux_context">SELinux konteksts</string>
|
||||||
|
<string name="profile_umount_modules">Atvienot moduļus</string>
|
||||||
|
<string name="failed_to_update_app_profile">Neizdevās atjaunināt lietotnes profilu %s</string>
|
||||||
|
<string name="settings_umount_modules_default">Pēc noklusējuma atvienot moduļus</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">Globālā noklusējuma vērtība vienumam “Atvienot moduļus” lietotņu profilos. Ja tas ir iespējots, lietojumprogrammām, kurām nav iestatīts profils, tiks noņemtas visas sistēmas moduļu modifikācijas.</string>
|
||||||
|
<string name="profile_selinux_domain">Domēns</string>
|
||||||
|
<string name="profile_selinux_rules">Noteikumi</string>
|
||||||
|
<string name="module_update">Atjaunināt</string>
|
||||||
|
<string name="module_downloading">Lejupielādē moduli: %s</string>
|
||||||
|
<string name="module_start_downloading">Sākt lejupielādi: %s</string>
|
||||||
|
<string name="new_version_available">Jaunā versija: %s ir pieejama, noklikšķiniet, lai atjauninātu</string>
|
||||||
|
<string name="launch_app">Palaist</string>
|
||||||
|
<string name="force_stop_app">Piespiedu apstāšana</string>
|
||||||
|
<string name="restart_app">Restartēt aplikāciju</string>
|
||||||
|
<string name="module_changelog">Izmaiņu žurnāls</string>
|
||||||
|
<string name="settings_profile_template">Lietotnes profila veidne</string>
|
||||||
|
<string name="app_profile_template_create">Izveidot veidni</string>
|
||||||
|
<string name="app_profile_template_edit">Rediģēt veidni</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="app_profile_template_name">Vārds</string>
|
||||||
|
<string name="app_profile_template_description">Apraksts</string>
|
||||||
|
<string name="app_profile_template_save">Saglabāt</string>
|
||||||
|
<string name="app_profile_template_delete">Dzēst</string>
|
||||||
|
<string name="app_profile_template_view">Skatīt veidni</string>
|
||||||
|
<string name="app_profile_template_readonly">tikai lasīt</string>
|
||||||
|
<string name="app_profile_import_export">Importēt/Eksportēt</string>
|
||||||
|
<string name="app_profile_template_export_empty">Nevar atrast vietējo eksportējamo veidni!</string>
|
||||||
|
<string name="app_profile_template_save_failed">Neizdevās saglabāt veidni</string>
|
||||||
|
<string name="app_profile_template_import_empty">Starpliktuve ir tukša!</string>
|
||||||
|
<string name="module_changelog_failed">Izmaiņu žurnāla iegūšana neizdevās: %s</string>
|
||||||
|
<string name="selinux_status_permissive">Visatļautība</string>
|
||||||
|
<string name="module_failed_to_enable">Neizdevās iespējot moduli: %s</string>
|
||||||
|
<string name="module_install">Instalēt</string>
|
||||||
|
<string name="module_uninstall_confirm">Vai tiešām vēlaties atinstalēt moduli %s?</string>
|
||||||
|
<string name="module_version">Versija</string>
|
||||||
|
<string name="module_overlay_fs_not_available">overlayfs nav pieejams, modulis nevar darboties!</string>
|
||||||
|
<string name="safe_mode">Drošais režīms</string>
|
||||||
|
<string name="module_magisk_conflict">Moduļi ir atspējoti, jo tie konfliktē ar Magisk!</string>
|
||||||
|
<string name="home_support_content">KernelSU ir un vienmēr būs bezmaksas un atvērtā koda. Tomēr jūs varat parādīt mums, ka jums rūp, veicot ziedojumu.</string>
|
||||||
|
<string name="profile_groups">Grupas</string>
|
||||||
|
<string name="profile_namespace_global">Globāli</string>
|
||||||
|
<string name="require_kernel_version">Pašreizējā KernelSU versija %d ir pārāk zema, lai pārvaldnieks darbotos pareizi. Lūdzu, atjauniniet uz versiju %d vai jaunāku!</string>
|
||||||
|
</resources>
|
||||||
37
manager/app/src/main/res/values-ms/strings.xml
Normal file
37
manager/app/src/main/res/values-ms/strings.xml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="selinux_status_unknown">Tidak Diketahui</string>
|
||||||
|
<string name="selinux_status_disabled">Lumpuhkan</string>
|
||||||
|
<string name="selinux_status_permissive">Permisif</string>
|
||||||
|
<string name="reboot_download">Mulakan semula ke Download</string>
|
||||||
|
<string name="module_failed_to_enable">Modul tidak berjaya Diaktifkan:%s</string>
|
||||||
|
<string name="reboot_edl">Mulakan semula ke EDL</string>
|
||||||
|
<string name="home_superuser_count">Superusers%d</string>
|
||||||
|
<string name="home_module_count">Modul%d</string>
|
||||||
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
|
<string name="home_fingerprint">Cap Jari</string>
|
||||||
|
<string name="reboot_recovery">Mulakan semula ke Recovery</string>
|
||||||
|
<string name="reboot_userspace">Soft reboot</string>
|
||||||
|
<string name="uninstall">Padam</string>
|
||||||
|
<string name="module_install">Pasang</string>
|
||||||
|
<string name="home_click_to_install">Tekan untuk memasang</string>
|
||||||
|
<string name="module">Modul</string>
|
||||||
|
<string name="about">Tentang</string>
|
||||||
|
<string name="home_working_version">Versi%d</string>
|
||||||
|
<string name="reboot">Mulakan semula</string>
|
||||||
|
<string name="home_unsupported_reason">KernelSU ketika ini hanya menyokong kernel GKI</string>
|
||||||
|
<string name="home_selinux_status">Status SELinux</string>
|
||||||
|
<string name="home_unsupported">Tidak Disokong</string>
|
||||||
|
<string name="home">Layar Utama</string>
|
||||||
|
<string name="module_uninstall_confirm">Apakah anda pasti ingin membuang modul %s\?</string>
|
||||||
|
<string name="superuser">SuperUser</string>
|
||||||
|
<string name="settings">Tetapan</string>
|
||||||
|
<string name="home_working">Berjalan</string>
|
||||||
|
<string name="module_failed_to_disable">Gagal mematikan modul:%s</string>
|
||||||
|
<string name="module_empty">Tiada modul dipasang</string>
|
||||||
|
<string name="install">Pasang</string>
|
||||||
|
<string name="home_kernel">Kernel</string>
|
||||||
|
<string name="home_not_installed">Tidak terpasang</string>
|
||||||
|
<string name="reboot_bootloader">Mulakan semula ke bootloader</string>
|
||||||
|
<string name="home_manager_version">Versi Manager</string>
|
||||||
|
</resources>
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
<string name="selinux_status_enforcing">Afgedwongen</string>
|
<string name="selinux_status_enforcing">Afgedwongen</string>
|
||||||
<string name="selinux_status_permissive">Permissief</string>
|
<string name="selinux_status_permissive">Permissief</string>
|
||||||
<string name="selinux_status_unknown">Niet gekend</string>
|
<string name="selinux_status_unknown">Niet gekend</string>
|
||||||
<string name="superuser">Supergebruiker</string>
|
<string name="superuser">SupergeBruiker</string>
|
||||||
<string name="module_failed_to_enable">Mislukt om module in te schakelen: %s</string>
|
<string name="module_failed_to_enable">Mislukt om module in te schakelen: %s</string>
|
||||||
<string name="module_failed_to_disable">Mislukt om module uit te schakelen: %s</string>
|
<string name="module_failed_to_disable">Mislukt om module uit te schakelen: %s</string>
|
||||||
<string name="module_empty">Geen module geïnstalleerd</string>
|
<string name="module_empty">Geen geïnstalleerde modules</string>
|
||||||
<string name="module">Module</string>
|
<string name="module">Module</string>
|
||||||
<string name="uninstall">Verwijderen</string>
|
<string name="uninstall">Verwijderen</string>
|
||||||
<string name="module_install">Installeren</string>
|
<string name="module_install">Installeren</string>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<string name="reboot_edl">Herstart naar EDL</string>
|
<string name="reboot_edl">Herstart naar EDL</string>
|
||||||
<string name="about">Over</string>
|
<string name="about">Over</string>
|
||||||
<string name="module_uninstall_confirm">Zeker van het verwijderen van module %s?</string>
|
<string name="module_uninstall_confirm">Zeker van het verwijderen van module %s?</string>
|
||||||
<string name="module_uninstall_success">%s verwijderd</string>
|
<string name="module_uninstall_success">%s is verwijderd</string>
|
||||||
<string name="module_uninstall_failed">Mislukt om te verwijderen: %s</string>
|
<string name="module_uninstall_failed">Mislukt om te verwijderen: %s</string>
|
||||||
<string name="module_version">Versie</string>
|
<string name="module_version">Versie</string>
|
||||||
<string name="module_author">Auteur</string>
|
<string name="module_author">Auteur</string>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<string name="refresh">Vernieuwen</string>
|
<string name="refresh">Vernieuwen</string>
|
||||||
<string name="show_system_apps">Toon systeem apps</string>
|
<string name="show_system_apps">Toon systeem apps</string>
|
||||||
<string name="hide_system_apps">Verberg systeem apps</string>
|
<string name="hide_system_apps">Verberg systeem apps</string>
|
||||||
<string name="send_log">Stuur Log</string>
|
<string name="send_log">Rapport Log</string>
|
||||||
<string name="safe_mode">Safe mode</string>
|
<string name="safe_mode">Safe mode</string>
|
||||||
<string name="reboot_to_apply">Herstart om effect te hebben</string>
|
<string name="reboot_to_apply">Herstart om effect te hebben</string>
|
||||||
<string name="module_magisk_conflict">Modules zijn uitgeschakeld omdat ze in conflict zijn met magisk!</string>
|
<string name="module_magisk_conflict">Modules zijn uitgeschakeld omdat ze in conflict zijn met magisk!</string>
|
||||||
@@ -73,11 +73,33 @@
|
|||||||
<string name="profile_selinux_rules">Regels</string>
|
<string name="profile_selinux_rules">Regels</string>
|
||||||
<string name="module_update">Update</string>
|
<string name="module_update">Update</string>
|
||||||
<string name="module_downloading">Downloaden van module: %s</string>
|
<string name="module_downloading">Downloaden van module: %s</string>
|
||||||
<string name="new_version_available">Nieuwe versie: %s is beschikbaar, klik om te downloaden</string>
|
<string name="new_version_available">Nieuwe versie: %s is beschikbaar,klik om te upgraden</string>
|
||||||
<string name="launch_app">Start</string>
|
<string name="launch_app">Start</string>
|
||||||
<string name="force_stop_app">Forceer Stop</string>
|
<string name="force_stop_app">Forceer Stop</string>
|
||||||
<string name="restart_app">Herstart</string>
|
<string name="restart_app">Herstart</string>
|
||||||
<string name="module_start_downloading">Begin met downloaden: %s</string>
|
<string name="module_start_downloading">Begin met downloaden: %s</string>
|
||||||
<string name="failed_to_update_sepolicy">Kan SELinux-regels niet bijwerken voor: %s</string>
|
<string name="failed_to_update_sepolicy">Kan SELinux-regels niet bijwerken voor: %s</string>
|
||||||
<string name="require_kernel_version">De huidige KernelSU-versie %d is te laag om de manager correct te laten functioneren. Upgrade naar versie %d of hoger!</string>
|
<string name="require_kernel_version">De huidige KernelSU-versie %d is te laag om de manager correct te laten functioneren. Upgrade naar versie %d of hoger!</string>
|
||||||
|
<string name="module_changelog">wijzigings logboek</string>
|
||||||
|
<string name="settings_profile_template">App-profiel Sjabloon</string>
|
||||||
|
<string name="app_profile_template_create">Maken Sjabloon</string>
|
||||||
|
<string name="app_profile_template_edit">Bewerkin Sjabloon</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Ongeldige sjabloon id</string>
|
||||||
|
<string name="app_profile_template_name">Naam</string>
|
||||||
|
<string name="app_profile_template_save">Redde</string>
|
||||||
|
<string name="app_profile_template_view">Bekijken Sjabloon</string>
|
||||||
|
<string name="app_profile_template_description">Beschrijving</string>
|
||||||
|
<string name="settings_profile_template_summary">Beheer lokale en online sjabloon van app-profiel</string>
|
||||||
|
<string name="app_profile_template_delete">Verwijderen</string>
|
||||||
|
<string name="app_profile_template_readonly">alleen lezen</string>
|
||||||
|
<string name="app_profile_template_id_exist">sjabloon id bestaat al!</string>
|
||||||
|
<string name="app_profile_template_sync">Synchroniseer online-sjablonen</string>
|
||||||
|
<string name="app_profile_template_save_failed">Mislukt naar opslaan sjabloon</string>
|
||||||
|
<string name="app_profile_template_import_empty">Klembord is leeg!</string>
|
||||||
|
<string name="app_profile_import_export">Importeren/Exporteren</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importeren vanaf klembord</string>
|
||||||
|
<string name="module_changelog_failed">Ophalen van wijzigingslogboek mislukt: %s</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exporteren naar klembord</string>
|
||||||
|
<string name="settings_check_update">Controleer update</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<string name="home_click_to_install">Clique para instalar</string>
|
<string name="home_click_to_install">Clique para instalar</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>
|
||||||
<string name="home_module_count">Módulos: %d</string>
|
<string name="home_module_count">Módulos: %d</string>
|
||||||
<string name="home_unsupported">Sem suporte</string>
|
<string name="home_unsupported">Sem suporte</string>
|
||||||
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
|
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
|
||||||
@@ -13,15 +13,15 @@
|
|||||||
<string name="home_manager_version">Versão do gerenciador</string>
|
<string name="home_manager_version">Versão do gerenciador</string>
|
||||||
<string name="home_fingerprint">Impressão digital</string>
|
<string name="home_fingerprint">Impressão digital</string>
|
||||||
<string name="home_selinux_status">Status do SELinux</string>
|
<string name="home_selinux_status">Status do SELinux</string>
|
||||||
<string name="selinux_status_disabled">Desabilitado</string>
|
<string name="selinux_status_disabled">Desativado</string>
|
||||||
<string name="selinux_status_enforcing">Execução</string>
|
<string name="selinux_status_enforcing">Impondo</string>
|
||||||
<string name="selinux_status_permissive">Permissivo</string>
|
<string name="selinux_status_permissive">Permissivo</string>
|
||||||
<string name="selinux_status_unknown">Desconhecido</string>
|
<string name="selinux_status_unknown">Desconhecido</string>
|
||||||
<string name="superuser">Superusuário</string>
|
<string name="superuser">SuperUsuário</string>
|
||||||
<string name="module_failed_to_enable">Falha ao ativar o módulo: %s</string>
|
<string name="module_failed_to_enable">Falha ao ativar o módulo: %s</string>
|
||||||
<string name="module_failed_to_disable">Falha ao desativar o módulo: %s</string>
|
<string name="module_failed_to_disable">Falha ao desativar o módulo: %s</string>
|
||||||
<string name="module_empty">Nenhum módulo instalado</string>
|
<string name="module_empty">Nenhum módulo instalado</string>
|
||||||
<string name="module">Módulos</string>
|
<string name="module">Módulo</string>
|
||||||
<string name="uninstall">Desinstalar</string>
|
<string name="uninstall">Desinstalar</string>
|
||||||
<string name="module_install">Instalar</string>
|
<string name="module_install">Instalar</string>
|
||||||
<string name="install">Instalar</string>
|
<string name="install">Instalar</string>
|
||||||
@@ -34,21 +34,21 @@
|
|||||||
<string name="reboot_edl">Reiniciar em modo EDL</string>
|
<string name="reboot_edl">Reiniciar em modo EDL</string>
|
||||||
<string name="about">Sobre</string>
|
<string name="about">Sobre</string>
|
||||||
<string name="module_uninstall_confirm">Tem certeza de que deseja desinstalar o módulo %s?</string>
|
<string name="module_uninstall_confirm">Tem certeza de que deseja desinstalar o módulo %s?</string>
|
||||||
<string name="module_uninstall_success">%s desinstalado</string>
|
<string name="module_uninstall_success">%s foi desinstalado</string>
|
||||||
<string name="module_uninstall_failed">Falha ao desinstalar: %s</string>
|
<string name="module_uninstall_failed">Falha ao desinstalar: %s</string>
|
||||||
<string name="module_version">Versão</string>
|
<string name="module_version">Versão</string>
|
||||||
<string name="module_author">Autor</string>
|
<string name="module_author">Autor</string>
|
||||||
<string name="module_overlay_fs_not_available">overlayfs não está disponível, o módulo não pode funcionar!</string>
|
<string name="module_overlay_fs_not_available">OverlayFS não está disponível. O módulo não pode funcionar!</string>
|
||||||
<string name="refresh">Atualizar</string>
|
<string name="refresh">Atualizar</string>
|
||||||
<string name="show_system_apps">Mostrar apps do sistema</string>
|
<string name="show_system_apps">Mostrar apps do sistema</string>
|
||||||
<string name="hide_system_apps">Ocultar apps do sistema</string>
|
<string name="hide_system_apps">Ocultar apps do sistema</string>
|
||||||
<string name="send_log">Enviar Log</string>
|
<string name="send_log">Reportar registro</string>
|
||||||
<string name="safe_mode">Modo de segurança</string>
|
<string name="safe_mode">Modo de segurança</string>
|
||||||
<string name="reboot_to_apply">Reinicie para entrar em vigor</string>
|
<string name="reboot_to_apply">Reinicie para entrar em vigor</string>
|
||||||
<string name="module_magisk_conflict">Os módulos estão desativados porque estão em conflito com os do Magisk!</string>
|
<string name="module_magisk_conflict">Os módulos estão desativados porque estão em conflito com os do Magisk!</string>
|
||||||
<string name="home_learn_kernelsu">Leia mais sobre o KernelSU</string>
|
<string name="home_learn_kernelsu">Leia mais sobre o KernelSU</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/pt_BR/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">Aprenda a instalar o KernelSU e usar os módulos</string>
|
<string name="home_click_to_learn_kernelsu">Aprenda como instalar o KernelSU e usar módulos</string>
|
||||||
<string name="home_support_title">Apoie-nos</string>
|
<string name="home_support_title">Apoie-nos</string>
|
||||||
<string name="home_support_content">KernelSU sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode agradecer enviando uma pequena doação.</string>
|
<string name="home_support_content">KernelSU sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode agradecer enviando uma pequena doação.</string>
|
||||||
<string name="about_source_code"><![CDATA[Veja o código-fonte no %1$s<br/>Junte-se ao nosso canal do %2$s]]></string>
|
<string name="about_source_code"><![CDATA[Veja o código-fonte no %1$s<br/>Junte-se ao nosso canal do %2$s]]></string>
|
||||||
@@ -64,21 +64,47 @@
|
|||||||
<string name="profile_groups">Grupos</string>
|
<string name="profile_groups">Grupos</string>
|
||||||
<string name="profile_capabilities">Capacidades</string>
|
<string name="profile_capabilities">Capacidades</string>
|
||||||
<string name="profile_selinux_context">Contexto do SELinux</string>
|
<string name="profile_selinux_context">Contexto do SELinux</string>
|
||||||
<string name="profile_umount_modules">Módulos não montados</string>
|
<string name="profile_umount_modules">Desmontar módulos</string>
|
||||||
<string name="failed_to_update_app_profile">Falha ao atualizar o Perfil do Aplicativo para %s</string>
|
<string name="failed_to_update_app_profile">Falha ao atualizar o Perfil do Aplicativo para %s</string>
|
||||||
<string name="settings_umount_modules_default">Não montar módulos por padrão</string>
|
<string name="settings_umount_modules_default">Desmontar módulos por padrão</string>
|
||||||
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Módulos não montados\" em Perfis de Aplicativos. Se ativado, removerá todas as modificações do módulo do 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="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU 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 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>
|
||||||
<string name="module_update">Atualizar</string>
|
<string name="module_update">Atualizar</string>
|
||||||
<string name="module_downloading">Baixando módulo: %s</string>
|
<string name="module_downloading">Baixando módulo: %s</string>
|
||||||
<string name="module_start_downloading">Iniciar o download: %s</string>
|
<string name="module_start_downloading">Iniciar download: %s</string>
|
||||||
<string name="new_version_available">Nova versão: %s está disponível, clique para atualizar</string>
|
<string name="new_version_available">Nova versão: %s está disponível, clique para atualizar.</string>
|
||||||
<string name="launch_app">Iniciar</string>
|
<string name="launch_app">Iniciar</string>
|
||||||
<string name="force_stop_app">Forçar parada</string>
|
<string name="force_stop_app">Forçar parada</string>
|
||||||
<string name="restart_app">Reiniciar</string>
|
<string name="restart_app">Reiniciar</string>
|
||||||
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para: %s</string>
|
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para: %s</string>
|
||||||
<string name="require_kernel_version">A versão atual do KernelSU %d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %d ou superior!</string>
|
<string name="require_kernel_version">A versão atual do KernelSU %d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %d ou superior!</string>
|
||||||
<string name="module_changelog">Registro de alterações</string>
|
<string name="module_changelog">Registro de alterações</string>
|
||||||
|
<string name="app_profile_template_import_success">Importado com sucesso</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Exportar para a área de transferência</string>
|
||||||
|
<string name="app_profile_template_export_empty">Não foi possível encontrar o modelo local para exportar!</string>
|
||||||
|
<string name="app_profile_template_id_exist">O ID do modelo já existe!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Importar da área de transferência</string>
|
||||||
|
<string name="module_changelog_failed">Falha ao buscar o registro de alterações: %s</string>
|
||||||
|
<string name="app_profile_template_name">Nome</string>
|
||||||
|
<string name="app_profile_template_id_invalid">ID do modelo inválido</string>
|
||||||
|
<string name="app_profile_template_sync">Sincronizar modelos online</string>
|
||||||
|
<string name="app_profile_template_create">Criar modelo</string>
|
||||||
|
<string name="app_profile_template_readonly">Somente leitura</string>
|
||||||
|
<string name="app_profile_import_export">Importar/Exportar</string>
|
||||||
|
<string name="app_profile_template_save_failed">Falha ao salvar o modelo</string>
|
||||||
|
<string name="app_profile_template_edit">Editar modelo</string>
|
||||||
|
<string name="app_profile_template_id">ID</string>
|
||||||
|
<string name="settings_profile_template">Modelo do Perfil do Aplicativo</string>
|
||||||
|
<string name="app_profile_template_description">Descrição</string>
|
||||||
|
<string name="app_profile_template_save">Salvar</string>
|
||||||
|
<string name="settings_profile_template_summary">Gerencie o modelo local e online do Perfil do Aplicativo</string>
|
||||||
|
<string name="app_profile_template_delete">Excluir</string>
|
||||||
|
<string name="app_profile_template_import_empty">A área de transferência está vazia!</string>
|
||||||
|
<string name="app_profile_template_view">Ver modelo</string>
|
||||||
|
<string name="settings_check_update">Verificar atualização</string>
|
||||||
|
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
|
||||||
|
<string name="grant_root_failed">Falha ao conceder acesso root!</string>
|
||||||
|
<string name="open">Abrir</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<string name="selinux_status_enforcing">Obligatoriu</string>
|
<string name="selinux_status_enforcing">Obligatoriu</string>
|
||||||
<string name="selinux_status_permissive">Permisiv</string>
|
<string name="selinux_status_permissive">Permisiv</string>
|
||||||
<string name="selinux_status_unknown">Necunoscut</string>
|
<string name="selinux_status_unknown">Necunoscut</string>
|
||||||
<string name="superuser">Super-utilizator</string>
|
<string name="superuser">Super-Utilizator</string>
|
||||||
<string name="module_failed_to_enable">Activarea modulului %s a eșuat</string>
|
<string name="module_failed_to_enable">Activarea modulului %s a eșuat</string>
|
||||||
<string name="module_failed_to_disable">Dezactivarea modulului %s a eșuat</string>
|
<string name="module_failed_to_disable">Dezactivarea modulului %s a eșuat</string>
|
||||||
<string name="module_empty">Niciun modul instalat</string>
|
<string name="module_empty">Niciun modul instalat</string>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<string name="refresh">Reîmprospătează</string>
|
<string name="refresh">Reîmprospătează</string>
|
||||||
<string name="show_system_apps">Arată aplicațiile de sistem</string>
|
<string name="show_system_apps">Arată aplicațiile de sistem</string>
|
||||||
<string name="hide_system_apps">Ascunde aplicațiile de sistem</string>
|
<string name="hide_system_apps">Ascunde aplicațiile de sistem</string>
|
||||||
<string name="send_log">Trimite jurnal</string>
|
<string name="send_log">Raportează jurnal</string>
|
||||||
<string name="safe_mode">Mod sigur</string>
|
<string name="safe_mode">Mod sigur</string>
|
||||||
<string name="reboot_to_apply">Repornește pentru ca modificările să intre în vigoare</string>
|
<string name="reboot_to_apply">Repornește pentru ca modificările să intre în vigoare</string>
|
||||||
<string name="module_magisk_conflict">Modulele sunt dezactivate deoarece sunt în conflict cu cele ale Magisk-ului!</string>
|
<string name="module_magisk_conflict">Modulele sunt dezactivate deoarece sunt în conflict cu cele ale Magisk-ului!</string>
|
||||||
@@ -80,4 +80,28 @@
|
|||||||
<string name="restart_app">Repornește</string>
|
<string name="restart_app">Repornește</string>
|
||||||
<string name="require_kernel_version">Versiunea actuală a KernelSU %d este prea mică pentru ca managerul să funcționeze corect. Actualizează la versiunea %d sau o versiune superioară!</string>
|
<string name="require_kernel_version">Versiunea actuală a KernelSU %d este prea mică pentru ca managerul să funcționeze corect. Actualizează la versiunea %d sau o versiune superioară!</string>
|
||||||
<string name="module_changelog">Jurnalul modificărilor</string>
|
<string name="module_changelog">Jurnalul modificărilor</string>
|
||||||
|
<string name="app_profile_template_import_success">Importat cu succes</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Export în clipboard</string>
|
||||||
|
<string name="app_profile_template_export_empty">Nu există șabloane locale de exportat!</string>
|
||||||
|
<string name="app_profile_template_id_exist">ID-ul șablonului există deja!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Import din clipboard</string>
|
||||||
|
<string name="module_changelog_failed">Preluarea jurnalului de modificări a eșuat: %s</string>
|
||||||
|
<string name="app_profile_template_name">Nume</string>
|
||||||
|
<string name="app_profile_template_id_invalid">ID șablon nevalid</string>
|
||||||
|
<string name="app_profile_template_sync">Sincronizează șabloanele online</string>
|
||||||
|
<string name="app_profile_template_create">Creează un șablon</string>
|
||||||
|
<string name="app_profile_template_readonly">doar citire</string>
|
||||||
|
<string name="app_profile_import_export">Import/Export</string>
|
||||||
|
<string name="app_profile_template_save_failed">Nu s-a salvat șablonul</string>
|
||||||
|
<string name="app_profile_template_edit">Editează șablonul</string>
|
||||||
|
<string name="app_profile_template_id">ID</string>
|
||||||
|
<string name="settings_profile_template">Șablon de profil al aplicației</string>
|
||||||
|
<string name="app_profile_template_description">Descriere</string>
|
||||||
|
<string name="app_profile_template_save">Salvează</string>
|
||||||
|
<string name="settings_profile_template_summary">Gestionează șablonul local și online al Profilului aplicației</string>
|
||||||
|
<string name="app_profile_template_delete">Șterge</string>
|
||||||
|
<string name="app_profile_template_import_empty">Clipboard-ul este gol!</string>
|
||||||
|
<string name="app_profile_template_view">Vizualizare șablon</string>
|
||||||
|
<string name="settings_check_update">Verifică actualizarea</string>
|
||||||
|
<string name="settings_check_update_summary">Se verifică automat actualizările când deschizi aplicația</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<string name="home_click_to_install">Нажмите, чтобы установить</string>
|
<string name="home_click_to_install">Нажмите, чтобы установить</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">Суперпользователи: %d</string>
|
||||||
<!--Don't translate this string!-->
|
<!--Don't translate this string!-->
|
||||||
<string name="home_module_count">Модули: %d</string>
|
<string name="home_module_count">Модули: %d</string>
|
||||||
<string name="home_unsupported">Не поддерживается</string>
|
<string name="home_unsupported">Не поддерживается</string>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<string name="module_version">Версия</string>
|
<string name="module_version">Версия</string>
|
||||||
<string name="module_author">Автор</string>
|
<string name="module_author">Автор</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>
|
||||||
<string name="show_system_apps">Показать системные приложения</string>
|
<string name="show_system_apps">Показать системные приложения</string>
|
||||||
<string name="hide_system_apps">Скрыть системные приложения</string>
|
<string name="hide_system_apps">Скрыть системные приложения</string>
|
||||||
<string name="send_log">Отправить лог</string>
|
<string name="send_log">Отправить лог</string>
|
||||||
@@ -84,4 +84,30 @@
|
|||||||
<string name="restart_app">Перезапустить</string>
|
<string name="restart_app">Перезапустить</string>
|
||||||
<string name="require_kernel_version">Текущая версия KernelSU %d слишком низкая для правильной работы менеджера. Пожалуйста, обновите до версии %d или выше!</string>
|
<string name="require_kernel_version">Текущая версия KernelSU %d слишком низкая для правильной работы менеджера. Пожалуйста, обновите до версии %d или выше!</string>
|
||||||
<string name="module_changelog">Список изменений</string>
|
<string name="module_changelog">Список изменений</string>
|
||||||
|
<string name="app_profile_template_import_success">Успешный импорт</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Экспортировать в буфер обмена</string>
|
||||||
|
<string name="app_profile_template_export_empty">Нет локальных шаблонов для экспорта!</string>
|
||||||
|
<string name="app_profile_template_id_exist">Шаблон с таким id уже существует!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Импортировать из буфера обмена</string>
|
||||||
|
<string name="module_changelog_failed">Не удалось получить список изменений: %s</string>
|
||||||
|
<string name="app_profile_template_name">Название</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Неверный id шаблона</string>
|
||||||
|
<string name="app_profile_template_sync">Синхронизировать онлайн-шаблоны</string>
|
||||||
|
<string name="app_profile_template_create">Создать шаблон</string>
|
||||||
|
<string name="app_profile_template_readonly">только чтение</string>
|
||||||
|
<string name="app_profile_import_export">Импорт/Экспорт</string>
|
||||||
|
<string name="app_profile_template_save_failed">Не удалось сохранить шаблон</string>
|
||||||
|
<string name="app_profile_template_edit">Редактирование шаблона</string>
|
||||||
|
<string name="app_profile_template_id">Идентификационный номер</string>
|
||||||
|
<string name="settings_profile_template">Шаблон профиля приложения</string>
|
||||||
|
<string name="app_profile_template_description">Описание</string>
|
||||||
|
<string name="app_profile_template_save">Сохранить</string>
|
||||||
|
<string name="settings_profile_template_summary">Управление локальным и онлайн-шаблоном профиля приложения</string>
|
||||||
|
<string name="app_profile_template_delete">Удалить</string>
|
||||||
|
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
|
||||||
|
<string name="app_profile_template_view">Просмотр шаблона</string>
|
||||||
|
<string name="settings_check_update">Проверка обновления</string>
|
||||||
|
<string name="settings_check_update_summary">Автоматическая проверка обновлений при открытии приложения</string>
|
||||||
|
<string name="grant_root_failed">Не удалось выдать root!</string>
|
||||||
|
<string name="open">Открыть</string>
|
||||||
</resources>
|
</resources>
|
||||||
105
manager/app/src/main/res/values-sl/strings.xml
Normal file
105
manager/app/src/main/res/values-sl/strings.xml
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="home_click_to_install">Klikni za namestitev</string>
|
||||||
|
<string name="home_working">V obdelavi</string>
|
||||||
|
<string name="home_working_version">Verzija: %d</string>
|
||||||
|
<string name="home_superuser_count">Superuporabniki: %d</string>
|
||||||
|
<string name="home_unsupported_reason">KernelSU podpira samo GKI kernele</string>
|
||||||
|
<string name="home_kernel">Kernel</string>
|
||||||
|
<string name="home_manager_version">Verzija upravitelja</string>
|
||||||
|
<string name="home_fingerprint">Prstni odtis</string>
|
||||||
|
<string name="home_selinux_status">SELinux status</string>
|
||||||
|
<string name="selinux_status_disabled">Onemogočeno</string>
|
||||||
|
<string name="selinux_status_unknown">Neznano</string>
|
||||||
|
<string name="module_failed_to_disable">Napaka pri onemogočanju modula: %s</string>
|
||||||
|
<string name="module_empty">Ni nameščenih modulov</string>
|
||||||
|
<string name="module">Modul</string>
|
||||||
|
<string name="uninstall">Odmesti</string>
|
||||||
|
<string name="module_install">Namesti</string>
|
||||||
|
<string name="install">Namesti</string>
|
||||||
|
<string name="reboot_userspace">Mehki ponovni zagon</string>
|
||||||
|
<string name="reboot_recovery">Ponovni zagon v Recovery</string>
|
||||||
|
<string name="reboot_bootloader">Ponovni zagon v Bootloader</string>
|
||||||
|
<string name="reboot_edl">Ponovni zagon v EDL</string>
|
||||||
|
<string name="module_uninstall_confirm">Ste prepričani, da želite odstraniti modul %s?</string>
|
||||||
|
<string name="module_uninstall_success">%s je odmeščen</string>
|
||||||
|
<string name="module_author">Avtor</string>
|
||||||
|
<string name="module_overlay_fs_not_available">overlayfs ni na voljo, modul ne more delovati!</string>
|
||||||
|
<string name="hide_system_apps">Skrij prikaz sistemskih aplikacij</string>
|
||||||
|
<string name="send_log">Prijavite dnevnik</string>
|
||||||
|
<string name="home_learn_kernelsu">Naučite se KernelSU</string>
|
||||||
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
|
<string name="home_click_to_learn_kernelsu">Naučite se, kako namestiti KernelSU in uporabiti module</string>
|
||||||
|
<string name="about_source_code">Glej odprto kodo na %1$s<br/>Pridružite se našem %2$s kanalu</string>
|
||||||
|
<string name="profile_default">Privzeto</string>
|
||||||
|
<string name="profile_template">Predloga</string>
|
||||||
|
<string name="profile_namespace">Imenski prostor vmestitve</string>
|
||||||
|
<string name="profile_namespace_inherited">Podedovano</string>
|
||||||
|
<string name="profile_namespace_global">Globalno</string>
|
||||||
|
<string name="profile_namespace_individual">Pozameznik</string>
|
||||||
|
<string name="profile_capabilities">Zmožnosti</string>
|
||||||
|
<string name="profile_umount_modules">Izvrzi module</string>
|
||||||
|
<string name="settings_umount_modules_default">Po privzetem izvrzi module</string>
|
||||||
|
<string name="profile_selinux_domain">Domena</string>
|
||||||
|
<string name="module_update">Posodobitev</string>
|
||||||
|
<string name="module_downloading">Nalaganje modula: %s</string>
|
||||||
|
<string name="launch_app">Zaženi</string>
|
||||||
|
<string name="restart_app">Ponovni zagon</string>
|
||||||
|
<string name="module_changelog">Dnevnik sprememb</string>
|
||||||
|
<string name="settings_profile_template">Predloga za aplikacijski profil</string>
|
||||||
|
<string name="home">Domov</string>
|
||||||
|
<string name="home_module_count">Moduli: %d</string>
|
||||||
|
<string name="home_unsupported">Ne podpira</string>
|
||||||
|
<string name="superuser">SuperUporabnik</string>
|
||||||
|
<string name="module_failed_to_enable">Napaka pri omogočanju modula: %s</string>
|
||||||
|
<string name="reboot">Znova zaženi</string>
|
||||||
|
<string name="settings">Nastavitve</string>
|
||||||
|
<string name="reboot_download">Ponovni zagon v Download</string>
|
||||||
|
<string name="about">O nas</string>
|
||||||
|
<string name="module_version">Verzija</string>
|
||||||
|
<string name="module_uninstall_failed">Napaka pri odmeščanju: %s</string>
|
||||||
|
<string name="refresh">Osveži</string>
|
||||||
|
<string name="safe_mode">Varni način</string>
|
||||||
|
<string name="reboot_to_apply">Za uveljavitev je potreben ponovni zagon</string>
|
||||||
|
<string name="show_system_apps">Prikaz sistemskih aplikacij</string>
|
||||||
|
<string name="module_magisk_conflict">Moduli so onemogočeni, ker so v konfliktu z Magiskovimi!</string>
|
||||||
|
<string name="home_support_title">Podprite nas</string>
|
||||||
|
<string name="profile_custom">Po meri</string>
|
||||||
|
<string name="profile_name">Ime profila</string>
|
||||||
|
<string name="profile_groups">Skupine</string>
|
||||||
|
<string name="profile_selinux_context">SELinux kontekst</string>
|
||||||
|
<string name="home_support_content">KernelSU je, in bo vedno brezplačen in odprtokoden. Kljub temu, nam lahko z donacijo pokažete, da vam je mar.</string>
|
||||||
|
<string name="failed_to_update_app_profile">Napaka pri posodobitvi aplikacijskega profila za %s</string>
|
||||||
|
<string name="require_kernel_version">Za pravilno funkionalnost upravitelja je trenutna KernelSU verzija %d prenizka. Potrebna je nadgradnja na verzijo %d ali več!</string>
|
||||||
|
<string name="settings_umount_modules_default_summary">Globalno privzeta vrednost za \"Izvrzi module\" v aplikacijskih profilih. Če je omogočena, bo to odstranilo vse sistemske modifikacije modulov za aplikacije, ki nimajo nastavljenega profila.</string>
|
||||||
|
<string name="profile_umount_modules_summary">Omogočanje te opcije bo dovolilo KernelSU, da obnovi vse zaradi modulov spremenjene datoteke za to aplikacijo.</string>
|
||||||
|
<string name="force_stop_app">Prisilna ustavitev</string>
|
||||||
|
<string name="profile_selinux_rules">Pravila</string>
|
||||||
|
<string name="module_start_downloading">Začni z nalaganjem: %s</string>
|
||||||
|
<string name="new_version_available">Na voljo je nova verzija: %s, kliknite za nadgradnjo</string>
|
||||||
|
<string name="failed_to_update_sepolicy">Napaka pri posodobitvi SELinux pravil za: %s</string>
|
||||||
|
<string name="home_not_installed">Ni nameščeno</string>
|
||||||
|
<string name="selinux_status_enforcing">Enforcing</string>
|
||||||
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
|
<string name="app_profile_template_create">Ustvari predlogo</string>
|
||||||
|
<string name="app_profile_template_edit">Uredi predlogo</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Neveljaven id predloge</string>
|
||||||
|
<string name="app_profile_template_description">Opis</string>
|
||||||
|
<string name="app_profile_template_save">Shrani</string>
|
||||||
|
<string name="app_profile_template_delete">Odstrani</string>
|
||||||
|
<string name="app_profile_template_readonly">le za branje</string>
|
||||||
|
<string name="app_profile_template_id_exist">id predloge že obstaja!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Uvoz iz odložišča</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Izvoz v odložišče</string>
|
||||||
|
<string name="app_profile_template_export_empty">Lokalna predloga za izvoz ni bila najdena!</string>
|
||||||
|
<string name="app_profile_template_save_failed">Napaka pri shranjevanju predloge</string>
|
||||||
|
<string name="app_profile_template_import_empty">Odložišče je prazno!</string>
|
||||||
|
<string name="settings_profile_template_summary">Upravljaj z lokalnimi in spletnimi predlogami za aplikacijski profil</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="app_profile_template_name">Ime</string>
|
||||||
|
<string name="app_profile_template_view">Ogled predloge</string>
|
||||||
|
<string name="app_profile_template_import_success">Uvoz uspešen</string>
|
||||||
|
<string name="app_profile_template_sync">Sinhroniziraj predloge iz spleta</string>
|
||||||
|
<string name="app_profile_import_export">Uvoz/Izvoz</string>
|
||||||
|
<string name="module_changelog_failed">Napaka pri pridobivanju dnevnika sprememb: %s</string>
|
||||||
|
</resources>
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="home_superuser_count">Superkorisnici</string>
|
<string name="home_superuser_count">Superkorisnici</string>
|
||||||
<string name="home_module_count">Moduli: %d</string>
|
<string name="home_module_count">Moduli: %d</string>
|
||||||
<string name="home_click_to_install">Kliknite da instalirate</string>
|
<string name="home_click_to_install">Додирните да бисте инсталирали</string>
|
||||||
<string name="home">дом</string>
|
<string name="home">Почетна</string>
|
||||||
<string name="home_not_installed">Nije instalirano</string>
|
<string name="home_not_installed">Није инсталирано</string>
|
||||||
|
<string name="home_working_version">Верзија: %d</string>
|
||||||
|
<string name="home_working">Ради</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -12,4 +12,9 @@
|
|||||||
<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="home_not_installed">ఇన్స్టాల్ చేయలేదు</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>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<string name="show_system_apps">แสดงแอประบบ</string>
|
<string name="show_system_apps">แสดงแอประบบ</string>
|
||||||
<string name="hide_system_apps">ซ่อนแอประบบ</string>
|
<string name="hide_system_apps">ซ่อนแอประบบ</string>
|
||||||
<string name="refresh">รีเฟรช</string>
|
<string name="refresh">รีเฟรช</string>
|
||||||
<string name="send_log">ส่ง Log</string>
|
<string name="send_log">ส่งรายงาน Log</string>
|
||||||
<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>
|
||||||
@@ -80,4 +80,30 @@
|
|||||||
<string name="failed_to_update_sepolicy">ไม่สามารถอัปเดตกฎ SElinux สำหรับ: %s ได้</string>
|
<string name="failed_to_update_sepolicy">ไม่สามารถอัปเดตกฎ SElinux สำหรับ: %s ได้</string>
|
||||||
<string name="require_kernel_version">KernelSU เวอร์ชั่น %d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถใช้งานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชั่น %d หรือที่สูงกว่า!</string>
|
<string name="require_kernel_version">KernelSU เวอร์ชั่น %d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถใช้งานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชั่น %d หรือที่สูงกว่า!</string>
|
||||||
<string name="module_changelog">บันทึกการเปลี่ยนแปลง</string>
|
<string name="module_changelog">บันทึกการเปลี่ยนแปลง</string>
|
||||||
|
<string name="app_profile_template_import_success">นำเข้าเสร็จสิ้น</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">ส่งออกไปยังคลิปบอร์ด</string>
|
||||||
|
<string name="app_profile_template_export_empty">ไม่พบเทมเพลตในเครื่องที่จะส่งออก!</string>
|
||||||
|
<string name="app_profile_template_id_exist">มีไอดีเทมเพลตนี้อยู่แล้ว!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">นำเข้าจากคลิปบอร์ด</string>
|
||||||
|
<string name="app_profile_template_name">ชื่อ</string>
|
||||||
|
<string name="app_profile_template_id_invalid">ไอดีเทมเพลตไม่ถูกต้อง</string>
|
||||||
|
<string name="app_profile_template_sync">ซิงค์เทมเพลตออนไลน์</string>
|
||||||
|
<string name="app_profile_template_create">สร้างเทมเพลต</string>
|
||||||
|
<string name="app_profile_template_readonly">อ่านเท่านั้น</string>
|
||||||
|
<string name="app_profile_import_export">นำเข้า/ส่งออก</string>
|
||||||
|
<string name="app_profile_template_save_failed">ไม่สามารถบันทึกเทมเพลต</string>
|
||||||
|
<string name="app_profile_template_edit">แก้ไขเทมเพลต</string>
|
||||||
|
<string name="app_profile_template_id">ไอดี</string>
|
||||||
|
<string name="settings_profile_template">เทมเพลตโปรไฟล์แอป</string>
|
||||||
|
<string name="app_profile_template_description">คำอธิบาย</string>
|
||||||
|
<string name="app_profile_template_save">บันทึก</string>
|
||||||
|
<string name="settings_profile_template_summary">จัดการเทมเพลตโปรไฟล์แอปในเครื่องและเทมเพลตออนไลน์</string>
|
||||||
|
<string name="app_profile_template_delete">ลบ</string>
|
||||||
|
<string name="app_profile_template_import_empty">คลิปบอร์ดว่างเปล่า!</string>
|
||||||
|
<string name="app_profile_template_view">ดูเทมเพลต</string>
|
||||||
|
<string name="module_changelog_failed">ดึงข้อมูลบันทึกการเปลี่ยนแปลงล้มเหลว: %s</string>
|
||||||
|
<string name="open">เปิด</string>
|
||||||
|
<string name="grant_root_failed">ไม่สามารถให้สิทธิ์รูทได้!</string>
|
||||||
|
<string name="settings_check_update">ตรวจสอบการอัปเดต</string>
|
||||||
|
<string name="settings_check_update_summary">ตรวจสอบการอัปเดตโดยอัตโนมัติเมื่อเปิดแอป</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="home">Ana menü</string>
|
<string name="app_name" translatable="false">KernelSU</string>
|
||||||
<string name="home_not_installed">Yüklü değil</string>
|
<string name="home">Ana Sayfa</string>
|
||||||
<string name="home_click_to_install">Yüklemek için tıkla</string>
|
<string name="home_not_installed">Yüklenmedi</string>
|
||||||
|
<string name="home_click_to_install">Yüklemek için tıklayın</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>
|
||||||
<string name="home_module_count">Modüller: %d</string>
|
<string name="home_module_count">Modüller: %d</string>
|
||||||
<string name="home_unsupported">Desteklenmiyor</string>
|
<string name="home_unsupported">Desteklenmiyor</string>
|
||||||
<string name="home_unsupported_reason">KernelSU şu an yalnızca GKI çekirdeklerini destekliyor</string>
|
<string name="home_unsupported_reason">KernelSU şimdilik sadece GKI çekirdeklerini destekliyor</string>
|
||||||
<string name="home_kernel">Kernel</string>
|
<string name="home_kernel">Çekirdek</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_fingerprint">Parmak İzi</string>
|
<string name="home_fingerprint">Parmak izi</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">Enforcing</string>
|
<string name="selinux_status_enforcing">Etkin (Enforcing)</string>
|
||||||
<string name="selinux_status_permissive">Permissive</string>
|
<string name="selinux_status_permissive">Serbest (Permissive)</string>
|
||||||
<string name="selinux_status_unknown">Bilinmiyor</string>
|
<string name="selinux_status_unknown">Bilinmiyor</string>
|
||||||
<string name="superuser">Süper kullanıcı</string>
|
<string name="superuser">Süper kullanıcı</string>
|
||||||
<string name="module_failed_to_enable">Modül etkinleştirilemedi: %s</string>
|
<string name="module_failed_to_enable">Modül etkinleştirilemedi: %s</string>
|
||||||
@@ -28,33 +29,33 @@
|
|||||||
<string name="reboot">Cihazı yeniden başlat</string>
|
<string name="reboot">Cihazı yeniden başlat</string>
|
||||||
<string name="settings">Ayarlar</string>
|
<string name="settings">Ayarlar</string>
|
||||||
<string name="reboot_userspace">Hızlı yeniden başlat</string>
|
<string name="reboot_userspace">Hızlı yeniden başlat</string>
|
||||||
<string name="reboot_recovery">Kurtarma modunda başlat</string>
|
<string name="reboot_recovery">Kurtarma modunda yeniden başlat</string>
|
||||||
<string name="reboot_bootloader">Bootloader modunda başlat</string>
|
<string name="reboot_bootloader">Önyükleyici modunda yeniden başlat</string>
|
||||||
<string name="reboot_download">İndirme modunda başlat</string>
|
<string name="reboot_download">İndirme modunda yeniden başlat</string>
|
||||||
<string name="reboot_edl">EDL modunda başlat</string>
|
<string name="reboot_edl">EDL modunda yeniden başlat</string>
|
||||||
<string name="about">Hakkında</string>
|
<string name="about">Hakkında</string>
|
||||||
<string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinizden emin misiniz?</string>
|
<string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinizden emin misiniz?</string>
|
||||||
<string name="module_uninstall_success">%s kaldırıldı</string>
|
<string name="module_uninstall_success">%s kaldırıldı</string>
|
||||||
<string name="module_uninstall_failed">%s kaldırılamadı</string>
|
<string name="module_uninstall_failed">Kaldırma başarısız: %s</string>
|
||||||
<string name="module_version">Sürüm</string>
|
<string name="module_version">Sürüm</string>
|
||||||
<string name="module_author">Geliştirici</string>
|
<string name="module_author">Geliştirici</string>
|
||||||
<string name="module_overlay_fs_not_available">overlayfs mevcut değil, modül çalışamaz!</string>
|
<string name="module_overlay_fs_not_available">overlayfs mevcut değil, modül çalışamaz!</string>
|
||||||
<string name="refresh">Yenile</string>
|
<string name="refresh">Yenile</string>
|
||||||
<string name="show_system_apps">Sistem uygulamalarını göster</string>
|
<string name="show_system_apps">Sistem uygulamalarını göster</string>
|
||||||
<string name="hide_system_apps">Sistem uygulamalarını gizle</string>
|
<string name="hide_system_apps">Sistem uygulamalarını gizle</string>
|
||||||
<string name="send_log">Log gönder</string>
|
<string name="send_log">Günlük raporu gönder</string>
|
||||||
<string name="safe_mode">Güvenli mod</string>
|
<string name="safe_mode">Güvenli mod</string>
|
||||||
<string name="reboot_to_apply">Değişiklilerin kaydedilmesi için cihazı yeniden başlat</string>
|
<string name="reboot_to_apply">Değişikliklerin uygulanması için cihazı yeniden başlat</string>
|
||||||
<string name="module_magisk_conflict">Modüller Magisk ile çakıştığı için devre dışı bırakıldı!</string>
|
<string name="module_magisk_conflict">Modüller, Magisk ile çakıştığı için devre dışı bırakıldı!</string>
|
||||||
<string name="home_learn_kernelsu">KernelSU\'yu öğren</string>
|
<string name="home_learn_kernelsu">KernelSU\'yu öğrenin</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">KernelSU\'yu nasıl kuracağınızı ve modülleri nasıl kullanacağınızı öğrenin</string>
|
<string name="home_click_to_learn_kernelsu">KernelSU\'nun nasıl kurulacağını ve modüllerin nasıl kullanılacağını öğrenin</string>
|
||||||
<string name="home_support_title">Bizi destekle</string>
|
<string name="home_support_title">Bizi destekleyin</string>
|
||||||
<string name="home_support_content">KernelSU ücretsiz ve açık kaynaktır ve her zaman öyle kalacaktır. Ancak bağış yaparak bize değer verdiğinizi gösterebilirsiniz.</string>
|
<string name="home_support_content">KernelSU ücretsiz ve açık kaynaklı bir yazılımdır ve her zaman öyle kalacaktır. Ancak bağış yaparak bize destek olduğunuzu gösterebilirsiniz.</string>
|
||||||
<string name="about_source_code"><![CDATA[%1$s kaynak kodunu görüntüle<br/>%2$s kanalımıza katılın]]></string>
|
<string name="about_source_code">Kaynak kodunu %1$s\'tan görüntüleyin<br/>%2$s kanalımıza katılın</string>
|
||||||
<string name="profile">Uygulama profili</string>
|
<string name="profile" translatable="false">Uygulama profili</string>
|
||||||
<string name="profile_default">Varsayılan</string>
|
<string name="profile_default">Varsayılan</string>
|
||||||
<string name="profile_template">Örnek</string>
|
<string name="profile_template">Şablon</string>
|
||||||
<string name="profile_custom">Özel</string>
|
<string name="profile_custom">Özel</string>
|
||||||
<string name="profile_name">Profil adı</string>
|
<string name="profile_name">Profil adı</string>
|
||||||
<string name="profile_namespace">Ad alanını bağla</string>
|
<string name="profile_namespace">Ad alanını bağla</string>
|
||||||
@@ -62,23 +63,49 @@
|
|||||||
<string name="profile_namespace_global">Küresel</string>
|
<string name="profile_namespace_global">Küresel</string>
|
||||||
<string name="profile_namespace_individual">Bireysel</string>
|
<string name="profile_namespace_individual">Bireysel</string>
|
||||||
<string name="profile_groups">Gruplar</string>
|
<string name="profile_groups">Gruplar</string>
|
||||||
<string name="profile_capabilities">Yetkiler</string>
|
<string name="profile_capabilities">Yetkinlikler</string>
|
||||||
<string name="profile_selinux_context">SELinux içeriği</string>
|
<string name="profile_selinux_context">SELinux içeriği</string>
|
||||||
<string name="profile_umount_modules">Modüllerin bağlantısını kes</string>
|
<string name="profile_umount_modules">Modüllerin bağlantısını kes</string>
|
||||||
<string name="failed_to_update_app_profile">%s için uygulama profili güncellenemedi.</string>
|
<string name="failed_to_update_app_profile">%s için uygulama profili güncellenemedi.</string>
|
||||||
<string name="settings_umount_modules_default">Varsayılan olarak modüllerin bağlantısını kesin</string>
|
<string name="require_kernel_version">Mevcut KernelSU sürümü %d, yöneticinin düzgün çalışabilmesi için çok düşük. Lütfen %d veya daha yüksek bir sürüme güncelleyin!</string>
|
||||||
<string name="settings_umount_modules_default_summary">Uygulama profillerindeki \"Modüllerin bağlantısını kes\" seçeneği için varsayılan değer. Etkinleştirilirse, profil ayarı yapılmamış uygulamalar için modüllerin sistemde yaptığı tüm değişiklikler kaldırılacaktır.</string>
|
<string name="settings_umount_modules_default">Varsayılan olarak modüllerin bağlantısını kes</string>
|
||||||
<string name="profile_umount_modules_summary">Bu seçeneğin etkinleştirilmesi ile, bu uygulama için modüller tarafından değiştirilen tüm dosyaların KernelSU tarafından geri alınmasına izin verilecektir.</string>
|
<string name="settings_umount_modules_default_summary">Uygulama profilindeki \"Modüllerin bağlantısını kes\" seçeneği için varsayılan değer. Etkinleştirilirse, profil ayarı yapılmamış uygulamalar için modüllerin sistemde yaptığı tüm değişiklikler kaldırılacaktır.</string>
|
||||||
<string name="profile_selinux_domain">Ad alanı</string>
|
<string name="profile_umount_modules_summary">Bu seçeneği etkinleştirmek, KernelSU\'nun bu uygulama için modüller tarafından değiştirilen dosyaları geri yüklemesine izin verir.</string>
|
||||||
|
<string name="profile_selinux_domain">İsim alanı</string>
|
||||||
<string name="profile_selinux_rules">Kurallar</string>
|
<string name="profile_selinux_rules">Kurallar</string>
|
||||||
<string name="module_update">Güncelle</string>
|
<string name="module_update">Güncelle</string>
|
||||||
<string name="module_downloading">Modül indiriliyor: %s</string>
|
<string name="module_downloading">Modül indiriliyor: %s</string>
|
||||||
<string name="module_start_downloading">İndirme başladı: %s</string>
|
<string name="module_start_downloading">İndirme başladı: %s</string>
|
||||||
<string name="new_version_available">Yeni sürüm: %s mevcut, güncellemek için tıklayın</string>
|
<string name="new_version_available">Yeni sürüm: %s mevcut, güncellemek için tıklayın</string>
|
||||||
<string name="launch_app">Uygulamayı çalıştır</string>
|
<string name="launch_app">Uygulamayı başlat</string>
|
||||||
<string name="force_stop_app">Uygulamayı durmaya zorla</string>
|
<string name="force_stop_app">Uygulamayı durmaya zorla</string>
|
||||||
<string name="restart_app">Uygulamayı yeniden başlat</string>
|
<string name="restart_app">Uygulamayı yeniden başlat</string>
|
||||||
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi</string>
|
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi.</string>
|
||||||
<string name="require_kernel_version">Mevcut KernelSU sürümü %d, yöneticinin düzgün çalışması için çok düşük. Lütfen %d veya daha yüksek bir sürüme yükseltin!</string>
|
<string name="module_changelog">Değişiklik geçmişi</string>
|
||||||
<string name="module_changelog">Değişiklik listesi</string>
|
<string name="settings_profile_template">Uygulama profili şablonu</string>
|
||||||
|
<string name="settings_profile_template_summary">Yerel ve çevrimiçi uygulama profili şablonlarını yönetin</string>
|
||||||
|
<string name="app_profile_template_create">Şablon oluştur</string>
|
||||||
|
<string name="app_profile_template_edit">Şablonu düzenle</string>
|
||||||
|
<string name="app_profile_template_id">Kimlik</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Geçersiz şablon kimliği</string>
|
||||||
|
<string name="app_profile_template_name">İsim</string>
|
||||||
|
<string name="app_profile_template_description">Açıklama</string>
|
||||||
|
<string name="app_profile_template_save">Kaydet</string>
|
||||||
|
<string name="app_profile_template_delete">Sil</string>
|
||||||
|
<string name="app_profile_template_view">Şablonu görüntüle</string>
|
||||||
|
<string name="app_profile_template_readonly">Salt okunur</string>
|
||||||
|
<string name="app_profile_template_id_exist">Şablon kimliği zaten mevcut!</string>
|
||||||
|
<string name="app_profile_import_export">İçe aktar/Dışa aktar</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Panodan içe aktar</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Panodan dışa aktar</string>
|
||||||
|
<string name="app_profile_template_export_empty">Dışa aktarmak için yerel şablon bulunamadı!</string>
|
||||||
|
<string name="app_profile_template_import_success">Başarıyla içe aktarıldı</string>
|
||||||
|
<string name="app_profile_template_sync">Çevrimiçi şablonları senkronize et</string>
|
||||||
|
<string name="app_profile_template_save_failed">Şablon kaydedilemedi</string>
|
||||||
|
<string name="app_profile_template_import_empty">Pano boş!</string>
|
||||||
|
<string name="module_changelog_failed">Değişiklik geçmişi alınamadı: %s</string>
|
||||||
|
<string name="settings_check_update">Güncellemeleri denetle</string>
|
||||||
|
<string name="settings_check_update_summary">Uygulamayı açarken güncellemeleri otomatik denetle</string>
|
||||||
|
<string name="grant_root_failed">Root izni verilemedi!</string>
|
||||||
|
<string name="open">Aç</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<string name="home_superuser_count">Суперкористувачі: %d</string>
|
<string name="home_superuser_count">Суперкористувачі: %d</string>
|
||||||
<string name="home_module_count">Модулі: %d</string>
|
<string name="home_module_count">Модулі: %d</string>
|
||||||
<string name="home_unsupported">Не підтримується</string>
|
<string name="home_unsupported">Не підтримується</string>
|
||||||
<string name="home_unsupported_reason">KernelSU підтримує лише ядра GKI</string>
|
<string name="home_unsupported_reason">KernelSU підтримує лише GKI ядра на данний момент</string>
|
||||||
<string name="home_kernel">Ядро</string>
|
<string name="home_kernel">Ядро</string>
|
||||||
<string name="home_manager_version">Версія менеджера</string>
|
<string name="home_manager_version">Версія менеджера</string>
|
||||||
<string name="home_fingerprint">Відбиток</string>
|
<string name="home_fingerprint">Відбиток</string>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<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>
|
||||||
@@ -39,10 +39,10 @@
|
|||||||
<string name="module_version">Версія</string>
|
<string name="module_version">Версія</string>
|
||||||
<string name="module_author">Автор</string>
|
<string name="module_author">Автор</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>
|
||||||
<string name="show_system_apps">Показати системні додатки</string>
|
<string name="show_system_apps">Показати системні додатки</string>
|
||||||
<string name="hide_system_apps">Сховати системні додатки</string>
|
<string name="hide_system_apps">Сховати системні додатки</string>
|
||||||
<string name="send_log">Надіслати лог</string>
|
<string name="send_log">Надіслати логи</string>
|
||||||
<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>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
<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>
|
||||||
<string name="profile_namespace_global">Глобальний</string>
|
<string name="profile_namespace_global">Глобальний</string>
|
||||||
<string name="profile_namespace_individual">Індивідуальний</string>
|
<string name="profile_namespace_individual">Індивідуальний</string>
|
||||||
@@ -81,4 +81,26 @@
|
|||||||
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string>
|
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string>
|
||||||
<string name="module_changelog">Журнал змін</string>
|
<string name="module_changelog">Журнал змін</string>
|
||||||
<string name="require_kernel_version">Поточна версія KernelSU %d занадто низька, щоб менеджер міг працювати належним чином. Будь ласка, оновіть до версії %d або вище!</string>
|
<string name="require_kernel_version">Поточна версія KernelSU %d занадто низька, щоб менеджер міг працювати належним чином. Будь ласка, оновіть до версії %d або вище!</string>
|
||||||
|
<string name="app_profile_template_import_success">Успішно імпортовано</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Експортувати в буфер обміну</string>
|
||||||
|
<string name="app_profile_template_export_empty">Неможливо знайти локальні шаблони для експорту!</string>
|
||||||
|
<string name="app_profile_template_id_exist">Шаблон з таким ідентифікатором вже існує!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Імпортувати з буферу обміну</string>
|
||||||
|
<string name="module_changelog_failed">Невдача при завантаженні списку змін: %s</string>
|
||||||
|
<string name="app_profile_template_name">Ім\'я</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Невірний ідентифікатор шаблону</string>
|
||||||
|
<string name="app_profile_template_sync">Синхронізувати мережеві шаблони</string>
|
||||||
|
<string name="app_profile_template_create">Створити шаблон</string>
|
||||||
|
<string name="app_profile_template_readonly">Тільки читання</string>
|
||||||
|
<string name="app_profile_import_export">Імпорт/Експорт</string>
|
||||||
|
<string name="app_profile_template_save_failed">Помилка при збереженні шаблону</string>
|
||||||
|
<string name="app_profile_template_edit">Редагувати шаблон</string>
|
||||||
|
<string name="app_profile_template_id">Ідентифікатор</string>
|
||||||
|
<string name="settings_profile_template">Шаблон Профілю Додатку</string>
|
||||||
|
<string name="app_profile_template_description">Опис</string>
|
||||||
|
<string name="app_profile_template_save">Зберегти</string>
|
||||||
|
<string name="settings_profile_template_summary">Керувати локальними та мережевими шаблонами профілів додатків</string>
|
||||||
|
<string name="app_profile_template_delete">Видалити</string>
|
||||||
|
<string name="app_profile_template_import_empty">Буфер обміну пустий!</string>
|
||||||
|
<string name="app_profile_template_view">Переглянути шаблон</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<string name="module_update">Cập nhật</string>
|
<string name="module_update">Cập nhật</string>
|
||||||
<string name="module_downloading">Đang tải xuống mô-đun: %s</string>
|
<string name="module_downloading">Đang tải xuống mô-đun: %s</string>
|
||||||
<string name="module_start_downloading">Bắt đầu tải xuống: %s</string>
|
<string name="module_start_downloading">Bắt đầu tải xuống: %s</string>
|
||||||
<string name="new_version_available">Đã có phiên bản mới: %s, nhấn để tải xuống</string>
|
<string name="new_version_available">Phiên bản mới: %s đã có, bấm để nâng cấp</string>
|
||||||
<string name="home_learn_kernelsu">Tìm hiểu KernelSU</string>
|
<string name="home_learn_kernelsu">Tìm hiểu KernelSU</string>
|
||||||
<string name="home_click_to_learn_kernelsu">Tìm hiểu cách cài đặt KernelSU và sử dụng các mô-đun</string>
|
<string name="home_click_to_learn_kernelsu">Tìm hiểu cách cài đặt KernelSU và sử dụng các mô-đun</string>
|
||||||
<string name="home_support_title">Hỗ trợ chúng tôi</string>
|
<string name="home_support_title">Hỗ trợ chúng tôi</string>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s<br/>Tham gia kênh %2$s của chúng tôi]]></string>
|
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s<br/>Tham gia kênh %2$s của chúng tôi]]></string>
|
||||||
<string name="module_magisk_conflict">Các mô-đun bị vô hiệu hóa vì chúng xung đột với Magisk!</string>
|
<string name="module_magisk_conflict">Các mô-đun bị vô hiệu hóa vì chúng xung đột với Magisk!</string>
|
||||||
<string name="module_uninstall_confirm">Bạn có muốn gỡ cài đặt mô-đun %s không\?</string>
|
<string name="module_uninstall_confirm">Bạn có muốn gỡ cài đặt mô-đun %s không\?</string>
|
||||||
<string name="send_log">Gửi nhật ký</string>
|
<string name="send_log">báo cáo nhật ký</string>
|
||||||
<string name="home">Trang chủ</string>
|
<string name="home">Trang chủ</string>
|
||||||
<string name="home_not_installed">Chưa cài đặt</string>
|
<string name="home_not_installed">Chưa cài đặt</string>
|
||||||
<string name="home_click_to_install">Nhấn để cài dặt</string>
|
<string name="home_click_to_install">Nhấn để cài dặt</string>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
<string name="selinux_status_enforcing">Thực thi</string>
|
<string name="selinux_status_enforcing">Thực thi</string>
|
||||||
<string name="selinux_status_permissive">Cho phép</string>
|
<string name="selinux_status_permissive">Cho phép</string>
|
||||||
<string name="selinux_status_unknown">Không rõ</string>
|
<string name="selinux_status_unknown">Không rõ</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">SuperUser</string>
|
||||||
<string name="module_failed_to_enable">Không thể kích hoạt mô-đun: %s</string>
|
<string name="module_failed_to_enable">Không thể kích hoạt mô-đun: %s</string>
|
||||||
<string name="module_failed_to_disable">Không thể vô hiệu hóa mô-đun: %s</string>
|
<string name="module_failed_to_disable">Không thể vô hiệu hóa mô-đun: %s</string>
|
||||||
<string name="module_empty">Chưa có mô-đun nào được cài đặt</string>
|
<string name="module_empty">Chưa có mô-đun nào được cài đặt</string>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
<string name="reboot_download">Khởi động lại vào Download Mode</string>
|
<string name="reboot_download">Khởi động lại vào Download Mode</string>
|
||||||
<string name="reboot_edl">Khởi động lại vào EDL</string>
|
<string name="reboot_edl">Khởi động lại vào EDL</string>
|
||||||
<string name="about">Về ứng dụng</string>
|
<string name="about">Về ứng dụng</string>
|
||||||
<string name="module_uninstall_success">%s đã được gỡ cài đặt</string>
|
<string name="module_uninstall_success">%s được gỡ cài đặt</string>
|
||||||
<string name="module_uninstall_failed">Lỗi khi gỡ cài đặt: %s</string>
|
<string name="module_uninstall_failed">Lỗi khi gỡ cài đặt: %s</string>
|
||||||
<string name="module_version">Phiên bản</string>
|
<string name="module_version">Phiên bản</string>
|
||||||
<string name="module_author">Tác giả</string>
|
<string name="module_author">Tác giả</string>
|
||||||
@@ -80,4 +80,27 @@
|
|||||||
<string name="profile_selinux_context">SELinux context</string>
|
<string name="profile_selinux_context">SELinux context</string>
|
||||||
<string name="profile_umount_modules">Ngắt mô-đun</string>
|
<string name="profile_umount_modules">Ngắt mô-đun</string>
|
||||||
<string name="require_kernel_version">KernelSU phiên bản %d quá thấp để trình quản lý hoạt động, hãy cập nhật lên %d hoặc mới hơn!</string>
|
<string name="require_kernel_version">KernelSU phiên bản %d quá thấp để trình quản lý hoạt động, hãy cập nhật lên %d hoặc mới hơn!</string>
|
||||||
|
<string name="app_profile_template_import_success">Đã nhập thành công</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Xuất từ khay nhớ tạm</string>
|
||||||
|
<string name="app_profile_template_export_empty">Không thể tìm thấy mẫu cục bộ để xuất!</string>
|
||||||
|
<string name="app_profile_template_id_exist">id bản mẫu đã tồn tại!</string>
|
||||||
|
<string name="module_changelog">Nhật ký thay đổi</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Nhập từ khay nhớ tạm</string>
|
||||||
|
<string name="module_changelog_failed">Tìm nạp nhật ký thay đổi không thành công: %s</string>
|
||||||
|
<string name="app_profile_template_name">Tên</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Id mẫu không hợp lệ</string>
|
||||||
|
<string name="app_profile_template_sync">Đồng bộ hóa các mẫu trực tuyến</string>
|
||||||
|
<string name="app_profile_template_create">Tạo Bản Mẫu</string>
|
||||||
|
<string name="app_profile_import_export">Nhập/Xuất</string>
|
||||||
|
<string name="app_profile_template_save_failed">Không lưu được mẫu</string>
|
||||||
|
<string name="app_profile_template_edit">Sửa Bản Mẫu</string>
|
||||||
|
<string name="settings_profile_template">Mẫu Hồ Sơ Ứng Dụng</string>
|
||||||
|
<string name="app_profile_template_description">Mô tả</string>
|
||||||
|
<string name="app_profile_template_save">Lưu</string>
|
||||||
|
<string name="settings_profile_template_summary">Quản lý mẫu Hồ sơ Ứng dụng cục bộ và trực tuyến</string>
|
||||||
|
<string name="app_profile_template_delete">Xóa</string>
|
||||||
|
<string name="app_profile_template_import_empty">Bảng tạm trống!</string>
|
||||||
|
<string name="app_profile_template_view">Xem Bản Mẫu</string>
|
||||||
|
<string name="app_profile_template_readonly">chỉ đọc</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_CN/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_CN/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string>
|
<string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string>
|
||||||
<string name="home_support_title">支持开发</string>
|
<string name="home_support_title">支持开发</string>
|
||||||
<string name="home_support_content">KernelSU 将保持免费和开源,向开发者捐赠以表示支持。</string>
|
<string name="home_support_content">KernelSU 将保持免费开源,向开发者捐赠以表示支持。</string>
|
||||||
<string name="about_source_code"><![CDATA[在 %1$s 查看源码<br/>加入我们的 %2$s 频道<br/>加入我们的 <b><a href="https://pd.qq.com/s/8lipl1brp">QQ 频道</a></b>]]></string>
|
<string name="about_source_code"><![CDATA[在 %1$s 查看源码<br/>加入我们的 %2$s 频道<br/>加入我们的 <b><a href="https://pd.qq.com/s/8lipl1brp">QQ 频道</a></b>]]></string>
|
||||||
<string name="profile_default">默认</string>
|
<string name="profile_default">默认</string>
|
||||||
<string name="profile_template">模版</string>
|
<string name="profile_template">模版</string>
|
||||||
@@ -80,4 +80,30 @@
|
|||||||
<string name="restart_app">重新启动</string>
|
<string name="restart_app">重新启动</string>
|
||||||
<string name="failed_to_update_sepolicy">为:%s 更新翻译失败</string>
|
<string name="failed_to_update_sepolicy">为:%s 更新翻译失败</string>
|
||||||
<string name="module_changelog">更新日志</string>
|
<string name="module_changelog">更新日志</string>
|
||||||
|
<string name="settings_profile_template">App Profile 模版</string>
|
||||||
|
<string name="settings_profile_template_summary">管理本地和在线的 App Profile 模版</string>
|
||||||
|
<string name="app_profile_template_create">创建模版</string>
|
||||||
|
<string name="app_profile_template_edit">编辑模版</string>
|
||||||
|
<string name="app_profile_template_id">模版 id</string>
|
||||||
|
<string name="app_profile_template_id_invalid">模版 id 不合法</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">模版 id 已存在!</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="open">打开</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -3,14 +3,14 @@
|
|||||||
<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="home_working">正在處理</string>
|
<string name="home_working">運作中</string>
|
||||||
<string name="home_working_version">版本:%d</string>
|
<string name="home_working_version">KernelSU 版本:%d</string>
|
||||||
<string name="home_superuser_count">超級使用者:%d 個</string>
|
<string name="home_superuser_count">超級使用者:%d 個</string>
|
||||||
<string name="home_module_count">模組:%d 個</string>
|
<string name="home_module_count">已安裝模組:%d 個</string>
|
||||||
<string name="home_unsupported">不支援</string>
|
<string name="home_unsupported">不支援</string>
|
||||||
<string name="home_unsupported_reason">KernelSU 現在僅支援 GKI 核心</string>
|
<string name="home_unsupported_reason">KernelSU 現在僅支援 GKI 核心</string>
|
||||||
<string name="home_kernel">核心</string>
|
<string name="home_kernel">核心</string>
|
||||||
<string name="home_manager_version">管理員版本</string>
|
<string name="home_manager_version">管理器版本</string>
|
||||||
<string name="home_fingerprint">指紋</string>
|
<string name="home_fingerprint">指紋</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>
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
<string name="module_magisk_conflict">模組已停用,因其與 Magisk 的模組存在衝突!</string>
|
<string name="module_magisk_conflict">模組已停用,因其與 Magisk 的模組存在衝突!</string>
|
||||||
<string name="home_learn_kernelsu">深入瞭解 KernelSU</string>
|
<string name="home_learn_kernelsu">深入瞭解 KernelSU</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">瞭解如何安裝 KernelSU 和使用模組</string>
|
<string name="home_click_to_learn_kernelsu">瞭解如何安裝 KernelSU 以及如何開發模組</string>
|
||||||
<string name="home_support_title">支持我們</string>
|
<string name="home_support_title">支援開發</string>
|
||||||
<string name="home_support_content">KernelSU 是免費且開源的,您可以透過捐贈來向我們展示您對我們的關心。</string>
|
<string name="home_support_content">KernelSU 將保持免費和開源,您可以考慮向開發人員贊助以表示支持。</string>
|
||||||
<string name="about_source_code"><![CDATA[在 %1$s 中檢視原始碼<br/>加入我們的 %2$s 頻道]]></string>
|
<string name="about_source_code"><![CDATA[在 %1$s 中檢視原始碼<br/>加入我們的 %2$s 頻道]]></string>
|
||||||
<string name="profile_default">預設</string>
|
<string name="profile_default">預設</string>
|
||||||
<string name="profile_name">設定檔名稱</string>
|
<string name="profile_name">設定檔名稱</string>
|
||||||
@@ -61,8 +61,8 @@
|
|||||||
<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="profile_selinux_rules">規則</string>
|
<string name="profile_selinux_rules">規則</string>
|
||||||
<string name="require_kernel_version">目前 KernelSU 版本 %d 過低,管理員無法正常運作。請升級至 %d 或更高版本!</string>
|
<string name="require_kernel_version">目前 KernelSU 版本 %d 過低,管理器無法正常運作。請升級至 %d 或更高版本!</string>
|
||||||
<string name="settings_umount_modules_default_summary">應用程式設定檔中「卸載模組」的全域預設值。如果啟用,將會為沒有設定檔的應用程式移除所有模組對系統的修改。</string>
|
<string name="settings_umount_modules_default_summary">應用程式設定檔中「解除安裝模組」的全域預設值,如果啟用,將會為沒有設定檔的應用程式移除所有模組針對系統的修改。</string>
|
||||||
<string name="profile_umount_modules_summary">啟用此選項將允許 KernelSU 為這個應用程式還原任何被模組修改過的檔案。</string>
|
<string name="profile_umount_modules_summary">啟用此選項將允許 KernelSU 為這個應用程式還原任何被模組修改過的檔案。</string>
|
||||||
<string name="profile_selinux_domain">網域</string>
|
<string name="profile_selinux_domain">網域</string>
|
||||||
<string name="module_update">更新</string>
|
<string name="module_update">更新</string>
|
||||||
@@ -70,13 +70,36 @@
|
|||||||
<string name="profile_namespace">掛載命名空間</string>
|
<string name="profile_namespace">掛載命名空間</string>
|
||||||
<string name="profile_namespace_individual">個人</string>
|
<string name="profile_namespace_individual">個人</string>
|
||||||
<string name="profile_groups">群組</string>
|
<string name="profile_groups">群組</string>
|
||||||
<string name="profile_selinux_context">SELinux 內容</string>
|
<string name="profile_selinux_context">SELinux 環境</string>
|
||||||
<string name="settings_umount_modules_default">預設卸載模組</string>
|
<string name="settings_umount_modules_default">預設解除安裝模組</string>
|
||||||
<string name="module_downloading">正在下載模組:%s</string>
|
<string name="module_downloading">正在下載模組:%s</string>
|
||||||
<string name="module_start_downloading">開始下載:%s</string>
|
<string name="module_start_downloading">開始下載:%s</string>
|
||||||
<string name="new_version_available">新版本:%s 已可供使用,按一下以下載</string>
|
<string name="new_version_available">新版本:%s 已可供使用,按一下以升級</string>
|
||||||
<string name="launch_app">啟動</string>
|
<string name="launch_app">啟動</string>
|
||||||
<string name="force_stop_app">強制停止</string>
|
<string name="force_stop_app">強制停止</string>
|
||||||
<string name="restart_app">重新啟動</string>
|
<string name="restart_app">重新啟動</string>
|
||||||
<string name="failed_to_update_sepolicy">無法為 %s 更新 SELinux 規則</string>
|
<string name="failed_to_update_sepolicy">無法為 %s 更新 SELinux 規則</string>
|
||||||
</resources>
|
<string name="module_changelog">變更記錄</string>
|
||||||
|
<string name="app_profile_template_import_success">成功匯出</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">導出到剪貼板</string>
|
||||||
|
<string name="app_profile_template_export_empty">本地沒有模板可匯出!</string>
|
||||||
|
<string name="app_profile_template_id_exist">模板 ID 已存在!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">從剪貼簿匯入</string>
|
||||||
|
<string name="module_changelog_failed">獲取更新日誌失敗:%s</string>
|
||||||
|
<string name="app_profile_template_name">名字</string>
|
||||||
|
<string name="app_profile_template_id_invalid">模板 ID 無效</string>
|
||||||
|
<string name="app_profile_template_sync">同步在線規則</string>
|
||||||
|
<string name="app_profile_template_create">創建模板</string>
|
||||||
|
<string name="app_profile_template_readonly">只讀</string>
|
||||||
|
<string name="app_profile_import_export">匯出 / 匯入</string>
|
||||||
|
<string name="app_profile_template_save_failed">模板儲存失敗</string>
|
||||||
|
<string name="app_profile_template_edit">編輯模板</string>
|
||||||
|
<string name="app_profile_template_id">模板 ID</string>
|
||||||
|
<string name="settings_profile_template">App Profile 模板</string>
|
||||||
|
<string name="app_profile_template_description">描述</string>
|
||||||
|
<string name="app_profile_template_save">儲存</string>
|
||||||
|
<string name="settings_profile_template_summary">管理本地和線上的 App Profile 模板</string>
|
||||||
|
<string name="app_profile_template_delete">刪除</string>
|
||||||
|
<string name="app_profile_template_import_empty">剪貼簿沒有內容!</string>
|
||||||
|
<string name="app_profile_template_view">查看模板</string>
|
||||||
|
</resources>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<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="home_working">正在處理</string>
|
<string name="home_working">運作中</string>
|
||||||
<string name="home_working_version">KernelSU 版本:%d</string>
|
<string name="home_working_version">KernelSU 版本:%d</string>
|
||||||
<string name="home_superuser_count">已授權 Root:%d 個</string>
|
<string name="home_superuser_count">已授權 Root:%d 個</string>
|
||||||
<string name="home_unsupported">不支援</string>
|
<string name="home_unsupported">不支援</string>
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
<string name="home_learn_kernelsu">深入瞭解 KernelSU</string>
|
<string name="home_learn_kernelsu">深入瞭解 KernelSU</string>
|
||||||
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html</string>
|
<string name="home_learn_kernelsu_url">https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html</string>
|
||||||
<string name="home_click_to_learn_kernelsu">瞭解如何安裝 KernelSU 以及如何開發模組</string>
|
<string name="home_click_to_learn_kernelsu">瞭解如何安裝 KernelSU 以及如何開發模組</string>
|
||||||
<string name="home_support_title">支持開發</string>
|
<string name="home_support_title">支援開發</string>
|
||||||
<string name="home_support_content">KernelSU 將保持免費和開源,您可以考慮向開發人員捐贈以表示支持。</string>
|
<string name="home_support_content">KernelSU 將保持免費和開源,您可以考慮向開發人員贊助以表示支持。</string>
|
||||||
<string name="about_source_code"><![CDATA[在 %1$s 中檢視原始碼<br/>加入我們的 %2$s 頻道]]></string>
|
<string name="about_source_code"><![CDATA[在 %1$s 中檢視原始碼<br/>加入我們的 %2$s 頻道]]></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>
|
||||||
@@ -80,4 +80,26 @@
|
|||||||
<string name="force_stop_app">強制停止</string>
|
<string name="force_stop_app">強制停止</string>
|
||||||
<string name="failed_to_update_sepolicy">無法為 %s 更新 SELinux</string>
|
<string name="failed_to_update_sepolicy">無法為 %s 更新 SELinux</string>
|
||||||
<string name="module_changelog">變更記錄</string>
|
<string name="module_changelog">變更記錄</string>
|
||||||
|
<string name="app_profile_template_id_invalid">模板 ID 無效</string>
|
||||||
|
<string name="app_profile_template_create">創建模板</string>
|
||||||
|
<string name="app_profile_template_edit">編輯模板</string>
|
||||||
|
<string name="app_profile_template_id">模板 ID</string>
|
||||||
|
<string name="settings_profile_template">App Profile 模板</string>
|
||||||
|
<string name="settings_profile_template_summary">管理本地和線上的 App Profile 模板</string>
|
||||||
|
<string name="app_profile_template_import_success">成功匯出</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">匯出至剪貼簿</string>
|
||||||
|
<string name="app_profile_template_export_empty">本地沒有模板可匯出!</string>
|
||||||
|
<string name="app_profile_template_id_exist">模板 ID 已存在!</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">從剪貼簿匯入</string>
|
||||||
|
<string name="module_changelog_failed">獲取更新日誌失敗:%s</string>
|
||||||
|
<string name="app_profile_template_name">名稱</string>
|
||||||
|
<string name="app_profile_template_sync">與線上規則同步</string>
|
||||||
|
<string name="app_profile_template_readonly">只讀</string>
|
||||||
|
<string name="app_profile_import_export">匯出 / 匯入</string>
|
||||||
|
<string name="app_profile_template_save_failed">模板儲存失敗</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_import_empty">剪貼簿沒有內容!</string>
|
||||||
|
<string name="app_profile_template_view">檢查模板</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">KernelSU</string>
|
<string name="app_name" translatable="false">KernelSU</string>
|
||||||
|
|
||||||
<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>
|
||||||
@@ -10,21 +10,18 @@
|
|||||||
<string name="home_module_count">Modules: %d</string>
|
<string name="home_module_count">Modules: %d</string>
|
||||||
<string name="home_unsupported">Unsupported</string>
|
<string name="home_unsupported">Unsupported</string>
|
||||||
<string name="home_unsupported_reason">KernelSU only supports GKI kernels now</string>
|
<string name="home_unsupported_reason">KernelSU only supports GKI kernels now</string>
|
||||||
|
|
||||||
<string name="home_kernel">Kernel</string>
|
<string name="home_kernel">Kernel</string>
|
||||||
<string name="home_manager_version">Manager Version</string>
|
<string name="home_manager_version">Manager Version</string>
|
||||||
<string name="home_fingerprint">Fingerprint</string>
|
<string name="home_fingerprint">Fingerprint</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>
|
||||||
<string name="selinux_status_permissive">Permissive</string>
|
<string name="selinux_status_permissive">Permissive</string>
|
||||||
<string name="selinux_status_unknown">Unknown</string>
|
<string name="selinux_status_unknown">Unknown</string>
|
||||||
<string name="superuser">Superuser</string>
|
<string name="superuser">SuperUser</string>
|
||||||
<string name="module_failed_to_enable">Failed to enable module: %s</string>
|
<string name="module_failed_to_enable">Failed to enable module: %s</string>
|
||||||
<string name="module_failed_to_disable">Failed to disable module: %s</string>
|
<string name="module_failed_to_disable">Failed to disable module: %s</string>
|
||||||
<string name="module_empty">No module installed</string>
|
<string name="module_empty">No installed modules</string>
|
||||||
|
|
||||||
<string name="module">Module</string>
|
<string name="module">Module</string>
|
||||||
<string name="uninstall">Uninstall</string>
|
<string name="uninstall">Uninstall</string>
|
||||||
<string name="module_install">Install</string>
|
<string name="module_install">Install</string>
|
||||||
@@ -38,7 +35,7 @@
|
|||||||
<string name="reboot_edl">Reboot to EDL</string>
|
<string name="reboot_edl">Reboot to EDL</string>
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
<string name="module_uninstall_confirm">Are you sure you want to uninstall module %s?</string>
|
<string name="module_uninstall_confirm">Are you sure you want to uninstall module %s?</string>
|
||||||
<string name="module_uninstall_success">%s uninstalled</string>
|
<string name="module_uninstall_success">%s is uninstalled</string>
|
||||||
<string name="module_uninstall_failed">Failed to uninstall: %s</string>
|
<string name="module_uninstall_failed">Failed to uninstall: %s</string>
|
||||||
<string name="module_version">Version</string>
|
<string name="module_version">Version</string>
|
||||||
<string name="module_author">Author</string>
|
<string name="module_author">Author</string>
|
||||||
@@ -46,7 +43,7 @@
|
|||||||
<string name="refresh">Refresh</string>
|
<string name="refresh">Refresh</string>
|
||||||
<string name="show_system_apps">Show system apps</string>
|
<string name="show_system_apps">Show system apps</string>
|
||||||
<string name="hide_system_apps">Hide system apps</string>
|
<string name="hide_system_apps">Hide system apps</string>
|
||||||
<string name="send_log">Send Log</string>
|
<string name="send_log">Report Log</string>
|
||||||
<string name="safe_mode">Safe mode</string>
|
<string name="safe_mode">Safe mode</string>
|
||||||
<string name="reboot_to_apply">Reboot to take effect</string>
|
<string name="reboot_to_apply">Reboot to take effect</string>
|
||||||
<string name="module_magisk_conflict">Modules are disabled because it is conflict with Magisk\'s!</string>
|
<string name="module_magisk_conflict">Modules are disabled because it is conflict with Magisk\'s!</string>
|
||||||
@@ -85,4 +82,30 @@
|
|||||||
<string name="restart_app">Restart</string>
|
<string name="restart_app">Restart</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="module_changelog">Changelog</string>
|
<string name="module_changelog">Changelog</string>
|
||||||
|
<string name="settings_profile_template">App Profile Template</string>
|
||||||
|
<string name="settings_profile_template_summary">Manage local and online template of App Profile</string>
|
||||||
|
<string name="app_profile_template_create">Create Template</string>
|
||||||
|
<string name="app_profile_template_edit">Edit Template</string>
|
||||||
|
<string name="app_profile_template_id">id</string>
|
||||||
|
<string name="app_profile_template_id_invalid">Invalid template id</string>
|
||||||
|
<string name="app_profile_template_name">Name</string>
|
||||||
|
<string name="app_profile_template_description">Description</string>
|
||||||
|
<string name="app_profile_template_save">Save</string>
|
||||||
|
<string name="app_profile_template_delete">Delete</string>
|
||||||
|
<string name="app_profile_template_view">View Template</string>
|
||||||
|
<string name="app_profile_template_readonly">readonly</string>
|
||||||
|
<string name="app_profile_template_id_exist">template id already exists!</string>
|
||||||
|
<string name="app_profile_import_export">Import/Export</string>
|
||||||
|
<string name="app_profile_import_from_clipboard">Import from clipboard</string>
|
||||||
|
<string name="app_profile_export_to_clipboard">Export to clipboard</string>
|
||||||
|
<string name="app_profile_template_export_empty">Can not find local template to export!</string>
|
||||||
|
<string name="app_profile_template_import_success">Imported successfully</string>
|
||||||
|
<string name="app_profile_template_sync">Sync online templates</string>
|
||||||
|
<string name="app_profile_template_save_failed">Failed to save template</string>
|
||||||
|
<string name="app_profile_template_import_empty">Clipboard is empty!</string>
|
||||||
|
<string name="module_changelog_failed">Fetch changelog failed: %s</string>
|
||||||
|
<string name="settings_check_update">Check update</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="open">Open</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user