You've already forked KernelSU-Next
mirror of
https://github.com/KernelSU-Next/KernelSU-Next.git
synced 2025-08-27 23:46:34 +00:00
Compare commits
61 Commits
kpm
...
dc7ae2db5f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc7ae2db5f | ||
|
|
b3b7ef1cb3 | ||
|
|
4de4d1e091 | ||
|
|
0beea57ab7 | ||
|
|
49aee1ff4c | ||
|
|
f7a3699fe3 | ||
|
|
66d42de599 | ||
|
|
d562594ae1 | ||
|
|
02afc6710c | ||
|
|
9d9f9ed5d5 | ||
|
|
b3b6320946 | ||
|
|
d43b8320ad | ||
|
|
a2260ae330 | ||
|
|
aa221acad1 | ||
|
|
c41d35db62 | ||
|
|
e5f0c733b8 | ||
|
|
70b52f85e9 | ||
|
|
303b5192ec | ||
|
|
443d3a6abe | ||
|
|
a2a7383343 | ||
|
|
ed64f933f5 | ||
|
|
4c7ad8eac4 | ||
|
|
6a922febcd | ||
|
|
71eba5df8b | ||
|
|
f1ef0afc20 | ||
|
|
844c9f94e9 | ||
|
|
07a4d3457c | ||
|
|
8c9728df95 | ||
|
|
14ec1194e4 | ||
|
|
a37f398cc7 | ||
|
|
80bd797737 | ||
|
|
600d9ce5d2 | ||
|
|
f15d9b18e9 | ||
|
|
aa19e8c609 | ||
|
|
2b2320000c | ||
|
|
06135cc827 | ||
|
|
fc58bdf0e2 | ||
|
|
9b5e60912d | ||
|
|
c108a8ed32 | ||
|
|
adce657583 | ||
|
|
d6601e1e54 | ||
|
|
0d4efa649f | ||
|
|
85f4e6ac27 | ||
|
|
c91f9c18ec | ||
|
|
bf35f73430 | ||
|
|
ad290a51a0 | ||
|
|
d218346613 | ||
|
|
502e5599fe | ||
|
|
11fb52b929 | ||
|
|
057388ccef | ||
|
|
67759ad723 | ||
|
|
f231cbdba7 | ||
|
|
7abc9bc821 | ||
|
|
e7697d86fe | ||
|
|
68394fddd5 | ||
|
|
90d34bf511 | ||
|
|
236fbc7615 | ||
|
|
6871cbdba7 | ||
|
|
38a9949211 | ||
|
|
9fba0faa43 | ||
|
|
b1250b002e |
2
.github/workflows/avd-kernel.yml
vendored
2
.github/workflows/avd-kernel.yml
vendored
@@ -37,7 +37,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ inputs.version_name }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Maximize build space
|
||||
uses: easimon/maximize-build-space@master
|
||||
|
||||
26
.github/workflows/build-debug-kernel.yml
vendored
26
.github/workflows/build-debug-kernel.yml
vendored
@@ -7,9 +7,9 @@ jobs:
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android12-5.10
|
||||
version_name: android12-5.10.233
|
||||
tag: android12-5.10-2025-02
|
||||
os_patch_level: 2025-02
|
||||
version_name: android12-5.10.236
|
||||
tag: android12-5.10-2025-05
|
||||
os_patch_level: 2025-05
|
||||
patch_path: "5.10"
|
||||
debug: true
|
||||
build-debug-kernel-a13:
|
||||
@@ -17,11 +17,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.10"
|
||||
sub_level: 234
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android13-${{ matrix.version }}
|
||||
@@ -34,11 +34,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
- version: "6.1"
|
||||
sub_level: 129
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 138
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android14-${{ matrix.version }}
|
||||
@@ -51,8 +51,8 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "6.6"
|
||||
sub_level: 82
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 89
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android15-${{ matrix.version }}
|
||||
|
||||
10
.github/workflows/build-kernel-a12.yml
vendored
10
.github/workflows/build-kernel-a12.yml
vendored
@@ -21,14 +21,14 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- sub_level: 209
|
||||
os_patch_level: 2024-05
|
||||
- sub_level: 218
|
||||
os_patch_level: 2024-08
|
||||
- sub_level: 226
|
||||
os_patch_level: 2024-11
|
||||
- sub_level: 233
|
||||
os_patch_level: 2025-02
|
||||
- sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android12-5.10
|
||||
version_name: android12-5.10.223
|
||||
tag: android12-5.10-2024-11
|
||||
os_patch_level: 2024-11
|
||||
version_name: android12-5.10.236
|
||||
tag: android12-5.10-2025-05
|
||||
os_patch_level: 2025-05
|
||||
patch_path: "5.10"
|
||||
20
.github/workflows/build-kernel-a13.yml
vendored
20
.github/workflows/build-kernel-a13.yml
vendored
@@ -21,9 +21,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.10"
|
||||
sub_level: 209
|
||||
os_patch_level: 2024-05
|
||||
- version: "5.10"
|
||||
sub_level: 210
|
||||
os_patch_level: 2024-06
|
||||
@@ -42,9 +39,9 @@ jobs:
|
||||
- version: "5.10"
|
||||
sub_level: 234
|
||||
os_patch_level: 2025-03
|
||||
- version: "5.15"
|
||||
sub_level: 148
|
||||
os_patch_level: 2024-05
|
||||
- version: "5.10"
|
||||
sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
- version: "5.15"
|
||||
sub_level: 149
|
||||
os_patch_level: 2024-07
|
||||
@@ -63,6 +60,9 @@ jobs:
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
- version: "5.15"
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
@@ -149,11 +149,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.10"
|
||||
sub_level: 234
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android13-${{ matrix.version }}
|
||||
|
||||
23
.github/workflows/build-kernel-a14.yml
vendored
23
.github/workflows/build-kernel-a14.yml
vendored
@@ -21,9 +21,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.15"
|
||||
sub_level: 148
|
||||
os_patch_level: 2024-05
|
||||
- version: "5.15"
|
||||
sub_level: 149
|
||||
os_patch_level: 2024-06
|
||||
@@ -45,9 +42,9 @@ jobs:
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
- version: "6.1"
|
||||
sub_level: 75
|
||||
os_patch_level: 2024-05
|
||||
- version: "5.15"
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
- version: "6.1"
|
||||
sub_level: 78
|
||||
os_patch_level: 2024-06
|
||||
@@ -81,6 +78,12 @@ jobs:
|
||||
- version: "6.1"
|
||||
sub_level: 129
|
||||
os_patch_level: 2025-04
|
||||
- version: "6.1"
|
||||
sub_level: 134
|
||||
os_patch_level: 2025-05
|
||||
- version: "6.1"
|
||||
sub_level: 138
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
@@ -167,11 +170,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
- version: "6.1"
|
||||
sub_level: 129
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 138
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android14-${{ matrix.version }}
|
||||
|
||||
10
.github/workflows/build-kernel-a15.yml
vendored
10
.github/workflows/build-kernel-a15.yml
vendored
@@ -48,6 +48,12 @@ jobs:
|
||||
- version: "6.6"
|
||||
sub_level: 82
|
||||
os_patch_level: 2025-04
|
||||
- version: "6.6"
|
||||
sub_level: 87
|
||||
os_patch_level: 2025-05
|
||||
- version: "6.6"
|
||||
sub_level: 89
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
@@ -134,8 +140,8 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "6.6"
|
||||
sub_level: 82
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 89
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: android15-${{ matrix.version }}
|
||||
|
||||
137
.github/workflows/build-kernel-arcvm.yml
vendored
Normal file
137
.github/workflows/build-kernel-arcvm.yml
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
name: Build Kernel - ChromeOS ARCVM
|
||||
on:
|
||||
push:
|
||||
branches: ["next"]
|
||||
paths:
|
||||
- ".github/workflows/build-kernel-arcvm.yml"
|
||||
- "kernel/**"
|
||||
pull_request:
|
||||
branches: ["next"]
|
||||
paths:
|
||||
- ".github/workflows/build-kernel-arcvm.yml"
|
||||
- "kernel/**"
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
git_tag: chromeos-5.10-arcvm
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.event_name != 'pull_request' || (github.event_name == 'pull_request' && !github.event.pull_request.draft)
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
kernel_image_name: bzImage
|
||||
build_config: build.config.gki.x86_64
|
||||
defconfig: x86_64_arcvm_defconfig
|
||||
- arch: arm64
|
||||
kernel_image_name: Image
|
||||
build_config: build.config.gki.aarch64
|
||||
defconfig: arm64_arcvm_defconfig
|
||||
|
||||
name: Build ChromeOS ARCVM kernel
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
LTO: thin
|
||||
ROOT_DIR: /
|
||||
KERNEL_DIR: ${{ github.workspace }}/kernel
|
||||
|
||||
steps:
|
||||
- name: Install Build Tools
|
||||
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 \
|
||||
rsync python3 device-tree-compiler
|
||||
|
||||
sudo ln -s --force python3 /usr/bin/python
|
||||
|
||||
export LLVM_VERSION=14
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $LLVM_VERSION
|
||||
rm ./llvm.sh
|
||||
sudo ln -s --force /usr/bin/clang-$LLVM_VERSION /usr/bin/clang
|
||||
sudo ln -s --force /usr/bin/ld.lld-$LLVM_VERSION /usr/bin/ld.lld
|
||||
sudo ln -s --force /usr/bin/llvm-objdump-$LLVM_VERSION /usr/bin/llvm-objdump
|
||||
sudo ln -s --force /usr/bin/llvm-ar-$LLVM_VERSION /usr/bin/llvm-ar
|
||||
sudo ln -s --force /usr/bin/llvm-nm-$LLVM_VERSION /usr/bin/llvm-nm
|
||||
sudo ln -s --force /usr/bin/llvm-strip-$LLVM_VERSION /usr/bin/llvm-strip
|
||||
sudo ln -s --force /usr/bin/llvm-objcopy-$LLVM_VERSION /usr/bin/llvm-objcopy
|
||||
sudo ln -s --force /usr/bin/llvm-readelf-$LLVM_VERSION /usr/bin/llvm-readelf
|
||||
sudo ln -s --force /usr/bin/clang++-$LLVM_VERSION /usr/bin/clang++
|
||||
|
||||
- name: Checkout KernelSU-Next
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: KernelSU-Next
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup kernel source
|
||||
run: git clone https://chromium.googlesource.com/chromiumos/third_party/kernel.git -b ${{ env.git_tag }} --depth=1
|
||||
|
||||
- name: Extract version from Makefile
|
||||
working-directory: kernel
|
||||
run: |
|
||||
VERSION=$(grep -E '^VERSION = ' Makefile | awk '{print $3}')
|
||||
PATCHLEVEL=$(grep -E '^PATCHLEVEL = ' Makefile | awk '{print $3}')
|
||||
SUBLEVEL=$(grep -E '^SUBLEVEL = ' Makefile | awk '{print $3}')
|
||||
echo "ChromeOS ARCVM Linux kernel version: $VERSION.$PATCHLEVEL.$SUBLEVEL"
|
||||
echo "version=$VERSION.$PATCHLEVEL.$SUBLEVEL" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup KernelSU-Next
|
||||
working-directory: kernel
|
||||
run: |
|
||||
echo "[+] KernelSU-Next setup"
|
||||
KERNEL_ROOT=$GITHUB_WORKSPACE/kernel
|
||||
echo "[+] KERNEL_ROOT: $KERNEL_ROOT"
|
||||
echo "[+] Copy KernelSU-Next driver to $KERNEL_ROOT/drivers"
|
||||
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $KERNEL_ROOT/drivers/kernelsu-next
|
||||
|
||||
echo "[+] Add KernelSU-Next driver to Makefile"
|
||||
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
|
||||
DRIVER_KCONFIG=$KERNEL_ROOT/drivers/Kconfig
|
||||
grep -q "kernelsu-next" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu-next/\n" >> "$DRIVER_MAKEFILE"
|
||||
grep -q "kernelsu-next" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu-next/Kconfig\"" "$DRIVER_KCONFIG"
|
||||
|
||||
echo "[+] Apply KernelSU patches"
|
||||
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/5.10/*.patch || echo "[-] No patch found"
|
||||
|
||||
echo "[+] Patch script/setlocalversion"
|
||||
sed -i 's/-dirty//g' $KERNEL_ROOT/scripts/setlocalversion
|
||||
|
||||
echo "[+] KernelSU-Next setup done."
|
||||
cd $GITHUB_WORKSPACE/KernelSU-Next
|
||||
KSU_VERSION=$(($(git rev-list --count HEAD) + 10200))
|
||||
echo "KernelSU-Next version: $KSU_VERSION"
|
||||
echo "kernelsu-next_version=$KSU_VERSION" >> $GITHUB_ENV
|
||||
|
||||
- name: Build Kernel
|
||||
working-directory: kernel
|
||||
env:
|
||||
KERNEL_IMAGE_NAME: ${{ matrix.kernel_image_name }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
set -a && . ${{ matrix.build_config }}; set +a
|
||||
export DEFCONFIG=${{ matrix.defconfig }}
|
||||
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
|
||||
|
||||
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} mrproper
|
||||
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} ${DEFCONFIG} < /dev/null
|
||||
scripts/config --file .config -e LTO_CLANG -d LTO_NONE -e LTO_CLANG_THIN -d LTO_CLANG_FULL -e THINLTO
|
||||
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} -j$(nproc) ${KERNEL_IMAGE_NAME} modules prepare-objtool
|
||||
ls -l -h ${PWD}/arch/${ARCH}/boot
|
||||
echo "file_path=${PWD}/arch/${ARCH}/boot/${KERNEL_IMAGE_NAME}" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload kernel-ARCVM-${{ matrix.arch }}-${{ env.version }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: kernel-ARCVM-${{ matrix.arch }}-${{ env.version }}
|
||||
path: "${{ env.file_path }}"
|
||||
39
.github/workflows/build-kernel-avd.yml
vendored
Normal file
39
.github/workflows/build-kernel-avd.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Build Kernel - AVD
|
||||
on:
|
||||
push:
|
||||
branches: ["next"]
|
||||
paths:
|
||||
- ".github/workflows/build-kernel-avd.yml"
|
||||
- ".github/workflows/avd-kernel.yml"
|
||||
- "kernel/**"
|
||||
pull_request:
|
||||
branches: ["next"]
|
||||
paths:
|
||||
- ".github/workflows/build-kernel-avd.yml"
|
||||
- ".github/workflows/avd-kernel.yml"
|
||||
- "kernel/**"
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-kernel:
|
||||
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
|
||||
uses: ./.github/workflows/avd-kernel.yml
|
||||
secrets: inherit
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- version: "android-14-avd_x86_64"
|
||||
manifest: "android-14-avd_x86_64.xml"
|
||||
arch: "x86_64"
|
||||
- version: "android-15-avd_aarch64"
|
||||
manifest: "android-15-avd_aarch64.xml"
|
||||
arch: "aarch64"
|
||||
- version: "android-15-avd_x86_64"
|
||||
manifest: "android-15-avd_x86_64.xml"
|
||||
arch: "x86_64"
|
||||
with:
|
||||
version_name: ${{ matrix.version }}
|
||||
manifest_name: ${{ matrix.manifest }}
|
||||
arch: ${{ matrix.arch }}
|
||||
debug: true
|
||||
24
.github/workflows/build-lkm.yml
vendored
24
.github/workflows/build-lkm.yml
vendored
@@ -15,23 +15,23 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- version: "android12-5.10"
|
||||
sub_level: 233
|
||||
os_patch_level: 2025-02
|
||||
sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
- version: "android13-5.10"
|
||||
sub_level: 234
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 236
|
||||
os_patch_level: 2025-05
|
||||
- version: "android13-5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
- version: "android14-5.15"
|
||||
sub_level: 178
|
||||
os_patch_level: 2025-03
|
||||
sub_level: 180
|
||||
os_patch_level: 2025-05
|
||||
- version: "android14-6.1"
|
||||
sub_level: 129
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 138
|
||||
os_patch_level: 2025-06
|
||||
- version: "android15-6.6"
|
||||
sub_level: 82
|
||||
os_patch_level: 2025-04
|
||||
sub_level: 89
|
||||
os_patch_level: 2025-06
|
||||
uses: ./.github/workflows/gki-kernel.yml
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
|
||||
21
.github/workflows/build-manager.yml
vendored
21
.github/workflows/build-manager.yml
vendored
@@ -33,17 +33,6 @@ jobs:
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
build-kpmmgr:
|
||||
needs: build-lkm
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64-linux-android
|
||||
os: ubuntu-latest
|
||||
uses: ./.github/workflows/kpmmgr.yml
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
|
||||
build-ksud:
|
||||
needs: build-susfsd
|
||||
strategy:
|
||||
@@ -120,16 +109,6 @@ jobs:
|
||||
mkdir -p app/src/main/jniLibs/x86_64
|
||||
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
|
||||
|
||||
- name: Download arm64 kpmmgr
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: kpmmgr-aarch64-linux-android
|
||||
path: .
|
||||
|
||||
- name: Copy kpmmgr to app jniLibs
|
||||
run: |
|
||||
mkdir -p app/src/main/jniLibs/arm64-v8a
|
||||
cp -f ../arm64-v8a/kpmmgr ../manager/app/src/main/jniLibs/arm64-v8a/libkpmmgr.so
|
||||
|
||||
- name: Download arm64 ksud_overlayfs
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
4
.github/workflows/clippy.yml
vendored
4
.github/workflows/clippy.yml
vendored
@@ -3,14 +3,14 @@ name: Clippy check
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- x86
|
||||
- next
|
||||
paths:
|
||||
- '.github/workflows/clippy.yml'
|
||||
- 'userspace/ksud_magic/**'
|
||||
- 'userspace/ksud_overlayfs/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- x86
|
||||
- next
|
||||
paths:
|
||||
- '.github/workflows/clippy.yml'
|
||||
- 'userspace/ksud_magic/**'
|
||||
|
||||
40
.github/workflows/kpmmgr.yml
vendored
40
.github/workflows/kpmmgr.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: Build kpmmgr
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "mian" ]
|
||||
paths:
|
||||
- '.github/workflows/kpmmgr.yml'
|
||||
- 'userspace/kpmmgr/**'
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
target:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: self-hosted
|
||||
|
||||
jobs:
|
||||
build-susfs:
|
||||
name: Build userspace kpmmgr
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build kpmmgr
|
||||
working-directory: ./userspace/kpmmgr
|
||||
run: |
|
||||
$ANDROID_NDK_HOME/ndk-build
|
||||
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: kpmmgr-aarch64-linux-android
|
||||
path: ./userspace/kpmmgr/libs
|
||||
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -21,6 +21,12 @@ jobs:
|
||||
build-a15-kernel:
|
||||
uses: ./.github/workflows/build-kernel-a15.yml
|
||||
secrets: inherit
|
||||
build-wsa-kernel:
|
||||
uses: ./.github/workflows/build-kernel-wsa.yml
|
||||
secrets: inherit
|
||||
build-arcvm-kernel:
|
||||
uses: ./.github/workflows/build-kernel-arcvm.yml
|
||||
secrets: inherit
|
||||
release:
|
||||
needs:
|
||||
- build-manager
|
||||
@@ -29,6 +35,7 @@ jobs:
|
||||
- build-a14-kernel
|
||||
- build-a15-kernel
|
||||
- build-wsa-kernel
|
||||
- build-arcvm-kernel
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
@@ -42,6 +49,24 @@ jobs:
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Zip WSA kernel
|
||||
run: |
|
||||
for dir in kernel-WSA-*; do
|
||||
if [ -d "$dir" ]; then
|
||||
echo "------ Zip $dir ----------"
|
||||
(cd $dir && zip -r9 "$dir".zip ./* -x .git .gitignore ./*.zip && mv *.zip ..)
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Zip ChromeOS ARCVM kernel
|
||||
run: |
|
||||
for dir in kernel-ARCVM-*; do
|
||||
if [ -d "$dir" ]; then
|
||||
echo "------ Zip $dir ----------"
|
||||
(cd $dir && zip -r9 "$dir".zip ./* -x .git .gitignore ./*.zip && mv *.zip ..)
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
@@ -54,6 +79,7 @@ jobs:
|
||||
AnyKernel3-*.zip
|
||||
boot-images-*/Image-*/*.img.gz
|
||||
kernel-WSA*.zip
|
||||
kernel-ARCVM*.zip
|
||||
ksud_magic*.zip
|
||||
ksud_overlayfs*.zip
|
||||
susfsd*.zip
|
||||
susfsd*.zip
|
||||
24
.github/workflows/wsa-kernel.yml
vendored
24
.github/workflows/wsa-kernel.yml
vendored
@@ -43,10 +43,10 @@ jobs:
|
||||
ubuntu-version: "16.04"
|
||||
cached: ${{ steps.cache-llvm.outputs.cache-hit }}
|
||||
|
||||
- name: Checkout KernelSU
|
||||
- name: Checkout KernelSU-Next
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: KernelSU
|
||||
path: KernelSU-Next
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup kernel source
|
||||
@@ -63,23 +63,23 @@ jobs:
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
max-size: 2G
|
||||
|
||||
- name: Setup KernelSU
|
||||
- name: Setup KernelSU-Next
|
||||
working-directory: WSA-Linux-Kernel
|
||||
run: |
|
||||
echo "[+] KernelSU setup"
|
||||
echo "[+] KernelSU-Next 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"
|
||||
echo "[+] Copy KernelSU-Next driver to $KERNEL_ROOT/drivers"
|
||||
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $KERNEL_ROOT/drivers/kernelsu
|
||||
echo "[+] Add KernelSU-Next driver to Makefile"
|
||||
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
|
||||
DRIVER_KCONFIG=$KERNEL_ROOT/drivers/Kconfig
|
||||
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
|
||||
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
|
||||
echo "[+] Apply KernelSU patches"
|
||||
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.15/*.patch || echo "[-] No patch found"
|
||||
echo "[+] KernelSU setup done."
|
||||
cd $GITHUB_WORKSPACE/KernelSU
|
||||
echo "[+] Apply KernelSU-Next patches"
|
||||
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/5.15/*.patch || echo "[-] No patch found"
|
||||
echo "[+] KernelSU-Next setup done."
|
||||
cd $GITHUB_WORKSPACE/KernelSU-Next
|
||||
VERSION=$(($(git rev-list --count HEAD) + 10200))
|
||||
echo "VERSION: $VERSION"
|
||||
echo "kernelsu_version=$VERSION" >> $GITHUB_ENV
|
||||
@@ -103,4 +103,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: kernel-WSA-${{ inputs.arch }}-${{ inputs.version }}
|
||||
path: "${{ env.file_path }}"
|
||||
path: "${{ env.file_path }}"
|
||||
|
||||
@@ -24,11 +24,11 @@ KernelSU Next officially supports most Android kernels starting from 4.4 up to 6
|
||||
- GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver.
|
||||
- EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports).
|
||||
|
||||
Currently, only the `arm64-v8a`, `armeabi-v7a` & `x86_64` architecture is supported.
|
||||
Currently, only the `arm64-v8a`, `armeabi-v7a` & `x86_64` architectures are supported.
|
||||
|
||||
## Usage
|
||||
|
||||
- [Installation instruction](https://ksunext.org/pages/installation.html)
|
||||
- [Installation instruction](https://kernelsu-next.github.io/webpage/pages/installation.html)
|
||||
|
||||
## Security
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ KernelSU Next suporta oficialmente a maioria dos kernels Android a partir de 4.4
|
||||
- Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU.
|
||||
- Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções).
|
||||
|
||||
Atualmente, apenas a arquitetura `arm64-v8a`, `armeabi-v7a` & `x86_64` é compatível.
|
||||
Atualmente, apenas as arquiteturas `arm64-v8a`, `armeabi-v7a` & `x86_64` são compatíveis.
|
||||
|
||||
## Uso
|
||||
|
||||
|
||||
@@ -40,13 +40,4 @@ config KSU_LSM_SECURITY_HOOKS
|
||||
Disabling this is mostly only useful for kernel 4.1 and older.
|
||||
Make sure to implement manual hooks on security/security.c.
|
||||
|
||||
config KPM
|
||||
bool "Enable SukiSU KPM"
|
||||
depends on KSU && 64BIT
|
||||
default n
|
||||
help
|
||||
Enabling this option will activate the KPM feature of SukiSU.
|
||||
This option is suitable for scenarios where you need to force KPM to be enabled.
|
||||
but it may affect system stability.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -16,20 +16,32 @@ ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-
|
||||
|
||||
obj-$(CONFIG_KSU) += kernelsu.o
|
||||
|
||||
obj-$(CONFIG_KPM) += kpm/
|
||||
REPO_OWNER := KernelSU-Next
|
||||
REPO_NAME := KernelSU-Next
|
||||
REPO_BRANCH := next
|
||||
|
||||
GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git
|
||||
CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl
|
||||
|
||||
KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p')
|
||||
|
||||
ifeq ($(KSU_GITHUB_VERSION),)
|
||||
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
|
||||
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
|
||||
KSU_LOCAL_VERSION := $(shell cd $(srctree)/$(src); $(GIT_BIN) rev-list --count HEAD)
|
||||
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_LOCAL_VERSION) + 200))
|
||||
$(info -- KernelSU-Next version (local .git): $(KSU_VERSION))
|
||||
else
|
||||
$(eval KSU_VERSION := 11998)
|
||||
$(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION))
|
||||
endif
|
||||
else
|
||||
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_GITHUB_VERSION) + 200))
|
||||
$(info -- KernelSU-Next version (GitHub): $(KSU_VERSION))
|
||||
endif
|
||||
|
||||
# .git is a text file while the module is imported by 'git submodule add'.
|
||||
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
|
||||
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow)
|
||||
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count HEAD)
|
||||
# ksu_version: major * 10000 + git version + 200 for historical reasons
|
||||
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200))
|
||||
$(info -- KernelSU-Next version: $(KSU_VERSION))
|
||||
ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
|
||||
else # If there is no .git file, the default version will be passed.
|
||||
$(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU-Next a git submodule!")
|
||||
ccflags-y += -DKSU_VERSION=11998
|
||||
endif
|
||||
|
||||
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
|
||||
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "apk_sign.h"
|
||||
#include "klog.h" // IWYU pragma: keep
|
||||
#include "kernel_compat.h"
|
||||
#include "throne_tracker.h"
|
||||
|
||||
|
||||
struct sdesc {
|
||||
@@ -316,5 +317,21 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
|
||||
|
||||
bool is_manager_apk(char *path)
|
||||
{
|
||||
int tries = 0;
|
||||
|
||||
while (tries++ < 10) {
|
||||
if (!is_lock_held(path))
|
||||
break;
|
||||
|
||||
pr_info("%s: waiting for %s\n", __func__, path);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
// let it go, if retry fails, check_v2_signature will fail to open it anyway
|
||||
if (tries == 10) {
|
||||
pr_info("%s: timeout for %s\n", __func__, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
#include "throne_tracker.h"
|
||||
#include "kernel_compat.h"
|
||||
|
||||
#include "kpm/kpm.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_COMPAT_GET_CRED_RCU)
|
||||
#define KSU_GET_CRED_RCU
|
||||
#endif
|
||||
@@ -120,6 +118,7 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
|
||||
|
||||
groups_sort(group_info);
|
||||
set_groups(cred, group_info);
|
||||
put_group_info(group_info);
|
||||
}
|
||||
|
||||
static void disable_seccomp(void)
|
||||
@@ -144,27 +143,17 @@ void escape_to_root(void)
|
||||
{
|
||||
struct cred *cred;
|
||||
|
||||
#ifdef KSU_GET_CRED_RCU
|
||||
rcu_read_lock();
|
||||
|
||||
do {
|
||||
cred = (struct cred *)__task_cred((current));
|
||||
BUG_ON(!cred);
|
||||
} while (!get_cred_rcu(cred));
|
||||
cred = prepare_creds();
|
||||
if (!cred) {
|
||||
pr_warn("prepare_creds failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cred->euid.val == 0) {
|
||||
pr_warn("Already root, don't escape!\n");
|
||||
rcu_read_unlock();
|
||||
abort_creds(cred);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
cred = (struct cred *)__task_cred(current);
|
||||
|
||||
if (cred->euid.val == 0) {
|
||||
pr_warn("Already root, don't escape!\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
|
||||
|
||||
@@ -200,9 +189,7 @@ void escape_to_root(void)
|
||||
|
||||
setup_groups(profile, cred);
|
||||
|
||||
#ifdef KSU_GET_CRED_RCU
|
||||
rcu_read_unlock();
|
||||
#endif
|
||||
commit_creds(cred);
|
||||
|
||||
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
|
||||
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
|
||||
@@ -269,7 +256,7 @@ static void nuke_ext4_sysfs() {
|
||||
}
|
||||
|
||||
ext4_unregister_sysfs(sb);
|
||||
path_put(&path);
|
||||
path_put(&path);
|
||||
}
|
||||
|
||||
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
@@ -452,26 +439,6 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KPM
|
||||
// KPM Control
|
||||
if(sukisu_is_kpm_control_code(arg2)) {
|
||||
int res;
|
||||
|
||||
pr_info("KPM: calling before arg2=%d\n", (int) arg2);
|
||||
|
||||
res = sukisu_handle_kpm(arg2, arg3, arg4, arg5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
// KPM info
|
||||
if (arg2 == CMD_ENABLE_KPM) {
|
||||
bool KPM_Enabled = IS_ENABLED(CONFIG_KPM);
|
||||
if (copy_to_user((void __user *)arg3, &KPM_Enabled, sizeof(KPM_Enabled)))
|
||||
pr_info("KPM: copy_to_user() failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// all other cmds are for 'root manager'
|
||||
if (!from_manager) {
|
||||
return 0;
|
||||
@@ -602,11 +569,13 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
|
||||
if (path.dentry != path.mnt->mnt_root) {
|
||||
// it is not root mountpoint, maybe umounted by others already.
|
||||
path_put(&path);
|
||||
return;
|
||||
}
|
||||
|
||||
// we are only interest in some specific mounts
|
||||
if (check_mnt && !should_umount(&path)) {
|
||||
path_put(&path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
obj-y += kpm.o
|
||||
obj-y += compact.o
|
||||
obj-y += super_access.o
|
||||
|
||||
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
|
||||
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function
|
||||
@@ -1,102 +0,0 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
#include "../allowlist.h"
|
||||
#include "../manager.h"
|
||||
|
||||
unsigned long sukisu_compact_find_symbol(const char* name);
|
||||
|
||||
// ======================================================================
|
||||
// 兼容函数 for KPM
|
||||
|
||||
static
|
||||
int sukisu_is_su_allow_uid(uid_t uid) {
|
||||
return ksu_is_allow_uid(uid) ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
int sukisu_get_ap_mod_exclude(uid_t uid) {
|
||||
// Not supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int sukisu_is_uid_should_umount(uid_t uid) {
|
||||
return ksu_uid_should_umount(uid) ? 1 : 0;
|
||||
}
|
||||
|
||||
static
|
||||
int sukisu_is_current_uid_manager() {
|
||||
return is_manager();
|
||||
}
|
||||
|
||||
static
|
||||
uid_t sukisu_get_manager_uid() {
|
||||
return ksu_manager_uid;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct CompactAddressSymbol {
|
||||
const char* symbol_name;
|
||||
void* addr;
|
||||
};
|
||||
|
||||
static struct CompactAddressSymbol address_symbol [] = {
|
||||
{ "kallsyms_lookup_name", &kallsyms_lookup_name },
|
||||
{ "compact_find_symbol", &sukisu_compact_find_symbol },
|
||||
{ "is_run_in_sukisu_ultra", (void*)1 },
|
||||
{ "is_su_allow_uid", &sukisu_is_su_allow_uid },
|
||||
{ "get_ap_mod_exclude", &sukisu_get_ap_mod_exclude },
|
||||
{ "is_uid_should_umount", &sukisu_is_uid_should_umount },
|
||||
{ "is_current_uid_manager", &sukisu_is_current_uid_manager },
|
||||
{ "get_manager_uid", &sukisu_get_manager_uid }
|
||||
};
|
||||
|
||||
unsigned long sukisu_compact_find_symbol(const char* name) {
|
||||
int i;
|
||||
unsigned long addr;
|
||||
|
||||
// 先自己在地址表部分查出来
|
||||
for(i = 0; i < (sizeof(address_symbol) / sizeof(struct CompactAddressSymbol)); i++) {
|
||||
struct CompactAddressSymbol* symbol = &address_symbol[i];
|
||||
if(strcmp(name, symbol->symbol_name) == 0) {
|
||||
return (unsigned long) symbol->addr;
|
||||
}
|
||||
}
|
||||
|
||||
// 通过内核来查
|
||||
addr = kallsyms_lookup_name(name);
|
||||
if(addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sukisu_compact_find_symbol);
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef ___SUKISU_KPM_COMPACT_H
|
||||
#define ___SUKISU_KPM_COMPACT_H
|
||||
|
||||
unsigned long sukisu_compact_find_symbol(const char* name);
|
||||
|
||||
#endif
|
||||
184
kernel/kpm/kpm.c
184
kernel/kpm/kpm.c
@@ -1,184 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2025 Liankong (xhsw.new@outlook.com). All Rights Reserved.
|
||||
* 本代码由GPL-2授权
|
||||
*
|
||||
* 适配KernelSU的KPM 内核模块加载器兼容实现
|
||||
*
|
||||
* 集成了 ELF 解析、内存布局、符号处理、重定位(支持 ARM64 重定位类型)
|
||||
* 并参照KernelPatch的标准KPM格式实现加载和控制
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/insn.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) && defined(CONFIG_MODULES)
|
||||
#include <linux/moduleloader.h> // 需要启用 CONFIG_MODULES
|
||||
#endif
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
|
||||
#ifndef NO_OPTIMIZE
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define NO_OPTIMIZE __attribute__((optimize("O0")))
|
||||
#elif defined(__clang__)
|
||||
#define NO_OPTIMIZE __attribute__((optnone))
|
||||
#else
|
||||
#define NO_OPTIMIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ============================================================================================
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_load_module_path(const char* path, const char* args, void* ptr, void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_load_module_path). path=%s args=%s ptr=%p\n", path, args, ptr);
|
||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_unload_module(const char* name, void* ptr, void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_unload_module). name=%s ptr=%p\n", name, ptr);
|
||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_num(void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = 0;
|
||||
printk("KPM: Stub function called (sukisu_kpm_num).\n");
|
||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_info(const char* name, void __user* out, void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_info). name=%s buffer=%p\n", name, out);
|
||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_list(void __user* out, unsigned int bufferSize, void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_list). buffer=%p size=%d\n", out, bufferSize);
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_control(void __user* name, void __user* args, void __user* result) {
|
||||
// This is a KPM module stub.
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_control). name=%p args=%p\n", name, args);
|
||||
__asm__ volatile("nop"); // 精确控制循环不被优化
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
noinline
|
||||
NO_OPTIMIZE
|
||||
void sukisu_kpm_version(void __user* out, unsigned int bufferSize, void __user* result) {
|
||||
int res = -1;
|
||||
printk("KPM: Stub function called (sukisu_kpm_version). buffer=%p size=%d\n", out, bufferSize);
|
||||
if(copy_to_user(result, &res, sizeof(res)) < 1) printk("KPM: Copy to user faild.");
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sukisu_kpm_load_module_path);
|
||||
EXPORT_SYMBOL(sukisu_kpm_unload_module);
|
||||
EXPORT_SYMBOL(sukisu_kpm_num);
|
||||
EXPORT_SYMBOL(sukisu_kpm_info);
|
||||
EXPORT_SYMBOL(sukisu_kpm_list);
|
||||
EXPORT_SYMBOL(sukisu_kpm_version);
|
||||
EXPORT_SYMBOL(sukisu_kpm_control);
|
||||
|
||||
noinline
|
||||
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
if(arg2 == SUKISU_KPM_LOAD) {
|
||||
char kernel_load_path[256] = { 0 };
|
||||
char kernel_args_buffer[256] = { 0 };
|
||||
|
||||
if(arg3 == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy_from_user((char*)&kernel_load_path, (const char __user *)arg3, 255);
|
||||
if(arg4 != 0) {
|
||||
strncpy_from_user((char*)&kernel_args_buffer, (const char __user *)arg4, 255);
|
||||
}
|
||||
sukisu_kpm_load_module_path((const char*)&kernel_load_path, (const char*) &kernel_args_buffer, NULL, (void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_UNLOAD) {
|
||||
char kernel_name_buffer[256] = { 0 };
|
||||
|
||||
if(arg3 == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
||||
sukisu_kpm_unload_module((const char*) &kernel_name_buffer, NULL, (void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_NUM) {
|
||||
sukisu_kpm_num((void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_INFO) {
|
||||
char kernel_name_buffer[256] = { 0 };
|
||||
|
||||
if(arg3 == 0 || arg4 == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy_from_user((char*)&kernel_name_buffer, (const char __user *)arg3, 255);
|
||||
sukisu_kpm_info((const char*) &kernel_name_buffer, (char __user*) arg4, (void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_LIST) {
|
||||
sukisu_kpm_list((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_VERSION) {
|
||||
sukisu_kpm_version((char __user*) arg3, (unsigned int) arg4, (void __user*) arg5);
|
||||
} else if(arg2 == SUKISU_KPM_CONTROL) {
|
||||
sukisu_kpm_control((char __user*) arg3, (char __user*) arg4, (void __user*) arg5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sukisu_is_kpm_control_code(unsigned long arg2) {
|
||||
return (arg2 >= CMD_KPM_CONTROL && arg2 <= CMD_KPM_CONTROL_MAX) ? 1 : 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sukisu_handle_kpm);
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef ___SUKISU_KPM_H
|
||||
#define ___SUKISU_KPM_H
|
||||
|
||||
int sukisu_handle_kpm(unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
||||
int sukisu_is_kpm_control_code(unsigned long arg2);
|
||||
|
||||
// KPM控制代码
|
||||
#define CMD_KPM_CONTROL 28
|
||||
#define CMD_KPM_CONTROL_MAX 35
|
||||
|
||||
// 控制代码
|
||||
|
||||
// prctl(xxx, 28, "PATH", "ARGS")
|
||||
// success return 0, error return -N
|
||||
#define SUKISU_KPM_LOAD 28
|
||||
|
||||
// prctl(xxx, 29, "NAME")
|
||||
// success return 0, error return -N
|
||||
#define SUKISU_KPM_UNLOAD 29
|
||||
|
||||
// num = prctl(xxx, 30)
|
||||
// error return -N
|
||||
// success return +num or 0
|
||||
#define SUKISU_KPM_NUM 30
|
||||
|
||||
// prctl(xxx, 31, Buffer, BufferSize)
|
||||
// success return +out, error return -N
|
||||
#define SUKISU_KPM_LIST 31
|
||||
|
||||
// prctl(xxx, 32, "NAME", Buffer[256])
|
||||
// success return +out, error return -N
|
||||
#define SUKISU_KPM_INFO 32
|
||||
|
||||
// prctl(xxx, 33, "NAME", "ARGS")
|
||||
// success return KPM's result value
|
||||
// error return -N
|
||||
#define SUKISU_KPM_CONTROL 33
|
||||
|
||||
// prctl(xxx, 34, buffer, bufferSize)
|
||||
// success return KPM's result value
|
||||
// error return -N
|
||||
#define SUKISU_KPM_VERSION 34
|
||||
|
||||
#endif
|
||||
@@ -1,289 +0,0 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/elf.h> /* 包含 ARM64 重定位类型定义 */
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
// 结构体成员元数据
|
||||
struct DynamicStructMember {
|
||||
const char* name;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
// 结构体元数据(包含总大小)
|
||||
struct DynamicStructInfo {
|
||||
const char* name;
|
||||
size_t count;
|
||||
size_t total_size;
|
||||
struct DynamicStructMember* members;
|
||||
};
|
||||
|
||||
// 定义结构体元数据的宏(直接使用 struct 名称)
|
||||
#define DYNAMIC_STRUCT_BEGIN(struct_name) \
|
||||
static struct DynamicStructMember struct_name##_members[] = {
|
||||
|
||||
#define DEFINE_MEMBER(struct_name, member) \
|
||||
{ \
|
||||
.name = #member, \
|
||||
.size = sizeof(((struct struct_name*)0)->member), \
|
||||
.offset = offsetof(struct struct_name, member) \
|
||||
},
|
||||
|
||||
#define DYNAMIC_STRUCT_END(struct_name) \
|
||||
}; \
|
||||
static struct DynamicStructInfo struct_name##_info = { \
|
||||
.name = #struct_name, \
|
||||
.count = sizeof(struct_name##_members) / sizeof(struct DynamicStructMember), \
|
||||
.total_size = sizeof(struct struct_name), \
|
||||
.members = struct_name##_members \
|
||||
};
|
||||
|
||||
// ==================================================================================
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#define KERNEL_VERSION_6_1 KERNEL_VERSION(6, 1, 0)
|
||||
#define KERNEL_VERSION_5_15 KERNEL_VERSION(5, 15, 0)
|
||||
|
||||
#include <../fs/mount.h>
|
||||
#include <linux/mount.h>
|
||||
|
||||
// 定义元数据
|
||||
DYNAMIC_STRUCT_BEGIN(mount)
|
||||
DEFINE_MEMBER(mount, mnt_parent)
|
||||
DEFINE_MEMBER(mount, mnt)
|
||||
DEFINE_MEMBER(mount, mnt_id)
|
||||
DEFINE_MEMBER(mount, mnt_group_id)
|
||||
DEFINE_MEMBER(mount, mnt_expiry_mark)
|
||||
DEFINE_MEMBER(mount, mnt_master)
|
||||
DEFINE_MEMBER(mount, mnt_devname)
|
||||
DYNAMIC_STRUCT_END(mount)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vfsmount)
|
||||
DEFINE_MEMBER(vfsmount, mnt_root)
|
||||
DEFINE_MEMBER(vfsmount, mnt_sb)
|
||||
DEFINE_MEMBER(vfsmount, mnt_flags)
|
||||
DYNAMIC_STRUCT_END(vfsmount)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(mnt_namespace)
|
||||
DEFINE_MEMBER(mnt_namespace, ns)
|
||||
DEFINE_MEMBER(mnt_namespace, root)
|
||||
DEFINE_MEMBER(mnt_namespace, seq)
|
||||
DEFINE_MEMBER(mnt_namespace, mounts)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||
DEFINE_MEMBER(mnt_namespace, count)
|
||||
#endif
|
||||
DYNAMIC_STRUCT_END(mnt_namespace)
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
DYNAMIC_STRUCT_BEGIN(kprobe)
|
||||
DEFINE_MEMBER(kprobe, addr)
|
||||
DEFINE_MEMBER(kprobe, symbol_name)
|
||||
DEFINE_MEMBER(kprobe, offset)
|
||||
DEFINE_MEMBER(kprobe, pre_handler)
|
||||
DEFINE_MEMBER(kprobe, post_handler)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_5_15
|
||||
DEFINE_MEMBER(kprobe, fault_handler)
|
||||
#endif
|
||||
DEFINE_MEMBER(kprobe, flags)
|
||||
DYNAMIC_STRUCT_END(kprobe)
|
||||
#endif
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mm_types.h>
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vm_area_struct)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_start)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_end)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_flags)
|
||||
DEFINE_MEMBER(vm_area_struct,anon_vma)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_pgoff)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_file)
|
||||
DEFINE_MEMBER(vm_area_struct,vm_private_data)
|
||||
#ifdef CONFIG_ANON_VMA_NAME
|
||||
DEFINE_MEMBER(vm_area_struct, anon_name)
|
||||
#endif
|
||||
DEFINE_MEMBER(vm_area_struct, vm_ops)
|
||||
DYNAMIC_STRUCT_END(vm_area_struct)
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(vm_operations_struct)
|
||||
DEFINE_MEMBER(vm_operations_struct, open)
|
||||
DEFINE_MEMBER(vm_operations_struct, close)
|
||||
DEFINE_MEMBER(vm_operations_struct, name)
|
||||
DEFINE_MEMBER(vm_operations_struct, access)
|
||||
DYNAMIC_STRUCT_END(vm_operations_struct)
|
||||
|
||||
#include <linux/netlink.h>
|
||||
|
||||
DYNAMIC_STRUCT_BEGIN(netlink_kernel_cfg)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, groups)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, flags)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, input)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, cb_mutex)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, bind)
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, unbind)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION_6_1
|
||||
DEFINE_MEMBER(netlink_kernel_cfg, compare)
|
||||
#endif
|
||||
DYNAMIC_STRUCT_END(netlink_kernel_cfg)
|
||||
|
||||
|
||||
#include <linux/sched.h>
|
||||
DYNAMIC_STRUCT_BEGIN(task_struct)
|
||||
DEFINE_MEMBER(task_struct, pid)
|
||||
DEFINE_MEMBER(task_struct, tgid)
|
||||
DEFINE_MEMBER(task_struct, cred)
|
||||
DEFINE_MEMBER(task_struct, real_cred)
|
||||
DEFINE_MEMBER(task_struct, comm)
|
||||
DEFINE_MEMBER(task_struct, parent)
|
||||
DEFINE_MEMBER(task_struct, group_leader)
|
||||
DEFINE_MEMBER(task_struct, mm)
|
||||
DEFINE_MEMBER(task_struct, active_mm)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
DEFINE_MEMBER(task_struct, pids[PIDTYPE_PID].pid)
|
||||
#else
|
||||
DEFINE_MEMBER(task_struct, thread_pid)
|
||||
#endif
|
||||
DEFINE_MEMBER(task_struct, files)
|
||||
DEFINE_MEMBER(task_struct, seccomp)
|
||||
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
||||
DEFINE_MEMBER(task_struct, thread_info)
|
||||
#endif
|
||||
#ifdef CONFIG_CGROUPS
|
||||
DEFINE_MEMBER(task_struct, cgroups)
|
||||
#endif
|
||||
#ifdef CONFIG_SECURITY
|
||||
DEFINE_MEMBER(task_struct, security)
|
||||
#endif
|
||||
DEFINE_MEMBER(task_struct, thread)
|
||||
DYNAMIC_STRUCT_END(task_struct)
|
||||
|
||||
// =====================================================================================================================
|
||||
|
||||
#define STRUCT_INFO(name) &(name##_info)
|
||||
|
||||
static
|
||||
struct DynamicStructInfo* dynamic_struct_infos[] = {
|
||||
STRUCT_INFO(mount),
|
||||
STRUCT_INFO(vfsmount),
|
||||
STRUCT_INFO(mnt_namespace),
|
||||
#ifdef CONFIG_KPROBES
|
||||
STRUCT_INFO(kprobe),
|
||||
#endif
|
||||
STRUCT_INFO(vm_area_struct),
|
||||
STRUCT_INFO(vm_operations_struct),
|
||||
STRUCT_INFO(netlink_kernel_cfg),
|
||||
STRUCT_INFO(task_struct)
|
||||
};
|
||||
|
||||
// return 0 if successful
|
||||
// return -1 if struct not defined
|
||||
int sukisu_super_find_struct(
|
||||
const char* struct_name,
|
||||
size_t* out_size,
|
||||
int* out_members
|
||||
) {
|
||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||
if(strcmp(struct_name, info->name) == 0) {
|
||||
if(out_size)
|
||||
*out_size = info->total_size;
|
||||
if(out_members)
|
||||
*out_members = info->count;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(sukisu_super_find_struct);
|
||||
|
||||
// Dynamic access struct
|
||||
// return 0 if successful
|
||||
// return -1 if struct not defined
|
||||
// return -2 if member not defined
|
||||
int sukisu_super_access (
|
||||
const char* struct_name,
|
||||
const char* member_name,
|
||||
size_t* out_offset,
|
||||
size_t* out_size
|
||||
) {
|
||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||
if(strcmp(struct_name, info->name) == 0) {
|
||||
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||
if (strcmp(info->members[i1].name, member_name) == 0) {
|
||||
if(out_offset)
|
||||
*out_offset = info->members[i].offset;
|
||||
if(out_size)
|
||||
*out_size = info->members[i].size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(sukisu_super_access);
|
||||
|
||||
// 动态 container_of 宏
|
||||
#define DYNAMIC_CONTAINER_OF(offset, member_ptr) ({ \
|
||||
(offset != (size_t)-1) ? (void*)((char*)(member_ptr) - offset) : NULL; \
|
||||
})
|
||||
|
||||
// Dynamic container_of
|
||||
// return 0 if success
|
||||
// return -1 if current struct not defined
|
||||
// return -2 if target member not defined
|
||||
int sukisu_super_container_of(
|
||||
const char* struct_name,
|
||||
const char* member_name,
|
||||
void* ptr,
|
||||
void** out_ptr
|
||||
) {
|
||||
if(ptr == NULL) {
|
||||
return -3;
|
||||
}
|
||||
for(size_t i = 0; i < (sizeof(dynamic_struct_infos) / sizeof(dynamic_struct_infos[0])); i++) {
|
||||
struct DynamicStructInfo* info = dynamic_struct_infos[i];
|
||||
if(strcmp(struct_name, info->name) == 0) {
|
||||
for (size_t i1 = 0; i1 < info->count; i1++) {
|
||||
if (strcmp(info->members[i1].name, member_name) == 0) {
|
||||
*out_ptr = (void*) DYNAMIC_CONTAINER_OF(info->members[i1].offset, ptr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(sukisu_super_container_of);
|
||||
@@ -1,39 +0,0 @@
|
||||
#ifndef __SUKISU_SUPER_ACCESS_H
|
||||
#define __SUKISU_SUPER_ACCESS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/stddef.h>
|
||||
#include "kpm.h"
|
||||
#include "compact.h"
|
||||
|
||||
// return 0 if successful
|
||||
// return -1 if struct not defined
|
||||
int sukisu_super_find_struct(
|
||||
const char* struct_name,
|
||||
size_t* out_size,
|
||||
int* out_members
|
||||
);
|
||||
|
||||
// Dynamic access struct
|
||||
// return 0 if successful
|
||||
// return -1 if struct not defined
|
||||
// return -2 if member not defined
|
||||
int sukisu_super_access (
|
||||
const char* struct_name,
|
||||
const char* member_name,
|
||||
size_t* out_offset,
|
||||
size_t* out_size
|
||||
);
|
||||
|
||||
// Dynamic container_of
|
||||
// return 0 if success
|
||||
// return -1 if current struct not defined
|
||||
// return -2 if target member not defined
|
||||
int sukisu_super_container_of(
|
||||
const char* struct_name,
|
||||
const char* member_name,
|
||||
void* ptr,
|
||||
void** out_ptr
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -25,9 +25,6 @@
|
||||
#define CMD_ENABLE_SU 15
|
||||
#define CMD_HOOK_MODE 16
|
||||
|
||||
// This is used to check if the kernel supports KPM
|
||||
#define CMD_ENABLE_KPM 100
|
||||
|
||||
#define EVENT_POST_FS_DATA 1
|
||||
#define EVENT_BOOT_COMPLETED 2
|
||||
#define EVENT_MODULE_MOUNTED 3
|
||||
|
||||
@@ -396,10 +396,12 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
|
||||
if (orig_read) {
|
||||
fops_proxy.read = read_proxy;
|
||||
}
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
|
||||
orig_read_iter = file->f_op->read_iter;
|
||||
if (orig_read_iter) {
|
||||
fops_proxy.read_iter = read_iter_proxy;
|
||||
}
|
||||
#endif
|
||||
// replace the file_operations
|
||||
file->f_op = &fops_proxy;
|
||||
read_count_append = rc_count;
|
||||
@@ -632,6 +634,29 @@ static void do_stop_input_hook(struct work_struct *work)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
#include "objsec.h" // task_security_struct
|
||||
bool is_ksu_transition(const struct task_security_struct *old_tsec,
|
||||
const struct task_security_struct *new_tsec)
|
||||
{
|
||||
static u32 ksu_sid;
|
||||
char *secdata;
|
||||
u32 seclen;
|
||||
bool allowed = false;
|
||||
|
||||
if (!ksu_sid)
|
||||
security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid);
|
||||
|
||||
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
|
||||
return false;
|
||||
|
||||
allowed = (!strcmp("u:r:init:s0", secdata) && new_tsec->sid == ksu_sid);
|
||||
security_release_secctx(secdata, seclen);
|
||||
|
||||
return allowed;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void stop_vfs_read_hook()
|
||||
{
|
||||
#ifdef CONFIG_KSU_KPROBES_HOOK
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/namei.h>
|
||||
|
||||
#include "allowlist.h"
|
||||
#include "klog.h" // IWYU pragma: keep
|
||||
@@ -14,13 +13,9 @@
|
||||
#include "throne_tracker.h"
|
||||
#include "kernel_compat.h"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
uid_t ksu_manager_uid = KSU_INVALID_UID;
|
||||
|
||||
static struct task_struct *throne_thread;
|
||||
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
||||
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list.tmp"
|
||||
|
||||
struct uid_data {
|
||||
struct list_head list;
|
||||
@@ -120,7 +115,6 @@ struct my_dir_context {
|
||||
void *private_data;
|
||||
int depth;
|
||||
int *stop;
|
||||
struct super_block* root_sb;
|
||||
};
|
||||
// https://docs.kernel.org/filesystems/porting.html
|
||||
// filldir_t (readdir callbacks) calling conventions have changed. Instead of returning 0 or -E... it returns bool now. false means "no more" (as -E... used to) and true - "keep going" (as 0 in old calling conventions). Rationale: callers never looked at specific -E... values anyway. -> iterate_shared() instances require no changes at all, all filldir_t ones in the tree converted.
|
||||
@@ -141,8 +135,6 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
||||
struct my_dir_context *my_ctx =
|
||||
container_of(ctx, struct my_dir_context, ctx);
|
||||
char dirpath[DATA_PATH_LEN];
|
||||
int err;
|
||||
struct path path;
|
||||
|
||||
if (!my_ctx) {
|
||||
pr_err("Invalid context\n");
|
||||
@@ -169,18 +161,6 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
||||
return FILLDIR_ACTOR_CONTINUE;
|
||||
}
|
||||
|
||||
err = kern_path(dirpath, 0, &path);
|
||||
|
||||
if (err) {
|
||||
pr_err("get dirpath %s err: %d\n", dirpath, err);
|
||||
return FILLDIR_ACTOR_CONTINUE;
|
||||
}
|
||||
|
||||
if (my_ctx->root_sb != path.dentry->d_inode->i_sb) {
|
||||
pr_info("skip cross fs: %s", dirpath);
|
||||
return FILLDIR_ACTOR_CONTINUE;
|
||||
}
|
||||
|
||||
if (d_type == DT_DIR && my_ctx->depth > 0 &&
|
||||
(my_ctx->stop && !*my_ctx->stop)) {
|
||||
struct data_path *data = kmalloc(sizeof(struct data_path), GFP_ATOMIC);
|
||||
@@ -236,21 +216,53 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
||||
return FILLDIR_ACTOR_CONTINUE;
|
||||
}
|
||||
|
||||
void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||
/*
|
||||
* small helper to check if lock is held
|
||||
* false - file is stable
|
||||
* true - file is being deleted/renamed
|
||||
* possibly optional
|
||||
*
|
||||
*/
|
||||
bool is_lock_held(const char *path)
|
||||
{
|
||||
int i, stop = 0, err;
|
||||
struct list_head data_path_list;
|
||||
struct path kpath;
|
||||
struct super_block* root_sb;
|
||||
INIT_LIST_HEAD(&data_path_list);
|
||||
|
||||
err = kern_path(path, 0, &kpath);
|
||||
// kern_path returns 0 on success
|
||||
if (kern_path(path, 0, &kpath))
|
||||
return true;
|
||||
|
||||
if (err) {
|
||||
pr_err("get search root %s err: %d\n", path, err);
|
||||
return;
|
||||
// just being defensive
|
||||
if (!kpath.dentry) {
|
||||
path_put(&kpath);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!spin_trylock(&kpath.dentry->d_lock)) {
|
||||
pr_info("%s: lock held, bail out!\n", __func__);
|
||||
path_put(&kpath);
|
||||
return true;
|
||||
}
|
||||
// we hold it ourselves here!
|
||||
|
||||
spin_unlock(&kpath.dentry->d_lock);
|
||||
path_put(&kpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// compat: https://elixir.bootlin.com/linux/v3.9/source/include/linux/fs.h#L771
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
|
||||
#define S_MAGIC_COMPAT(x) ((x)->f_inode->i_sb->s_magic)
|
||||
#else
|
||||
#define S_MAGIC_COMPAT(x) ((x)->f_path.dentry->d_inode->i_sb->s_magic)
|
||||
#endif
|
||||
|
||||
void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||
{
|
||||
int i, stop = 0;
|
||||
struct list_head data_path_list;
|
||||
INIT_LIST_HEAD(&data_path_list);
|
||||
unsigned long data_app_magic = 0;
|
||||
|
||||
// Initialize APK cache list
|
||||
struct apk_path_hash *pos, *n;
|
||||
list_for_each_entry(pos, &apk_path_hash_list, list) {
|
||||
@@ -267,8 +279,6 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||
data.depth = depth;
|
||||
list_add_tail(&data.list, &data_path_list);
|
||||
|
||||
root_sb = kpath.dentry->d_inode->i_sb;
|
||||
|
||||
for (i = depth; i >= 0; i--) {
|
||||
struct data_path *pos, *n;
|
||||
|
||||
@@ -278,8 +288,7 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||
.parent_dir = pos->dirpath,
|
||||
.private_data = uid_data,
|
||||
.depth = pos->depth,
|
||||
.stop = &stop,
|
||||
.root_sb = root_sb };
|
||||
.stop = &stop };
|
||||
struct file *file;
|
||||
|
||||
if (!stop) {
|
||||
@@ -288,6 +297,24 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
|
||||
pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file));
|
||||
goto skip_iterate;
|
||||
}
|
||||
|
||||
// grab magic on first folder, which is /data/app
|
||||
if (!data_app_magic) {
|
||||
if (S_MAGIC_COMPAT(file)) {
|
||||
data_app_magic = S_MAGIC_COMPAT(file);
|
||||
pr_info("%s: dir: %s got magic! 0x%lx\n", __func__, pos->dirpath, data_app_magic);
|
||||
} else {
|
||||
filp_close(file, NULL);
|
||||
goto skip_iterate;
|
||||
}
|
||||
}
|
||||
|
||||
if (S_MAGIC_COMPAT(file) != data_app_magic) {
|
||||
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n", __func__, pos->dirpath,
|
||||
S_MAGIC_COMPAT(file), data_app_magic);
|
||||
filp_close(file, NULL);
|
||||
goto skip_iterate;
|
||||
}
|
||||
|
||||
iterate_dir(file, &ctx.ctx);
|
||||
filp_close(file, NULL);
|
||||
@@ -324,15 +351,27 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
|
||||
return exist;
|
||||
}
|
||||
|
||||
static void track_throne_function()
|
||||
void track_throne()
|
||||
{
|
||||
struct file *fp =
|
||||
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
||||
struct file *fp;
|
||||
int tries = 0;
|
||||
|
||||
while (tries++ < 10) {
|
||||
if (!is_lock_held(SYSTEM_PACKAGES_LIST_PATH)) {
|
||||
fp = ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
|
||||
if (!IS_ERR(fp))
|
||||
break;
|
||||
}
|
||||
|
||||
pr_info("%s: waiting for %s\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
|
||||
msleep(100); // migth as well add a delay
|
||||
};
|
||||
|
||||
if (IS_ERR(fp)) {
|
||||
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n",
|
||||
__func__, PTR_ERR(fp));
|
||||
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", __func__, PTR_ERR(fp));
|
||||
return;
|
||||
}
|
||||
} else
|
||||
pr_info("%s: %s found!\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
|
||||
|
||||
struct list_head uid_list;
|
||||
INIT_LIST_HEAD(&uid_list);
|
||||
@@ -419,23 +458,6 @@ out:
|
||||
}
|
||||
}
|
||||
|
||||
static int throne_tracker_thread(void *data)
|
||||
{
|
||||
pr_info("%s: pid: %d started\n", __func__, current->pid);
|
||||
track_throne_function();
|
||||
throne_thread = NULL;
|
||||
pr_info("%s: pid: %d exit!\n", __func__, current->pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void track_throne()
|
||||
{
|
||||
throne_thread = kthread_run(throne_tracker_thread, NULL, "throne_tracker");
|
||||
if (IS_ERR(throne_thread)) {
|
||||
throne_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ksu_throne_tracker_init()
|
||||
{
|
||||
// nothing to do
|
||||
|
||||
@@ -7,4 +7,6 @@ void ksu_throne_tracker_exit();
|
||||
|
||||
void track_throne();
|
||||
|
||||
bool is_lock_held(const char *path);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:mimeType="application/zip" />
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="content" />
|
||||
<data android:pathPattern=".*\\.zip" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
|
||||
@@ -313,8 +313,3 @@ JNIEXPORT jboolean JNICALL
|
||||
Java_com_rifsxd_ksunext_Natives_setSuEnabled(JNIEnv *env, jobject thiz, jboolean enabled) {
|
||||
return set_su_enabled(enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_rifsxd_ksunext_Natives_isKPMEnabled(JNIEnv *env, jobject) {
|
||||
return is_KPM_enable();
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#define CMD_IS_SU_ENABLED 14
|
||||
#define CMD_ENABLE_SU 15
|
||||
#define CMD_HOOK_MODE 16
|
||||
#define CMD_ENABLE_KPM 100
|
||||
|
||||
static bool ksuctl(int cmd, void* arg1, void* arg2) {
|
||||
int32_t result = 0;
|
||||
@@ -104,9 +103,4 @@ bool is_su_enabled() {
|
||||
// if ksuctl failed, we assume su is enabled, and it cannot be disabled.
|
||||
ksuctl(CMD_IS_SU_ENABLED, &enabled, nullptr);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool is_KPM_enable() {
|
||||
bool enabled = false;
|
||||
return ksuctl(CMD_ENABLE_KPM, &enabled, nullptr), enabled;
|
||||
}
|
||||
@@ -85,6 +85,4 @@ bool set_su_enabled(bool enabled);
|
||||
|
||||
bool is_su_enabled();
|
||||
|
||||
bool is_KPM_enable();
|
||||
|
||||
#endif //KERNELSU_KSU_H
|
||||
|
||||
@@ -81,12 +81,6 @@ object Natives {
|
||||
external fun isSuEnabled(): Boolean
|
||||
external fun setSuEnabled(enabled: Boolean): Boolean
|
||||
|
||||
/**
|
||||
* Check if the KPM (Kernel Package Manager) is enabled.
|
||||
* @return true if KPM is enabled, false otherwise.
|
||||
*/
|
||||
external fun isKPMEnabled(): Boolean
|
||||
|
||||
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
|
||||
private const val NOBODY_UID = 9999
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.rifsxd.ksunext.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@@ -22,6 +24,8 @@ import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.union
|
||||
import androidx.compose.material3.Badge
|
||||
import androidx.compose.material3.BadgedBox
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
@@ -36,6 +40,7 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
@@ -51,9 +56,13 @@ import com.rifsxd.ksunext.Natives
|
||||
import com.rifsxd.ksunext.ksuApp
|
||||
import com.rifsxd.ksunext.ui.screen.BottomBarDestination
|
||||
import com.rifsxd.ksunext.ui.theme.KernelSUTheme
|
||||
import com.rifsxd.ksunext.ui.util.*
|
||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||
import com.rifsxd.ksunext.ui.util.rootAvailable
|
||||
import com.rifsxd.ksunext.ui.util.install
|
||||
import com.rifsxd.ksunext.ui.util.isSuCompatDisabled
|
||||
import com.rifsxd.ksunext.ui.screen.FlashIt
|
||||
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
@@ -70,11 +79,40 @@ class MainActivity : ComponentActivity() {
|
||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||
if (isManager) install()
|
||||
|
||||
val zipUri: Uri? = when (intent?.action) {
|
||||
Intent.ACTION_VIEW, Intent.ACTION_SEND -> {
|
||||
val uri = intent.data ?: intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
|
||||
uri?.let {
|
||||
val name = when (it.scheme) {
|
||||
"file" -> it.lastPathSegment ?: ""
|
||||
"content" -> {
|
||||
contentResolver.query(it, null, null, null, null)?.use { cursor ->
|
||||
val nameIndex = cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
|
||||
if (cursor.moveToFirst() && nameIndex != -1) {
|
||||
cursor.getString(nameIndex)
|
||||
} else {
|
||||
it.lastPathSegment ?: ""
|
||||
}
|
||||
} ?: (it.lastPathSegment ?: "")
|
||||
}
|
||||
else -> it.lastPathSegment ?: ""
|
||||
}
|
||||
if (name.lowercase().endsWith(".zip")) it else null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
setContent {
|
||||
// Read AMOLED mode preference
|
||||
val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
val amoledMode = prefs.getBoolean("enable_amoled", false)
|
||||
|
||||
val moduleViewModel: ModuleViewModel = viewModel()
|
||||
val moduleUpdateCount = moduleViewModel.moduleList.count {
|
||||
moduleViewModel.checkUpdate(it).first.isNotEmpty()
|
||||
}
|
||||
|
||||
KernelSUTheme (
|
||||
amoledMode = amoledMode
|
||||
) {
|
||||
@@ -82,6 +120,19 @@ class MainActivity : ComponentActivity() {
|
||||
val snackBarHostState = remember { SnackbarHostState() }
|
||||
val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination
|
||||
|
||||
val navigator = navController.rememberDestinationsNavigator()
|
||||
|
||||
LaunchedEffect(zipUri) {
|
||||
if (zipUri != null) {
|
||||
navigator.navigate(
|
||||
FlashScreenDestination(
|
||||
FlashIt.FlashModules(listOf(zipUri)),
|
||||
finishIntent = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val showBottomBar = when (currentDestination?.route) {
|
||||
FlashScreenDestination.route -> false // Hide for FlashScreenDestination
|
||||
ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen
|
||||
@@ -95,7 +146,7 @@ class MainActivity : ComponentActivity() {
|
||||
enter = slideInVertically(initialOffsetY = { it }) + fadeIn(),
|
||||
exit = slideOutVertically(targetOffsetY = { it }) + fadeOut()
|
||||
) {
|
||||
BottomBar(navController)
|
||||
BottomBar(navController, moduleUpdateCount)
|
||||
}
|
||||
},
|
||||
contentWindowInsets = WindowInsets(0, 0, 0, 0)
|
||||
@@ -122,43 +173,70 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomBar(navController: NavHostController) {
|
||||
private fun BottomBar(navController: NavHostController, moduleUpdateCount: Int) {
|
||||
val navigator = navController.rememberDestinationsNavigator()
|
||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
||||
val suCompatDisabled = isSuCompatDisabled()
|
||||
val suSFS = getSuSFS()
|
||||
val susSUMode = susfsSUS_SU_Mode()
|
||||
|
||||
NavigationBar(
|
||||
tonalElevation = 8.dp,
|
||||
windowInsets = WindowInsets.systemBars.union(WindowInsets.displayCutout).only(
|
||||
WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom
|
||||
)
|
||||
) {
|
||||
BottomBarDestination.entries.forEach { destination ->
|
||||
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
||||
NavigationBarItem(
|
||||
selected = isCurrentDestOnBackStack,
|
||||
onClick = {
|
||||
if (isCurrentDestOnBackStack) {
|
||||
navigator.popBackStack(destination.direction, false)
|
||||
}
|
||||
navigator.navigate(destination.direction) {
|
||||
popUpTo(NavGraphs.root) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
if (isCurrentDestOnBackStack) {
|
||||
Icon(destination.iconSelected, stringResource(destination.label))
|
||||
BottomBarDestination.entries
|
||||
.filter {
|
||||
// Hide SuperUser and Module when su compat is disabled
|
||||
if (suCompatDisabled) {
|
||||
if (suSFS == "Supported" && susSUMode == "2") {
|
||||
true
|
||||
} else {
|
||||
Icon(destination.iconNotSelected, stringResource(destination.label))
|
||||
// hide SuperUser and Module
|
||||
it != BottomBarDestination.SuperUser && it != BottomBarDestination.Module
|
||||
}
|
||||
},
|
||||
label = { Text(stringResource(destination.label)) },
|
||||
alwaysShowLabel = true
|
||||
)
|
||||
}
|
||||
} else true
|
||||
}
|
||||
.forEach { destination ->
|
||||
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
||||
NavigationBarItem(
|
||||
selected = isCurrentDestOnBackStack,
|
||||
onClick = {
|
||||
if (isCurrentDestOnBackStack) {
|
||||
navigator.popBackStack(destination.direction, false)
|
||||
}
|
||||
navigator.navigate(destination.direction) {
|
||||
popUpTo(NavGraphs.root) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = true
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
// Show badge for Module icon if moduleUpdateCount > 0
|
||||
if (destination == BottomBarDestination.Module && moduleUpdateCount > 0) {
|
||||
BadgedBox(badge = { Badge { Text(moduleUpdateCount.toString()) } }) {
|
||||
if (isCurrentDestOnBackStack) {
|
||||
Icon(destination.iconSelected, stringResource(destination.label))
|
||||
} else {
|
||||
Icon(destination.iconNotSelected, stringResource(destination.label))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isCurrentDestOnBackStack) {
|
||||
Icon(destination.iconSelected, stringResource(destination.label))
|
||||
} else {
|
||||
Icon(destination.iconNotSelected, stringResource(destination.label))
|
||||
}
|
||||
}
|
||||
},
|
||||
label = { Text(stringResource(destination.label)) },
|
||||
alwaysShowLabel = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.dropUnlessResumed
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
@@ -94,6 +95,7 @@ fun AppProfileScreen(
|
||||
val snackBarHost = LocalSnackbarHost.current
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
val scope = rememberCoroutineScope()
|
||||
val viewModel: SuperUserViewModel = viewModel()
|
||||
val failToUpdateAppProfile = stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
|
||||
val failToUpdateSepolicy = stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
|
||||
val suNotAllowed = stringResource(R.string.su_not_allowed).format(appInfo.label)
|
||||
@@ -160,6 +162,7 @@ fun AppProfileScreen(
|
||||
snackBarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid))
|
||||
} else {
|
||||
profile = it
|
||||
viewModel.updateAppProfile(packageName, it)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -165,9 +165,7 @@ fun BackupRestoreScreen(navigator: DestinationsNavigator) {
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
var useOverlayFs by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_overlay_fs", false)
|
||||
)
|
||||
mutableStateOf(readMountSystemFile())
|
||||
}
|
||||
|
||||
val moduleRestore = stringResource(id = R.string.module_restore)
|
||||
|
||||
@@ -90,35 +90,21 @@ fun CustomizationScreen(navigator: DestinationsNavigator) {
|
||||
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
var useLagacyUI by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_legacyui", false)
|
||||
)
|
||||
}
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.Dashboard,
|
||||
title = stringResource(id = R.string.settings_legacyui),
|
||||
summary = stringResource(id = R.string.settings_legacyui_summary),
|
||||
checked = useLagacyUI
|
||||
) {
|
||||
prefs.edit().putBoolean("use_legacyui", it).apply()
|
||||
useLagacyUI = it
|
||||
}
|
||||
|
||||
var useBanner by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_banner", true)
|
||||
)
|
||||
}
|
||||
SwitchItem(
|
||||
enabled = !useLagacyUI,
|
||||
icon = Icons.Filled.ViewCarousel,
|
||||
title = stringResource(id = R.string.settings_banner),
|
||||
summary = stringResource(id = R.string.settings_banner_summary),
|
||||
checked = useBanner
|
||||
) {
|
||||
prefs.edit().putBoolean("use_banner", it).apply()
|
||||
useBanner = it
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.ViewCarousel,
|
||||
title = stringResource(id = R.string.settings_banner),
|
||||
summary = stringResource(id = R.string.settings_banner_summary),
|
||||
checked = useBanner
|
||||
) {
|
||||
prefs.edit().putBoolean("use_banner", it).apply()
|
||||
useBanner = it
|
||||
}
|
||||
}
|
||||
|
||||
var enableAmoled by rememberSaveable {
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.rifsxd.ksunext.ui.screen
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.*
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.dergoogler.mmrl.platform.Platform
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||
import kotlinx.coroutines.launch
|
||||
import com.rifsxd.ksunext.Natives
|
||||
import com.rifsxd.ksunext.ksuApp
|
||||
import com.rifsxd.ksunext.R
|
||||
import com.rifsxd.ksunext.ui.component.SwitchItem
|
||||
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
|
||||
import com.rifsxd.ksunext.ui.util.*
|
||||
|
||||
/**
|
||||
* @author rifsxd
|
||||
* @date 2025/6/15.
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Destination<RootGraph>
|
||||
@Composable
|
||||
fun DeveloperScreen(navigator: DestinationsNavigator) {
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
val snackBarHost = LocalSnackbarHost.current
|
||||
|
||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||
val ksuVersion = if (isManager) Natives.version else null
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopBar(
|
||||
onBack = { navigator.popBackStack() },
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackBarHost) },
|
||||
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||
) { paddingValues ->
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
// --- Developer Options Switch ---
|
||||
var developerOptionsEnabled by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("enable_developer_options", false)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.DeveloperMode,
|
||||
title = stringResource(id = R.string.enable_developer_options),
|
||||
summary = stringResource(id = R.string.enable_developer_options_summary),
|
||||
checked = developerOptionsEnabled
|
||||
) {
|
||||
prefs.edit().putBoolean("enable_developer_options", it).apply()
|
||||
developerOptionsEnabled = it
|
||||
}
|
||||
}
|
||||
|
||||
var useWebUIX by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_webuix", true)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
beta = false,
|
||||
enabled = Platform.isAlive && developerOptionsEnabled,
|
||||
icon = Icons.Filled.WebAsset,
|
||||
title = stringResource(id = R.string.use_webuix),
|
||||
summary = stringResource(id = R.string.use_webuix_summary),
|
||||
checked = useWebUIX
|
||||
) {
|
||||
prefs.edit().putBoolean("use_webuix", it).apply()
|
||||
useWebUIX = it
|
||||
}
|
||||
}
|
||||
|
||||
var enableWebDebugging by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("enable_web_debugging", false)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
enabled = developerOptionsEnabled,
|
||||
icon = Icons.Filled.Web,
|
||||
title = stringResource(id = R.string.enable_web_debugging),
|
||||
summary = stringResource(id = R.string.enable_web_debugging_summary),
|
||||
checked = enableWebDebugging
|
||||
) {
|
||||
prefs.edit().putBoolean("enable_web_debugging", it).apply()
|
||||
enableWebDebugging = it
|
||||
}
|
||||
}
|
||||
|
||||
var useWebUIXEruda by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_webuix_eruda", false)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
beta = false,
|
||||
enabled = Platform.isAlive && useWebUIX && enableWebDebugging,
|
||||
icon = Icons.Filled.FormatListNumbered,
|
||||
title = stringResource(id = R.string.use_webuix_eruda),
|
||||
summary = stringResource(id = R.string.use_webuix_eruda_summary),
|
||||
checked = useWebUIXEruda
|
||||
) {
|
||||
prefs.edit().putBoolean("use_webuix_eruda", it).apply()
|
||||
useWebUIXEruda = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
onBack: () -> Unit = {},
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||
) {
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(R.string.developer)) }, navigationIcon = {
|
||||
IconButton(
|
||||
onClick = onBack
|
||||
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||
},
|
||||
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun DeveloperPreview() {
|
||||
DeveloperScreen(EmptyDestinationsNavigator)
|
||||
}
|
||||
@@ -63,6 +63,8 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import com.rifsxd.ksunext.R
|
||||
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
|
||||
import com.rifsxd.ksunext.ui.component.ConfirmResult
|
||||
import com.rifsxd.ksunext.ui.component.KeyEventBlocker
|
||||
import com.rifsxd.ksunext.ui.util.FlashResult
|
||||
import com.rifsxd.ksunext.ui.util.LkmSelection
|
||||
@@ -77,12 +79,21 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import android.app.Activity
|
||||
|
||||
enum class FlashingStatus {
|
||||
FLASHING,
|
||||
SUCCESS,
|
||||
FAILED
|
||||
}
|
||||
|
||||
fun Context.findActivity(): Activity? = when (this) {
|
||||
is Activity -> this
|
||||
is android.content.ContextWrapper -> baseContext.findActivity()
|
||||
else -> null
|
||||
}
|
||||
|
||||
// Lets you flash modules sequentially when mutiple zipUris are selected
|
||||
fun flashModulesSequentially(
|
||||
uris: List<Uri>,
|
||||
@@ -106,7 +117,11 @@ fun flashModulesSequentially(
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@Destination<RootGraph>
|
||||
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
fun FlashScreen(
|
||||
navigator: DestinationsNavigator,
|
||||
flashIt: FlashIt,
|
||||
finishIntent: Boolean = false
|
||||
) {
|
||||
|
||||
var text by rememberSaveable { mutableStateOf("") }
|
||||
var tempText: String
|
||||
@@ -126,6 +141,8 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
|
||||
|
||||
val activity = context.findActivity()
|
||||
|
||||
val view = LocalView.current
|
||||
DisposableEffect(flashing) {
|
||||
view.keepScreenOn = flashing == FlashingStatus.FLASHING
|
||||
@@ -134,16 +151,49 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler(enabled = flashing == FlashingStatus.FLASHING) {
|
||||
// Disable back button if flashing is running
|
||||
BackHandler(enabled = flashing != FlashingStatus.FLASHING) {
|
||||
navigator.popBackStack()
|
||||
if (finishIntent) activity?.finish()
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (text.isNotEmpty()) {
|
||||
return@LaunchedEffect
|
||||
val confirmDialog = rememberConfirmDialog()
|
||||
var confirmed by rememberSaveable { mutableStateOf(flashIt !is FlashIt.FlashModules) }
|
||||
var pendingFlashIt by rememberSaveable { mutableStateOf<FlashIt?>(null) }
|
||||
var hasFlashed by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(flashIt) {
|
||||
if (flashIt is FlashIt.FlashModules && !confirmed) {
|
||||
val uris = flashIt.uris
|
||||
val moduleNames =
|
||||
uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }
|
||||
.joinToString("")
|
||||
val confirmContent =
|
||||
context.getString(R.string.module_install_prompt_with_name, moduleNames)
|
||||
val confirmTitle = context.getString(R.string.module)
|
||||
val result = confirmDialog.awaitConfirm(
|
||||
title = confirmTitle,
|
||||
content = confirmContent,
|
||||
markdown = true
|
||||
)
|
||||
if (result == ConfirmResult.Confirmed) {
|
||||
confirmed = true
|
||||
pendingFlashIt = flashIt
|
||||
} else {
|
||||
// User cancelled, go back
|
||||
navigator.popBackStack()
|
||||
if (finishIntent) activity?.finish()
|
||||
}
|
||||
} else {
|
||||
confirmed = true
|
||||
pendingFlashIt = flashIt
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(confirmed, pendingFlashIt) {
|
||||
if (!confirmed || pendingFlashIt == null || text.isNotEmpty() || hasFlashed) return@LaunchedEffect
|
||||
hasFlashed = true
|
||||
withContext(Dispatchers.IO) {
|
||||
flashIt(flashIt, onStdout = {
|
||||
flashIt(pendingFlashIt!!, onStdout = {
|
||||
tempText = "$it\n"
|
||||
if (tempText.startsWith("[H[J")) { // clear command
|
||||
text = tempText.substring(6)
|
||||
@@ -172,6 +222,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
flashing,
|
||||
onBack = dropUnlessResumed {
|
||||
navigator.popBackStack()
|
||||
if (finishIntent) activity?.finish()
|
||||
},
|
||||
onSave = {
|
||||
scope.launch {
|
||||
@@ -211,6 +262,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
|
||||
onClick = {
|
||||
navigator.popBackStack()
|
||||
if (finishIntent) activity?.finish()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -282,6 +334,19 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Uri.getFileName(context: Context): String {
|
||||
val contentResolver = context.contentResolver
|
||||
val cursor = contentResolver.query(this, null, null, null, null)
|
||||
return cursor?.use {
|
||||
val nameIndex = it.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
|
||||
if (it.moveToFirst() && nameIndex != -1) {
|
||||
it.getString(nameIndex)
|
||||
} else {
|
||||
this.lastPathSegment ?: "unknown.zip"
|
||||
}
|
||||
} ?: (this.lastPathSegment ?: "unknown.zip")
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
sealed class FlashIt : Parcelable {
|
||||
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :
|
||||
|
||||
@@ -8,8 +8,12 @@ import android.os.Looper
|
||||
import android.system.Os
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
@@ -107,11 +111,7 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
}
|
||||
|
||||
val moduleUpdateCount = moduleViewModel.moduleList.count {
|
||||
moduleViewModel.checkUpdate(it).first.isNotEmpty()
|
||||
}
|
||||
|
||||
StatusCard(kernelVersion, ksuVersion, lkmMode, moduleUpdateCount) {
|
||||
StatusCard(kernelVersion, ksuVersion, lkmMode) {
|
||||
navigator.navigate(InstallScreenDestination)
|
||||
}
|
||||
if (isManager && Natives.requireNewKernel()) {
|
||||
@@ -193,6 +193,19 @@ fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
|
||||
})
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getSeasonalIcon(): ImageVector {
|
||||
val month = Calendar.getInstance().get(Calendar.MONTH) // 0-11 for January-December
|
||||
return when (month) {
|
||||
Calendar.DECEMBER, Calendar.JANUARY, Calendar.FEBRUARY -> Icons.Filled.AcUnit // Winter
|
||||
Calendar.MARCH, Calendar.APRIL, Calendar.MAY -> Icons.Filled.Spa // Spring
|
||||
Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -> Icons.Filled.WbSunny // Summer
|
||||
Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER -> Icons.Filled.Forest // Fall
|
||||
else -> Icons.Filled.Whatshot // Fallback icon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
@@ -201,8 +214,42 @@ private fun TopBar(
|
||||
onInstallClick: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||
) {
|
||||
var isSpinning by remember { mutableStateOf(false) }
|
||||
val rotation by animateFloatAsState(
|
||||
targetValue = if (isSpinning) 360f else 0f,
|
||||
animationSpec = tween(durationMillis = 800),
|
||||
finishedListener = {
|
||||
isSpinning = false
|
||||
}
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
isSpinning = true
|
||||
}
|
||||
|
||||
TopAppBar(
|
||||
title = { Text(stringResource(R.string.app_name)) },
|
||||
title = {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
if (!isSpinning) isSpinning = true
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = getSeasonalIcon(),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp)
|
||||
.graphicsLayer {
|
||||
rotationZ = rotation
|
||||
}
|
||||
)
|
||||
Text(stringResource(R.string.app_name))
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (ksuVersion != null) {
|
||||
if (kernelVersion.isGKI()) {
|
||||
@@ -249,17 +296,6 @@ private fun TopBar(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getSeasonalIcon(): ImageVector {
|
||||
val month = Calendar.getInstance().get(Calendar.MONTH) // 0-11 for January-December
|
||||
return when (month) {
|
||||
Calendar.DECEMBER, Calendar.JANUARY, Calendar.FEBRUARY -> Icons.Filled.AcUnit // Winter
|
||||
Calendar.MARCH, Calendar.APRIL, Calendar.MAY -> Icons.Filled.Spa // Spring
|
||||
Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -> Icons.Filled.WbSunny // Summer
|
||||
Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER -> Icons.Filled.Forest // Fall
|
||||
else -> Icons.Filled.Whatshot // Fallback icon
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StatusCard(
|
||||
@@ -292,8 +328,10 @@ private fun StatusCard(
|
||||
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
if (ksuVersion != null) {
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
} else if (ksuVersion == null && kernelVersion.isGKI()) {
|
||||
onClickInstall()
|
||||
} else {
|
||||
Toast.makeText(context, "Something weird happened... 🤔", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else if (ksuVersion == null && kernelVersion.isGKI()) {
|
||||
onClickInstall()
|
||||
@@ -312,7 +350,7 @@ private fun StatusCard(
|
||||
}
|
||||
|
||||
Icon(
|
||||
getSeasonalIcon(), // Use dynamic seasonal icon
|
||||
imageVector = Icons.Filled.CheckCircle,
|
||||
contentDescription = stringResource(R.string.home_working)
|
||||
)
|
||||
Column(
|
||||
@@ -322,25 +360,49 @@ private fun StatusCard(
|
||||
val labelStyle = LabelItemDefaults.style
|
||||
TextRow(
|
||||
trailingContent = {
|
||||
LabelItem(
|
||||
icon = if (Natives.isSafeMode) {
|
||||
{
|
||||
Icon(
|
||||
tint = labelStyle.contentColor,
|
||||
imageVector = Icons.Filled.Security,
|
||||
contentDescription = null
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||
) {
|
||||
LabelItem(
|
||||
icon = if (Natives.isSafeMode) {
|
||||
{
|
||||
Icon(
|
||||
tint = labelStyle.contentColor,
|
||||
imageVector = Icons.Filled.Security,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
text = workingMode,
|
||||
style = labelStyle.textStyle.copy(color = labelStyle.contentColor),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
text = workingMode,
|
||||
style = labelStyle.textStyle.copy(color = labelStyle.contentColor),
|
||||
)
|
||||
if (isSuCompatDisabled()) {
|
||||
LabelItem(
|
||||
icon = {
|
||||
Icon(
|
||||
tint = labelStyle.contentColor,
|
||||
imageVector = Icons.Filled.Warning,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
text = stringResource(R.string.sucompat_disabled),
|
||||
style = labelStyle.textStyle.copy(
|
||||
color = labelStyle.contentColor,
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
@@ -364,27 +426,11 @@ private fun StatusCard(
|
||||
text = stringResource(R.string.home_module_count, getModuleCount()),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
|
||||
if (moduleUpdateCount > 0) {
|
||||
Text(
|
||||
text = stringResource(R.string.home_module_update_count, moduleUpdateCount),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
||||
val suSFS = getSuSFS()
|
||||
if (suSFS == "Supported") {
|
||||
Text(
|
||||
text = "SuSFS: " + stringResource(R.string.susfs_supported),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kernelVersion.isGKI() -> {
|
||||
Icon(Icons.Filled.Report, stringResource(R.string.home_not_installed))
|
||||
Icon(Icons.Filled.NewReleases, stringResource(R.string.home_not_installed))
|
||||
Column(Modifier.padding(start = 20.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.home_not_installed),
|
||||
@@ -399,7 +445,7 @@ private fun StatusCard(
|
||||
}
|
||||
|
||||
else -> {
|
||||
Icon(Icons.Filled.Dangerous, stringResource(R.string.home_failure))
|
||||
Icon(Icons.Filled.Cancel, stringResource(R.string.home_failure))
|
||||
Column(Modifier.padding(start = 20.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.home_failure),
|
||||
@@ -531,7 +577,7 @@ private fun InfoCard(autoExpand: Boolean = false) {
|
||||
Spacer(Modifier.height(16.dp))
|
||||
InfoCardItem(
|
||||
label = stringResource(R.string.home_susfs_version),
|
||||
content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
|
||||
content = "${stringResource(R.string.susfs_supported)} | ${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
|
||||
icon = painterResource(R.drawable.ic_sus),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,10 +9,14 @@ import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.LocalIndication
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -73,6 +77,7 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
@@ -84,7 +89,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
@@ -287,12 +291,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
floatingActionButton = {
|
||||
if (!hideInstallButton) {
|
||||
val moduleInstall = stringResource(id = R.string.module_install)
|
||||
val confirmTitle = stringResource(R.string.module)
|
||||
var zipUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
|
||||
val confirmDialog = rememberConfirmDialog(onConfirm = {
|
||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(zipUris)))
|
||||
viewModel.markNeedRefresh()
|
||||
})
|
||||
val selectZipLauncher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult()
|
||||
) { result ->
|
||||
@@ -311,19 +309,13 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||
data.data?.let { uris.add(it) }
|
||||
}
|
||||
|
||||
// Show confirm dialog with selected zip file(s) name(s)
|
||||
val moduleNames =
|
||||
uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }
|
||||
.joinToString("")
|
||||
val confirmContent =
|
||||
context.getString(R.string.module_install_prompt_with_name, moduleNames)
|
||||
zipUris = uris
|
||||
confirmDialog.showConfirm(
|
||||
title = confirmTitle,
|
||||
content = confirmContent,
|
||||
markdown = true
|
||||
)
|
||||
if (uris.isEmpty()) return@rememberLauncherForActivityResult
|
||||
|
||||
viewModel.updateZipUris(uris)
|
||||
|
||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(uris)))
|
||||
viewModel.clearZipUris()
|
||||
viewModel.markNeedRefresh()
|
||||
}
|
||||
|
||||
ExtendedFloatingActionButton(
|
||||
@@ -437,6 +429,8 @@ private fun ModuleList(
|
||||
val loadingDialog = rememberLoadingDialog()
|
||||
val confirmDialog = rememberConfirmDialog()
|
||||
|
||||
var expandedModuleId by rememberSaveable { mutableStateOf<String?>(null) }
|
||||
|
||||
suspend fun onModuleUpdate(
|
||||
module: ModuleViewModel.ModuleInfo,
|
||||
changelogUrl: String,
|
||||
@@ -659,6 +653,10 @@ private fun ModuleList(
|
||||
},
|
||||
onClick = {
|
||||
onClickModule(it.dirId, it.name, it.hasWebUi)
|
||||
},
|
||||
expanded = expandedModuleId == module.id,
|
||||
onExpandToggle = {
|
||||
expandedModuleId = if (expandedModuleId == module.id) null else module.id
|
||||
}
|
||||
)
|
||||
|
||||
@@ -684,9 +682,18 @@ fun ModuleItem(
|
||||
onCheckChanged: (Boolean) -> Unit,
|
||||
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
|
||||
onClick: (ModuleViewModel.ModuleInfo) -> Unit,
|
||||
expanded: Boolean,
|
||||
onExpandToggle: () -> Unit,
|
||||
) {
|
||||
val viewModel = viewModel<ModuleViewModel>()
|
||||
|
||||
ElevatedCard(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.clickable(
|
||||
onClick = onExpandToggle
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@@ -694,11 +701,10 @@ fun ModuleItem(
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
val useLagacyUI = prefs.getBoolean("use_legacyui", false)
|
||||
|
||||
val useBanner = prefs.getBoolean("use_banner", true)
|
||||
|
||||
if (useBanner && !useLagacyUI && module.banner.isNotEmpty()) {
|
||||
if (useBanner && module.banner.isNotEmpty()) {
|
||||
val isDark = isSystemInDarkTheme()
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val context = LocalContext.current
|
||||
@@ -769,10 +775,7 @@ fun ModuleItem(
|
||||
}
|
||||
}
|
||||
Column {
|
||||
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val indication = LocalIndication.current
|
||||
val viewModel = viewModel<ModuleViewModel>()
|
||||
|
||||
var developerOptionsEnabled by rememberSaveable {
|
||||
mutableStateOf(
|
||||
@@ -784,112 +787,173 @@ fun ModuleItem(
|
||||
developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
|
||||
}
|
||||
|
||||
if (useLagacyUI) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(22.dp, 18.dp, 22.dp, 12.dp)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(22.dp, 18.dp, 22.dp, 12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
val moduleVersion = stringResource(id = R.string.module_version)
|
||||
val moduleAuthor = stringResource(id = R.string.module_author)
|
||||
val moduleId = stringResource(id = R.string.module_id)
|
||||
val moduleVersionCode = stringResource(id = R.string.module_version_code)
|
||||
val moduleUpdateJson = stringResource(id = R.string.module_update_json)
|
||||
val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(0.8f)
|
||||
) {
|
||||
val moduleVersion = stringResource(id = R.string.module_version)
|
||||
val moduleAuthor = stringResource(id = R.string.module_author)
|
||||
val moduleId = stringResource(id = R.string.module_id)
|
||||
val moduleVersionCode = stringResource(id = R.string.module_version_code)
|
||||
val moduleUpdateJson = stringResource(id = R.string.module_update_json)
|
||||
val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(0.8f)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||
) {
|
||||
Text(
|
||||
text = module.name,
|
||||
fontSize = MaterialTheme.typography.titleMedium.fontSize,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
|
||||
textDecoration = textDecoration,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersion: ${module.version}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleAuthor: ${module.author}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
if (developerOptionsEnabled) {
|
||||
|
||||
Text(
|
||||
text = "$moduleId: ${module.id}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
LabelItem(
|
||||
text = formatSize(module.size),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersionCode: ${module.versionCode}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
if (module.remove) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.uninstall),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onErrorContainer
|
||||
)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
}
|
||||
if (updateUrl.isNotEmpty() && !module.remove && !module.update) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.module_update),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
if (!module.remove) {
|
||||
if (module.update) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.module_updated),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (module.enabled && !module.remove) {
|
||||
if (module.hasWebUi) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.webui),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
if (module.hasActionScript) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.action),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
Switch(
|
||||
enabled = !module.update,
|
||||
checked = module.enabled,
|
||||
onCheckedChange = onCheckChanged,
|
||||
interactionSource = if (!module.hasWebUi) interactionSource else null
|
||||
Text(
|
||||
text = module.name,
|
||||
fontSize = MaterialTheme.typography.titleMedium.fontSize,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.titleMedium.fontFamily
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersion: ${module.version}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleAuthor: ${module.author}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
|
||||
)
|
||||
|
||||
if (developerOptionsEnabled) {
|
||||
|
||||
Text(
|
||||
text = "$moduleId: ${module.id}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersionCode: ${module.versionCode}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
|
||||
)
|
||||
|
||||
Text(
|
||||
text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Text(
|
||||
text = module.description,
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 4,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
Switch(
|
||||
enabled = !module.update,
|
||||
checked = module.enabled,
|
||||
onCheckedChange = onCheckChanged,
|
||||
interactionSource = if (!module.hasWebUi) interactionSource else null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
HorizontalDivider(thickness = Dp.Hairline)
|
||||
Text(
|
||||
text = module.description,
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 4
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
|
||||
if (expanded) {
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = expanded,
|
||||
enter = fadeIn() + expandVertically(),
|
||||
exit = shrinkVertically() + fadeOut()
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -906,7 +970,7 @@ fun ModuleItem(
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(20.dp),
|
||||
imageVector = Icons.Outlined.PlayArrow,
|
||||
imageVector = Icons.Outlined.Terminal,
|
||||
contentDescription = null
|
||||
)
|
||||
if (!module.hasWebUi && updateUrl.isEmpty()) {
|
||||
@@ -948,7 +1012,7 @@ fun ModuleItem(
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f, true))
|
||||
|
||||
if (updateUrl.isNotEmpty()) {
|
||||
if (updateUrl.isNotEmpty() && !module.remove && !module.update) {
|
||||
Button(
|
||||
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
|
||||
enabled = !module.remove,
|
||||
@@ -1018,254 +1082,6 @@ fun ModuleItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(22.dp, 18.dp, 22.dp, 12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
val moduleVersion = stringResource(id = R.string.module_version)
|
||||
val moduleAuthor = stringResource(id = R.string.module_author)
|
||||
val moduleId = stringResource(id = R.string.module_id)
|
||||
val moduleVersionCode = stringResource(id = R.string.module_version_code)
|
||||
val moduleUpdateJson = stringResource(id = R.string.module_update_json)
|
||||
val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(0.8f)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||
) {
|
||||
LabelItem(
|
||||
text = formatSize(module.size),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
)
|
||||
LabelItem(
|
||||
text = if (module.enabled) stringResource(R.string.enabled) else stringResource(R.string.disabled),
|
||||
style = if (module.enabled)
|
||||
com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy()
|
||||
else
|
||||
com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onErrorContainer
|
||||
)
|
||||
)
|
||||
if (module.remove) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.uninstalled),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onErrorContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
if (updateUrl.isNotEmpty() && !module.remove && !module.update) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.module_update),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.onTertiary,
|
||||
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
if (!module.remove) {
|
||||
if (module.update) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.module_updated),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (!module.remove) {
|
||||
if (module.hasWebUi) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.webui),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
if (module.hasActionScript) {
|
||||
LabelItem(
|
||||
text = stringResource(R.string.action),
|
||||
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = module.name,
|
||||
fontSize = MaterialTheme.typography.titleMedium.fontSize,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.titleMedium.fontFamily,
|
||||
textDecoration = textDecoration,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersion: ${module.version}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleAuthor: ${module.author}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
if (developerOptionsEnabled) {
|
||||
|
||||
Text(
|
||||
text = "$moduleId: ${module.id}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "$moduleVersionCode: ${module.versionCode}",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
Text(
|
||||
text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty",
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
IconButton(onClick = { expanded = true }) {
|
||||
Icon(
|
||||
Icons.Filled.MoreVert,
|
||||
contentDescription = "Module actions"
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false }
|
||||
) {
|
||||
if (updateUrl.isNotEmpty() && !module.remove) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.module_update)) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
onUpdate(module)
|
||||
}
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
if (!module.remove) {
|
||||
if (module.hasWebUi) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.webui)) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
onClick(module)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (module.hasActionScript) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.action)) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId))
|
||||
viewModel.markNeedRefresh()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (module.hasWebUi || module.hasActionScript ) {
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
|
||||
if (!module.remove) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(
|
||||
if (module.enabled) stringResource(R.string.disable)
|
||||
else stringResource(R.string.enable)
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
expanded = false
|
||||
onCheckChanged(!module.enabled)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (module.remove) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.restore)) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
onRestore(module)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.uninstall)) },
|
||||
onClick = {
|
||||
expanded = false
|
||||
onUninstall(module)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
Text(
|
||||
text = module.description,
|
||||
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
|
||||
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 4,
|
||||
textDecoration = textDecoration
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1304,5 +1120,5 @@ fun ModuleItemPreview() {
|
||||
size = 12345678L,
|
||||
banner = ""
|
||||
)
|
||||
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {})
|
||||
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}, false, {})
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplat
|
||||
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||
import com.ramcosta.composedestinations.generated.destinations.BackupRestoreScreenDestination
|
||||
import com.ramcosta.composedestinations.generated.destinations.CustomizationScreenDestination
|
||||
import com.ramcosta.composedestinations.generated.destinations.DeveloperScreenDestination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -224,9 +225,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
|
||||
var useOverlayFs by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_overlay_fs", false)
|
||||
)
|
||||
mutableStateOf(readMountSystemFile())
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
useOverlayFs = readMountSystemFile()
|
||||
}
|
||||
|
||||
var showRebootDialog by remember { mutableStateOf(false) }
|
||||
@@ -244,8 +247,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
useOverlayFs = it
|
||||
if (useOverlayFs) {
|
||||
moduleBackup()
|
||||
updateMountSystemFile(true)
|
||||
} else {
|
||||
moduleMigration()
|
||||
updateMountSystemFile(false)
|
||||
}
|
||||
if (isManager) install()
|
||||
showRebootDialog = true
|
||||
@@ -289,78 +294,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
checkUpdate = it
|
||||
}
|
||||
|
||||
var enableWebDebugging by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("enable_web_debugging", false)
|
||||
)
|
||||
}
|
||||
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.Web,
|
||||
title = stringResource(id = R.string.enable_web_debugging),
|
||||
summary = stringResource(id = R.string.enable_web_debugging_summary),
|
||||
checked = enableWebDebugging
|
||||
) {
|
||||
prefs.edit().putBoolean("enable_web_debugging", it).apply()
|
||||
enableWebDebugging = it
|
||||
}
|
||||
}
|
||||
|
||||
var developerOptionsEnabled by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("enable_developer_options", false)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
icon = Icons.Filled.DeveloperMode,
|
||||
title = stringResource(id = R.string.enable_developer_options),
|
||||
summary = stringResource(id = R.string.enable_developer_options_summary),
|
||||
checked = developerOptionsEnabled
|
||||
) {
|
||||
prefs.edit().putBoolean("enable_developer_options", it).apply()
|
||||
developerOptionsEnabled = it
|
||||
}
|
||||
}
|
||||
|
||||
var useWebUIX by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_webuix", true)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
beta = false,
|
||||
enabled = Platform.isAlive,
|
||||
icon = Icons.Filled.WebAsset,
|
||||
title = stringResource(id = R.string.use_webuix),
|
||||
summary = stringResource(id = R.string.use_webuix_summary),
|
||||
checked = useWebUIX
|
||||
) {
|
||||
prefs.edit().putBoolean("use_webuix", it).apply()
|
||||
useWebUIX = it
|
||||
}
|
||||
}
|
||||
var useWebUIXEruda by rememberSaveable {
|
||||
mutableStateOf(
|
||||
prefs.getBoolean("use_webuix_eruda", false)
|
||||
)
|
||||
}
|
||||
if (ksuVersion != null) {
|
||||
SwitchItem(
|
||||
beta = false,
|
||||
enabled = Platform.isAlive && useWebUIX && enableWebDebugging,
|
||||
icon = Icons.Filled.FormatListNumbered,
|
||||
title = stringResource(id = R.string.use_webuix_eruda),
|
||||
summary = stringResource(id = R.string.use_webuix_eruda_summary),
|
||||
checked = useWebUIXEruda
|
||||
) {
|
||||
prefs.edit().putBoolean("use_webuix_eruda", it).apply()
|
||||
useWebUIXEruda = it
|
||||
}
|
||||
}
|
||||
|
||||
if (isOverlayAvailable && useOverlayFs) {
|
||||
val shrink = stringResource(id = R.string.shrink_sparse_image)
|
||||
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
|
||||
@@ -415,6 +348,22 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
)
|
||||
}
|
||||
|
||||
val developer = stringResource(id = R.string.developer)
|
||||
if (ksuVersion != null) {
|
||||
ListItem(
|
||||
leadingContent = {
|
||||
Icon(
|
||||
Icons.Filled.DeveloperBoard,
|
||||
developer
|
||||
)
|
||||
},
|
||||
headlineContent = { Text(developer) },
|
||||
modifier = Modifier.clickable {
|
||||
navigator.navigate(DeveloperScreenDestination)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
|
||||
if (lkmMode) {
|
||||
UninstallItem(navigator) {
|
||||
|
||||
@@ -54,19 +54,6 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(viewModel.search) {
|
||||
if (viewModel.search.isEmpty()) {
|
||||
listState.scrollToItem(0)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (viewModel.refreshOnReturn) {
|
||||
viewModel.fetchAppList()
|
||||
viewModel.refreshOnReturn = false
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
SearchAppBar(
|
||||
@@ -105,7 +92,7 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
)
|
||||
}, onClick = {
|
||||
viewModel.showSystemApps = !viewModel.showSystemApps
|
||||
viewModel.updateShowSystemApps(!viewModel.showSystemApps)
|
||||
showDropdown = false
|
||||
})
|
||||
}
|
||||
@@ -131,7 +118,6 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
|
||||
) {
|
||||
items(viewModel.appList, key = { it.packageName + it.uid }) { app ->
|
||||
AppItem(app) {
|
||||
viewModel.refreshOnReturn = true
|
||||
navigator.navigate(AppProfileScreenDestination(app))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,16 @@ private fun ksuDaemonOverlayfsPath(): String {
|
||||
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud_overlayfs.so"
|
||||
}
|
||||
|
||||
fun readMountSystemFile(): Boolean {
|
||||
val shell = getRootShell()
|
||||
val filePath = "/data/adb/ksu/mount_system"
|
||||
val result = ShellUtils.fastCmd(shell, "cat $filePath").trim()
|
||||
return result == "OVERLAYFS"
|
||||
}
|
||||
|
||||
// Get the path based on the user's choice
|
||||
fun getKsuDaemonPath(): String {
|
||||
val prefs = ksuApp.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
val useOverlayFs = prefs.getBoolean("use_overlay_fs", false)
|
||||
val useOverlayFs = readMountSystemFile()
|
||||
|
||||
return if (useOverlayFs) {
|
||||
ksuDaemonOverlayfsPath()
|
||||
@@ -49,6 +55,16 @@ fun getKsuDaemonPath(): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMountSystemFile(useOverlayFs: Boolean) {
|
||||
val shell = getRootShell()
|
||||
val filePath = "/data/adb/ksu/mount_system"
|
||||
if (useOverlayFs) {
|
||||
ShellUtils.fastCmd(shell, "echo -n OVERLAYFS > $filePath")
|
||||
} else {
|
||||
ShellUtils.fastCmd(shell, "echo -n MAGIC_MOUNT > $filePath")
|
||||
}
|
||||
}
|
||||
|
||||
data class FlashResult(val code: Int, val err: String, val showReboot: Boolean) {
|
||||
constructor(result: Shell.Result, showReboot: Boolean) : this(result.code, result.err.joinToString("\n"), showReboot)
|
||||
constructor(result: Shell.Result) : this(result, result.isSuccess)
|
||||
@@ -89,9 +105,9 @@ fun createRootShell(globalMnt: Boolean = false): Shell {
|
||||
val builder = Shell.Builder.create()
|
||||
return try {
|
||||
if (globalMnt) {
|
||||
builder.build(getKsuDaemonPath(), "debug", "su", "-g")
|
||||
builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
|
||||
} else {
|
||||
builder.build(getKsuDaemonPath(), "debug", "su")
|
||||
builder.build(ksuDaemonMagicPath(), "debug", "su")
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Log.w(TAG, "ksu failed: ", e)
|
||||
@@ -612,6 +628,10 @@ fun getModuleSize(dir: File): Long {
|
||||
return result.toLongOrNull() ?: 0L
|
||||
}
|
||||
|
||||
fun isSuCompatDisabled(): Boolean {
|
||||
return Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT && !Natives.isSuEnabled()
|
||||
}
|
||||
|
||||
fun setAppProfileTemplate(id: String, template: String): Boolean {
|
||||
val shell = getRootShell()
|
||||
val escapedTemplate = template.replace("\"", "\\\"")
|
||||
@@ -645,72 +665,4 @@ fun launchApp(packageName: String) {
|
||||
fun restartApp(packageName: String) {
|
||||
forceStopApp(packageName)
|
||||
launchApp(packageName)
|
||||
}
|
||||
|
||||
fun getKpmmgrPath(): String {
|
||||
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libkpmmgr.so"
|
||||
}
|
||||
|
||||
|
||||
fun loadKpmModule(path: String, args: String? = null): String {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}"
|
||||
return ShellUtils.fastCmd(shell, cmd)
|
||||
}
|
||||
|
||||
fun unloadKpmModule(name: String): String {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} unload $name"
|
||||
return ShellUtils.fastCmd(shell, cmd)
|
||||
}
|
||||
|
||||
fun getKpmModuleCount(): Int {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} num"
|
||||
val result = ShellUtils.fastCmd(shell, cmd)
|
||||
return result.trim().toIntOrNull() ?: 0
|
||||
}
|
||||
|
||||
fun runCmd(shell : Shell, cmd : String) : String {
|
||||
return shell.newJob()
|
||||
.add(cmd)
|
||||
.to(mutableListOf<String>(), null)
|
||||
.exec().out
|
||||
.joinToString("\n")
|
||||
}
|
||||
|
||||
fun listKpmModules(): String {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} list"
|
||||
return try {
|
||||
runCmd(shell, cmd).trim()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to list KPM modules", e)
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun getKpmModuleInfo(name: String): String {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} info $name"
|
||||
return try {
|
||||
runCmd(shell, cmd).trim()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to get KPM module info: $name", e)
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun controlKpmModule(name: String, args: String? = null): Int {
|
||||
val shell = getRootShell()
|
||||
val cmd = """${getKpmmgrPath()} control $name "${args ?: ""}""""
|
||||
val result = runCmd(shell, cmd)
|
||||
return result.trim().toIntOrNull() ?: -1
|
||||
}
|
||||
|
||||
fun getKpmVersion(): String {
|
||||
val shell = getRootShell()
|
||||
val cmd = "${getKpmmgrPath()} version"
|
||||
val result = ShellUtils.fastCmd(shell, cmd)
|
||||
return result.trim()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.rifsxd.ksunext.ui.viewmodel
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -93,6 +94,16 @@ class ModuleViewModel : ViewModel() {
|
||||
isNeedRefresh = true
|
||||
}
|
||||
|
||||
var zipUris by mutableStateOf<List<Uri>>(emptyList())
|
||||
|
||||
fun updateZipUris(uris: List<Uri>) {
|
||||
zipUris = uris
|
||||
}
|
||||
|
||||
fun clearZipUris() {
|
||||
zipUris = emptyList()
|
||||
}
|
||||
|
||||
fun fetchModuleList() {
|
||||
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.rifsxd.ksunext.ui.viewmodel
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.os.Parcelable
|
||||
@@ -24,16 +28,17 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import java.text.Collator
|
||||
import java.util.*
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import androidx.core.content.edit
|
||||
|
||||
class SuperUserViewModel : ViewModel() {
|
||||
val isPlatformAlive get() = Platform.isAlive
|
||||
|
||||
var refreshOnReturn by mutableStateOf(false)
|
||||
public set
|
||||
|
||||
companion object {
|
||||
private const val TAG = "SuperUserViewModel"
|
||||
private var apps by mutableStateOf<List<AppInfo>>(emptyList())
|
||||
private var profileOverrides by mutableStateOf<Map<String, Natives.Profile>>(emptyMap())
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
@@ -63,16 +68,26 @@ class SuperUserViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
private val prefs = ksuApp.getSharedPreferences("settings", Context.MODE_PRIVATE)!!
|
||||
|
||||
var search by mutableStateOf("")
|
||||
var showSystemApps by mutableStateOf(false)
|
||||
var showSystemApps by mutableStateOf(prefs.getBoolean("show_system_apps", false))
|
||||
private set
|
||||
var isRefreshing by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
fun updateShowSystemApps(newValue: Boolean) {
|
||||
showSystemApps = newValue
|
||||
prefs.edit { putBoolean("show_system_apps", newValue) }
|
||||
}
|
||||
|
||||
private val sortedList by derivedStateOf {
|
||||
val comparator = compareBy<AppInfo> {
|
||||
when {
|
||||
it.allowSu -> 0
|
||||
it.hasCustomProfile -> 1
|
||||
it.profile != null && it.profile.allowSu -> 0
|
||||
it.profile != null && (
|
||||
if (it.profile.allowSu) !it.profile.rootUseDefault else !it.profile.nonRootUseDefault
|
||||
) -> 1
|
||||
else -> 2
|
||||
}
|
||||
}.then(compareBy(Collator.getInstance(Locale.getDefault()), AppInfo::label))
|
||||
@@ -82,7 +97,9 @@ class SuperUserViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
val appList by derivedStateOf {
|
||||
sortedList.filter {
|
||||
sortedList.map { app ->
|
||||
profileOverrides[app.packageName]?.let { app.copy(profile = it) } ?: app
|
||||
}.filter {
|
||||
it.label.contains(search, true) || it.packageName.contains(
|
||||
search,
|
||||
true
|
||||
@@ -94,11 +111,15 @@ class SuperUserViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAppProfile(packageName: String, newProfile: Natives.Profile) {
|
||||
profileOverrides = profileOverrides.toMutableMap().apply {
|
||||
put(packageName, newProfile)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun fetchAppList() {
|
||||
isRefreshing = true
|
||||
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
withTimeoutOrNull(TIMEOUT_MILLIS) {
|
||||
while (!isPlatformAlive) {
|
||||
@@ -124,6 +145,7 @@ class SuperUserViewModel : ViewModel() {
|
||||
profile = profile,
|
||||
)
|
||||
}.filter { it.packageName != ksuApp.packageName }
|
||||
profileOverrides = emptyMap()
|
||||
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="issue_report_title">Problémája van?</string>
|
||||
<string name="issue_report_body">Hibát észlelt, vagy van visszajelzése?</string>
|
||||
<string name="issue_report_body">Hibát észlelt, vagy visszajelzése van?</string>
|
||||
<string name="issue_report_body_2">Jelentse mielőbb!</string>
|
||||
<string name="issue_report_github">Report on GitHub</string>
|
||||
<string name="issue_report_telegram">Kapcsolatfelvétel Telegramon keresztül</string>
|
||||
@@ -12,13 +12,16 @@
|
||||
<string name="home">Kezdőlap</string>
|
||||
<string name="home_not_installed">Nincs telepítve</string>
|
||||
<string name="home_click_to_install">Kattintson a telepítéshez</string>
|
||||
<string name="lkm_alternative_suggestion">Telepíts GKI kernelt, vagy integráld a KernelSU Next-et az eszközödbe.</string>
|
||||
<string name="home_working">Működik</string>
|
||||
<string name="home_working_version">Verzió: %d</string>
|
||||
<string name="home_superuser_count">Superuserek: %d</string>
|
||||
<string name="home_module_count">Modulok: %d</string>
|
||||
<string name="home_module_update_count">Frissítések: %d</string>
|
||||
<string name="home_failure">KernelSU Next v2 aláírás nem található a kernelben! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Kérje meg kernel fejlesztőjét, hogy integrálja a KernelSU Next-et!</string>
|
||||
<string name="home_kernel">Kernel verzió</string>
|
||||
<string name="disable">Kikapcsolva</string>
|
||||
<string name="enabled">Bekapcsolva</string>
|
||||
<string name="disabled">Kikapcsolva</string>
|
||||
<string name="susfs_supported">Támogatott</string>
|
||||
@@ -38,13 +41,15 @@
|
||||
<string name="module_empty">Nincs telepített modul</string>
|
||||
<string name="module">Modul</string>
|
||||
<string name="module_install_prompt_with_name">A következő modul(ok) lesznek telepítve: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Rendezés (A-Z)</string>
|
||||
<string name="module_sort_z_to_a">Rendezés (Z-A)</string>
|
||||
<string name="module_sort_a_to_z">Rendezés (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Rendezés (Z → A)</string>
|
||||
<string name="module_size_high_to_low">Rendezés (Magas → Alacsony)</string>
|
||||
<string name="uninstall">Eltávolítás</string>
|
||||
<string name="restore">Visszaállítás</string>
|
||||
<string name="module_install">Telepítés</string>
|
||||
<string name="install">Telepítés</string>
|
||||
<string name="reboot">Újraindítás</string>
|
||||
<string name="uninstalled">Eltávolítva</string>
|
||||
<string name="settings">Beállítások</string>
|
||||
<string name="reboot_userspace">Lágy újraindítás</string>
|
||||
<string name="reboot_recovery">Újraindítás Recovery módba</string>
|
||||
@@ -96,6 +101,7 @@
|
||||
<string name="proceed">Folytatás</string>
|
||||
<string name="cancel">Mégse</string>
|
||||
<string name="later">Később</string>
|
||||
<string name="lkm_warning_message">Az LKM patch zárt forráskódú komponenseken alapul. Folytatja?</string>
|
||||
<string name="home_next_kernelsu">🔥 Next build</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next kísérleti branch. Nézze meg a GitHubon!</string>
|
||||
@@ -129,6 +135,7 @@
|
||||
<string name="profile_selinux_domain">Domain</string>
|
||||
<string name="profile_selinux_rules">Szabályok</string>
|
||||
<string name="module_update">Frissítés</string>
|
||||
<string name="module_updated">Frissítve</string>
|
||||
<string name="module_downloading">%s modul letöltése</string>
|
||||
<string name="module_start_downloading">Letöltés indítása: %s</string>
|
||||
<string name="new_version_available">Új verzió (%s) elérhető, kattintson a frissítéshez.</string>
|
||||
@@ -136,6 +143,7 @@
|
||||
<string name="close">Bezár</string>
|
||||
<string name="force_stop_app">Kényszer leállítás</string>
|
||||
<string name="restart_app">Újraindítás</string>
|
||||
<string name="restart_app_message">A módosítás érvénybe lépéséhez újra kell indítani az alkalmazást.</string>
|
||||
<string name="failed_to_update_sepolicy">Nem sikerült frissíteni a SELinux szabályait a következőhöz: %s</string>
|
||||
<string name="su_not_allowed">Superuser megadása nem engedélyezett a következőhöz: %s</string>
|
||||
<string name="module_changelog">Változásnapló</string>
|
||||
@@ -194,4 +202,20 @@
|
||||
<string name="settings_disable_su">Kapcsolja ki a su kompatibilitást</string>
|
||||
<string name="settings_disable_su_summary">Ideiglenesen tiltsa le bármely alkalmazás azon képességét, hogy root jogosultságokat szerezzen a su paranccsal (a már meglévő folyamatokat ez nem érinti).</string>
|
||||
<string name="settings_language">Nyelv</string>
|
||||
<string name="lkm_mode_deprecated">Az LKM mód elavult!</string>
|
||||
<string name="hook_mode">Hook módszer</string>
|
||||
<string name="enable">Bekapcsolva</string>
|
||||
<string name="module_size_low_to_high">Rendezés (Alacsony → Magas)</string>
|
||||
<string name="settings_amoled_mode">AMOLED mód</string>
|
||||
<string name="settings_amoled_mode_summary">Engedélyezzen egy teljesen fekete témát, amely leginkább AMOLED képernyőkön hasznos. Csökkenti a szem megerőltetését és az akkumulátort is kíméli.</string>
|
||||
<string name="restart_required">Újraindítás szükséges</string>
|
||||
<string name="settings_legacyui">Legacy UI használata</string>
|
||||
<string name="settings_legacyui_summary">Váltás az előző felhasználói felületre.</string>
|
||||
<string name="settings_banner">Bannerek engedélyezése</string>
|
||||
<string name="settings_banner_summary">Mutassa a modulok hátterének bannereit.</string>
|
||||
<string name="use_webuix">WebUI X használata</string>
|
||||
<string name="use_webuix_summary">A WebUI X több API-t támogat, mint a WebUI.</string>
|
||||
<string name="use_webuix_eruda">Eruda injektálása a WebUI X-be</string>
|
||||
<string name="use_webuix_eruda_summary">Hibakeresési konzol injektálása a WebUI X-be a hibakeresés megkönnyítése érdekében. Ehhez a webes hibakeresést be kell kapcsolni.</string>
|
||||
<string name="customization">Testreszabás</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
<string name="home_working_version">Versione: %d</string>
|
||||
<string name="home_superuser_count">Applicazioni con accesso root: %d</string>
|
||||
<string name="home_module_count">Moduli: %d</string>
|
||||
<string name="home_module_update_count">Aggiornamenti: %d</string>
|
||||
<string name="home_failure">Firma KernelSU Next v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel di integrare KernelSU Next!</string>
|
||||
<string name="home_kernel">Versione Kernel</string>
|
||||
<string name="hook_mode">Modalità Hook</string>
|
||||
<string name="enable">Abilita</string>
|
||||
<string name="disable">Disabilita</string>
|
||||
<string name="enabled">Abilitato</string>
|
||||
<string name="disabled">Disabilitato</string>
|
||||
<string name="susfs_supported">Supportato</string>
|
||||
@@ -42,13 +45,16 @@
|
||||
<string name="module_empty">Nessun modulo installato</string>
|
||||
<string name="module">Modulo</string>
|
||||
<string name="module_install_prompt_with_name">Verranno installati i seguenti moduli: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Ordinare (A-Z)</string>
|
||||
<string name="module_sort_z_to_a">Ordinare (Z-A)</string>
|
||||
<string name="module_sort_a_to_z">Ordina (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Ordina (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Ordina (Basso → Alto)</string>
|
||||
<string name="module_size_high_to_low">Ordina (Alto → Basso)</string>
|
||||
<string name="uninstall">Disinstalla</string>
|
||||
<string name="restore">Ripristina</string>
|
||||
<string name="module_install">Installa</string>
|
||||
<string name="install">Installa</string>
|
||||
<string name="reboot">Riavvia</string>
|
||||
<string name="uninstalled">Disinstallato</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="reboot_userspace">Riavvio rapido</string>
|
||||
<string name="reboot_recovery">Riavvia in Recovery</string>
|
||||
@@ -100,6 +106,7 @@
|
||||
<string name="proceed">Procedere</string>
|
||||
<string name="cancel">Cancellare</string>
|
||||
<string name="later">Dopo</string>
|
||||
<string name="lkm_warning_message">La patch LKM si basa su componenti closed source. Vuoi continuare?</string>
|
||||
<string name="home_next_kernelsu">🔥 Next build</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Branch sperimentale di Next. Dai un\'occhiata su GitHub!</string>
|
||||
@@ -133,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">Dominio</string>
|
||||
<string name="profile_selinux_rules">Regole</string>
|
||||
<string name="module_update">Aggiorna</string>
|
||||
<string name="module_updated">Aggiornato</string>
|
||||
<string name="module_downloading">Sto scaricando il modulo: %s</string>
|
||||
<string name="module_start_downloading">Inizia a scaricare: %s</string>
|
||||
<string name="new_version_available">Nuova versione: %s disponibile, tocca per aggiornare.</string>
|
||||
@@ -140,6 +148,10 @@
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="force_stop_app">Arresto forzato</string>
|
||||
<string name="restart_app">Riavvia</string>
|
||||
<string name="settings_amoled_mode">Modalità AMOLED</string>
|
||||
<string name="settings_amoled_mode_summary">Abilita un tema nero puro, utile per gli schermi AMOLED, per ridurre l\'affaticamento degli occhi e risparmiare batteria.</string>
|
||||
<string name="restart_required">Riavvio richiesto</string>
|
||||
<string name="restart_app_message">Affinché la modifica abbia effetto, è necessario riavviare l\'app.</string>
|
||||
<string name="failed_to_update_sepolicy">Aggiornamento regole SELinux per %s fallito</string>
|
||||
<string name="su_not_allowed">Non è consentito concedere i privilegi di superutente per: %s</string>
|
||||
<string name="module_changelog">Registro aggiornamenti</string>
|
||||
@@ -169,6 +181,7 @@
|
||||
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti all\'apertura dell\'applicazione.</string>
|
||||
<string name="grant_root_failed">Impossibile ottenere l\'accesso root!</string>
|
||||
<string name="action">Azione</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Apri</string>
|
||||
<string name="enable_web_debugging">Abilita il debug di WebView</string>
|
||||
<string name="enable_web_debugging_summary">Può essere usato per il debug di WebUI, è consigliato attivarlo solo quando necessario.</string>
|
||||
@@ -198,8 +211,14 @@
|
||||
<string name="settings_disable_su">Disabilita la compatibilità su</string>
|
||||
<string name="settings_disable_su_summary">Disattiva temporaneamente la possibilità per qualsiasi app di ottenere privilegi di root tramite il comando su (i processi di root esistenti non saranno interessati).</string>
|
||||
<string name="settings_language">Lingua</string>
|
||||
<string name="settings_legacyui">Usa Legacy UI</string>
|
||||
<string name="settings_legacyui_summary">Passa allo stile precedente dell\'interfaccia utente.</string>
|
||||
<string name="settings_banner">Abilita banner</string>
|
||||
<string name="settings_banner_summary">Mostra banner di sfondo per i moduli.</string>
|
||||
<string name="use_webuix">Usa WebUI X</string>
|
||||
<string name="use_webuix_summary">Usa WebUI X invece di WebUI che supporta più API</string>
|
||||
<string name="use_webuix_eruda">Iniettare Eruda in WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Inietta una console di debug in WebUI X per semplificare il debug. Richiede che il debug web sia attivo.</string>
|
||||
<string name="use_webuix_summary">Usa WebUI X invece di WebUI che supporta più API.</string>
|
||||
<string name="use_webuix_eruda">Iniettare Eruda in WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Inietta una console di debug in WebUI X per semplificare il debug. Richiede che il debug web sia attivo.</string>
|
||||
<string name="customization">Personalizzazione</string>
|
||||
<string name="developer">Sviluppatore</string>
|
||||
</resources>
|
||||
|
||||
@@ -12,13 +12,19 @@
|
||||
<string name="home">Strona główna</string>
|
||||
<string name="home_not_installed">Niezainstalowany</string>
|
||||
<string name="home_click_to_install">Kliknij, aby zainstalować</string>
|
||||
<string name="lkm_mode_deprecated">Tryb LKM jest już przestarzały!</string>
|
||||
<string name="lkm_alternative_suggestion">Zainstaluj jądro GKI lub zintegruj KernelSU Next ze swoim urządzeniem.</string>
|
||||
<string name="home_working">Uruchomiony</string>
|
||||
<string name="home_working_version">Wersja: %d</string>
|
||||
<string name="home_superuser_count">Superuserów: %d</string>
|
||||
<string name="home_module_count">Modułów: %d</string>
|
||||
<string name="home_module_update_count">Aktualizacji: %d</string>
|
||||
<string name="home_failure">Nie znaleziono sygnatury KernelSU Next v2 w jądrze! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Poproś swojego programistę jądra o integrację KernelSU Next!</string>
|
||||
<string name="home_kernel">Wersja jądra</string>
|
||||
<string name="hook_mode">Tryb hookowania</string>
|
||||
<string name="enable">Aktywuj</string>
|
||||
<string name="disable">Dezaktywuj</string>
|
||||
<string name="enabled">Aktywny</string>
|
||||
<string name="disabled">Nieaktywny</string>
|
||||
<string name="susfs_supported">Obsługiwany</string>
|
||||
@@ -27,6 +33,7 @@
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Wersja Androida</string>
|
||||
<string name="home_manager_version">Wersja managera</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">Status SELinux</string>
|
||||
<string name="selinux_status_disabled">Wyłączony</string>
|
||||
<string name="selinux_status_enforcing">Enforcing</string>
|
||||
@@ -38,13 +45,16 @@
|
||||
<string name="module_empty">Brak zainstalowanych modułów</string>
|
||||
<string name="module">Moduły</string>
|
||||
<string name="module_install_prompt_with_name">Następujące moduły zostaną zainstalowane: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Sortuj (A-Z)</string>
|
||||
<string name="module_sort_z_to_a">Sortuj (Z-A)</string>
|
||||
<string name="module_sort_a_to_z">Sortuj (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Sortuj (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Sortuj (Najmniejszy → Największy)</string>
|
||||
<string name="module_size_high_to_low">Sortuj (Największy → Najmniejszy)</string>
|
||||
<string name="uninstall">Odinstaluj</string>
|
||||
<string name="restore">Przywróć</string>
|
||||
<string name="module_install">Zainstaluj</string>
|
||||
<string name="install">Zainstaluj</string>
|
||||
<string name="reboot">Reboot (uruchom ponownie)</string>
|
||||
<string name="uninstalled">Odinstalowany</string>
|
||||
<string name="settings">Ustawienia</string>
|
||||
<string name="reboot_userspace">Miękki reboot</string>
|
||||
<string name="reboot_recovery">Reboot do trybu Recovery</string>
|
||||
@@ -96,6 +106,7 @@
|
||||
<string name="proceed">Dalej</string>
|
||||
<string name="cancel">Anuluj</string>
|
||||
<string name="later">Później</string>
|
||||
<string name="lkm_warning_message">Łatka LKM opiera się na komponentach o zamkniętym kodzie źródłowym. Czy chcesz kontynuować?</string>
|
||||
<string name="home_next_kernelsu">🔥 Kompilacja Next</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Eksperymentalna gałąź Next. Sprawdź na GitHub!</string>
|
||||
@@ -129,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">Domena</string>
|
||||
<string name="profile_selinux_rules">Reguły</string>
|
||||
<string name="module_update">Zaktualizuj</string>
|
||||
<string name="module_updated">Zaktualizowany</string>
|
||||
<string name="module_downloading">Pobieranie modułu: %s</string>
|
||||
<string name="module_start_downloading">Rozpocznij pobieranie: %s</string>
|
||||
<string name="new_version_available">Nowa wersja %s jest dostępna, kliknij, aby zaktualizować.</string>
|
||||
@@ -136,6 +148,10 @@
|
||||
<string name="close">Zamknij</string>
|
||||
<string name="force_stop_app">Wymuś zatrzymanie</string>
|
||||
<string name="restart_app">Uruchom ponownie</string>
|
||||
<string name="settings_amoled_mode">Tryb AMOLED</string>
|
||||
<string name="settings_amoled_mode_summary">Włącz czysto czarny motyw, przydatny dla ekranów AMOLED, aby zmniejszyć zmęczenie oczu oraz zużycie baterii.</string>
|
||||
<string name="restart_required">Wymagany restart</string>
|
||||
<string name="restart_app_message">Aplikacja wymaga ponownego uruchomienia, aby zmiana została uwzględniona.</string>
|
||||
<string name="failed_to_update_sepolicy">Nie udało się zaktualizować reguł SELinux dla: %s</string>
|
||||
<string name="su_not_allowed">Przyznanie uprawnień superusera nie jest dozwolone dla: %s</string>
|
||||
<string name="module_changelog">Dziennik zmian</string>
|
||||
@@ -165,6 +181,7 @@
|
||||
<string name="settings_check_update_summary">Automatycznie sprawdzaj dostępność aktualizacji przy otwieraniu aplikacji.</string>
|
||||
<string name="grant_root_failed">Nie udało się przyznać uprawnień roota!</string>
|
||||
<string name="action">Akcja</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Otwórz</string>
|
||||
<string name="enable_web_debugging">Włącz debugowanie WebView</string>
|
||||
<string name="enable_web_debugging_summary">Możesz użyć tej opcji w celu debugowania WebUI. Włącz tylko wtedy, gdy jest to potrzebne.</string>
|
||||
@@ -194,4 +211,15 @@
|
||||
<string name="settings_disable_su">Wyłącz funkcjonalność su</string>
|
||||
<string name="settings_disable_su_summary">Tymczasowo wyłącz możliwość uzyskania uprawnień roota przez dowolną aplikację za pomocą polecenia su (nie będzie to miało wpływu na istniejące procesy roota).</string>
|
||||
<string name="settings_language">Język</string>
|
||||
<string name="settings_legacyui">Używaj starszego interfejsu użytkownika</string>
|
||||
<string name="settings_legacyui_summary">Przełącz na poprzedni styl interfejsu użytkownika.</string>
|
||||
<string name="settings_banner">Włącz banery</string>
|
||||
<string name="settings_banner_summary">Pokazuj tła-banery dla modułów.</string>
|
||||
<string name="use_webuix">Używaj WebUI X</string>
|
||||
<string name="use_webuix_summary">Używaj WebUI X zamiast WebUI, który obsługuje więcej interfejsów API.</string>
|
||||
<string name="use_webuix_eruda">Wstrzykuj Eruda do WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Wstrzyknij konsolę debugowania do WebUI X, aby ułatwić debugowanie. Wymagane jest aktywne debugowanie WebView.</string>
|
||||
<string name="customization">Personalizacja</string>
|
||||
<string name="developer">Programista</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT NIEAKTYWNY</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
<string name="home_working_version">Versão: %d</string>
|
||||
<string name="home_superuser_count">SuperUsuários: %d</string>
|
||||
<string name="home_module_count">Módulos: %d</string>
|
||||
<string name="home_module_update_count">Atualizações: %d</string>
|
||||
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
|
||||
<string name="home_kernel">Versão do kernel</string>
|
||||
<string name="hook_mode">Modo do hook</string>
|
||||
<string name="enable">Ativar</string>
|
||||
<string name="disable">Desativar</string>
|
||||
<string name="enabled">Ativado</string>
|
||||
<string name="disabled">Desativado</string>
|
||||
<string name="susfs_supported">Suportado</string>
|
||||
@@ -42,13 +45,16 @@
|
||||
<string name="module_empty">Nenhum módulo instalado</string>
|
||||
<string name="module">Módulo</string>
|
||||
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalados: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Ordenar (A-Z)</string>
|
||||
<string name="module_sort_z_to_a">Ordenar (Z-A)</string>
|
||||
<string name="module_sort_a_to_z">Ordenar (A → Z)</string>
|
||||
<string name="module_sort_z_to_a">Ordenar (Z → A)</string>
|
||||
<string name="module_size_low_to_high">Ordenar (Menor → Maior)</string>
|
||||
<string name="module_size_high_to_low">Ordenar (Maior → Menor)</string>
|
||||
<string name="uninstall">Desinstalar</string>
|
||||
<string name="restore">Restaurar</string>
|
||||
<string name="module_install">Instalar</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="uninstalled">Desinstalado</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="reboot_userspace">Reinicialização suave</string>
|
||||
<string name="reboot_recovery">Reiniciar em modo Recovery</string>
|
||||
@@ -134,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">Domínio</string>
|
||||
<string name="profile_selinux_rules">Regras</string>
|
||||
<string name="module_update">Atualizar</string>
|
||||
<string name="module_updated">Atualizado</string>
|
||||
<string name="module_downloading">Baixando módulo %s</string>
|
||||
<string name="module_start_downloading">Começando a baixar %s</string>
|
||||
<string name="new_version_available">Nova versão %s está disponível, clique para atualizar.</string>
|
||||
@@ -141,6 +148,10 @@
|
||||
<string name="close">Fechar</string>
|
||||
<string name="force_stop_app">Forçar parada</string>
|
||||
<string name="restart_app">Reiniciar</string>
|
||||
<string name="settings_amoled_mode">Modo AMOLED</string>
|
||||
<string name="settings_amoled_mode_summary">Ative um tema preto puro útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
|
||||
<string name="restart_required">Reinicialização necessária</string>
|
||||
<string name="restart_app_message">O app precisa ser reiniciado para que essa alteração tenha efeito.</string>
|
||||
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para: %s</string>
|
||||
<string name="su_not_allowed">O acesso de SuperUsuário não é permitido para: %s</string>
|
||||
<string name="module_changelog">Registro de alterações</string>
|
||||
@@ -170,6 +181,7 @@
|
||||
<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="action">Ação</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="enable_web_debugging">Ativar depuração do WebView</string>
|
||||
<string name="enable_web_debugging_summary">Pode ser usado para depurar o WebUI. Por favor, ative somente quando necessário.</string>
|
||||
@@ -199,8 +211,13 @@
|
||||
<string name="settings_disable_su">Desativar compatibilidade su</string>
|
||||
<string name="settings_disable_su_summary">Desative temporariamente a capacidade de qualquer app obter privilégios root por meio do comando su (processos root existentes não serão afetados).</string>
|
||||
<string name="settings_language">Idioma</string>
|
||||
<string name="settings_legacyui">Usar IU antiga</string>
|
||||
<string name="settings_legacyui_summary">Mude para o estilo de interface do usuário anterior.</string>
|
||||
<string name="settings_banner">Ativar banners</string>
|
||||
<string name="settings_banner_summary">Mostre banners de fundo para módulos.</string>
|
||||
<string name="use_webuix">Usar WebUI X</string>
|
||||
<string name="use_webuix_summary">Use o WebUI X em vez do WebUI, que oferece suporte a mais APIs.</string>
|
||||
<string name="use_webuix_eruda">Injetar Eruda no WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Injeta um console de depuração no WebUI X para facilitar a depuração. Requer que a depuração web esteja ativada.</string>
|
||||
<string name="customization">Personalização</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,13 +18,16 @@
|
||||
<string name="home_working_version">Версия: %d</string>
|
||||
<string name="home_superuser_count">Superusers: %d</string>
|
||||
<string name="home_module_count">Модули: %d</string>
|
||||
<string name="home_module_update_count">Обновления: %d</string>
|
||||
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [!KSU_NEXT || != size/hash]</string>
|
||||
<string name="home_failure_tip">Попросите вашего разработчика ядра интегрировать KernelSU Next!</string>
|
||||
<string name="home_kernel">Версия ядра</string>
|
||||
<string name="hook_mode">Режим хуков</string>
|
||||
<string name="enable">Включить</string>
|
||||
<string name="disable">Отключить</string>
|
||||
<string name="disabled">Отключено</string>
|
||||
<string name="enabled">Включено</string>
|
||||
<string name="susfs_supported">Поддерживается</string>
|
||||
<string name="susfs_supported">Доступно</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">Версия SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
@@ -42,13 +45,16 @@
|
||||
<string name="module_empty">Нет установленных модулей</string>
|
||||
<string name="module">Модули</string>
|
||||
<string name="module_install_prompt_with_name">Следующие модуль(и) будут установлены: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Сортировать (А-Я)</string>
|
||||
<string name="module_sort_z_to_a">Сортировать (Я-А)</string>
|
||||
<string name="module_sort_a_to_z">Сортировать (А → Я)</string>
|
||||
<string name="module_sort_z_to_a">Сортировать (Я → А)</string>
|
||||
<string name="module_size_low_to_high">Сортировать (Низкий → Высокий)</string>
|
||||
<string name="module_size_high_to_low">Сортировать (Высокий → Низкий)</string>
|
||||
<string name="uninstall">Удалить</string>
|
||||
<string name="restore">Восстановить</string>
|
||||
<string name="module_install">Установить</string>
|
||||
<string name="install">Установить</string>
|
||||
<string name="reboot">Перезагрузка</string>
|
||||
<string name="uninstalled">Удалено</string>
|
||||
<string name="settings">Настройки</string>
|
||||
<string name="reboot_userspace">Мягкая перезагрузка</string>
|
||||
<string name="reboot_recovery">Перезагрузка в Recovery</string>
|
||||
@@ -100,6 +106,7 @@
|
||||
<string name="proceed">Продолжить</string>
|
||||
<string name="cancel">Отмена</string>
|
||||
<string name="later">Позже</string>
|
||||
<string name="lkm_warning_message">Патч LKM использует компоненты с закрытым исходным кодом. Хотите продолжить?</string>
|
||||
<string name="home_next_kernelsu">🔥 Следующий билд</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Следующая экспериментальная ветка. Посмотрите на GitHub!</string>
|
||||
@@ -109,7 +116,7 @@
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • Используйте на свой страх и риск: могут возникнуть сбои, непредвиденное поведение или проблемы с системой.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • Предупреждение: разработчики не несут ответственности за потерю данных, повреждение системы или другие последствия, вызванные использованием.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> • Только для тестирования: предназначено для пользователей, которые понимают риски и готовы решать возникающие проблемы.</string>
|
||||
<string name="about_source_code"><![CDATA[Посмотреть исходный код на %1$s]]></string>
|
||||
<string name="about_source_code"><![CDATA[Исходный код на %1$s]]></string>
|
||||
<string name="profile" translatable="false">Профиль Приложения</string>
|
||||
<string name="profile_default">По умолчанию</string>
|
||||
<string name="profile_template">Шаблон</string>
|
||||
@@ -133,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">Домен</string>
|
||||
<string name="profile_selinux_rules">Правила</string>
|
||||
<string name="module_update">Обновить</string>
|
||||
<string name="module_updated">Обновлено</string>
|
||||
<string name="module_downloading">Загрузка модуля: %s</string>
|
||||
<string name="module_start_downloading">Начало загрузки: %s</string>
|
||||
<string name="new_version_available">Доступна новая версия %s, нажмите для обновления.</string>
|
||||
@@ -140,6 +148,10 @@
|
||||
<string name="close">Закрыть</string>
|
||||
<string name="force_stop_app">Принудительно остановить</string>
|
||||
<string name="restart_app">Перезапустить</string>
|
||||
<string name="settings_amoled_mode">Режим AMOLED</string>
|
||||
<string name="settings_amoled_mode_summary">Включить полностью тёмную тему, оптимизированную для дисплеев AMOLED, чтобы снизить зрительную нагрузку и сэкономить заряд аккумулятора.</string>
|
||||
<string name="restart_required">Требуется перезапуск</string>
|
||||
<string name="restart_app_message">Чтобы изменения вступили в силу, необходимо перезапустить приложение.</string>
|
||||
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для: %s</string>
|
||||
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
|
||||
<string name="module_changelog">Журнал изменений</string>
|
||||
@@ -169,6 +181,7 @@
|
||||
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
|
||||
<string name="grant_root_failed">Не удалось предоставить root-доступ!</string>
|
||||
<string name="action">Запустить</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Открыть</string>
|
||||
<string name="enable_web_debugging">Отладка WebView</string>
|
||||
<string name="enable_web_debugging_summary">Можно использовать для отладки WebUI. Включайте только при необходимости.</string>
|
||||
@@ -198,8 +211,11 @@
|
||||
<string name="settings_disable_su">Откл. совместимость с su</string>
|
||||
<string name="settings_disable_su_summary">Временно отключить возможность приложениям получать права root через команду su (существующие процессы с правами root не будут затронуты).</string>
|
||||
<string name="settings_language">Язык</string>
|
||||
<string name="settings_legacyui">Использовать старый UI</string>
|
||||
<string name="settings_legacyui_summary">Переключиться на предыдущий стиль интерфейса.</string>
|
||||
<string name="use_webuix">Использовать WebUI X</string>
|
||||
<string name="use_webuix_summary">Использовать WebUI X вместо WebUI, который поддерживает больше API.</string>
|
||||
<string name="use_webuix_eruda">Инжект Eruda в WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Инжектить консоль отладки в WebUI X, чтобы упростить отладку. Требуется включить отладку WebView.</string>
|
||||
<string name="customization">Кастомизация</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
<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_module_count">Modüller: %d</string>
|
||||
<string name="home_module_update_count">Güncellemeler: %d</string>
|
||||
<string name="home_failure">Kernel\'de KernelSU Next v2 imzası bulunamadı! [ !KSU_NEXT || != boyut/hash ]</string>
|
||||
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmesini isteyin!</string>
|
||||
<string name="home_kernel">Kernel sürümü</string>
|
||||
<string name="hook_mode">Kanca Modu</string>
|
||||
<string name="enable">Etkinleştir</string>
|
||||
<string name="disable">Devre Dışı Bırak</string>
|
||||
<string name="enabled">Etkin</string>
|
||||
<string name="disabled">Devre dışı</string>
|
||||
<string name="susfs_supported">Destekleniyor</string>
|
||||
@@ -49,6 +52,7 @@
|
||||
<string name="module_install">Yükle</string>
|
||||
<string name="install">Yükle</string>
|
||||
<string name="reboot">Yeniden Başlat</string>
|
||||
<string name="uninstalled">Kaldırıldı</string>
|
||||
<string name="settings">Ayarlar</string>
|
||||
<string name="reboot_userspace">Yumuşak Yeniden Başlat</string>
|
||||
<string name="reboot_recovery">Kurtarma Moduna Yeniden Başlat</string>
|
||||
@@ -100,6 +104,7 @@
|
||||
<string name="proceed">Devam Et</string>
|
||||
<string name="cancel">İptal</string>
|
||||
<string name="later">Daha Sonra</string>
|
||||
<string name="lkm_warning_message">LKM yaması, kapalı kaynak bileşenlere dayanır. Devam etmek istiyor musunuz?</string>
|
||||
<string name="home_next_kernelsu">🔥 Yeni Sürüm</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Son deneysel dal. GitHub\'da kontrol edin!</string>
|
||||
@@ -133,6 +138,7 @@
|
||||
<string name="profile_selinux_domain">Etki Alanı</string>
|
||||
<string name="profile_selinux_rules">Kurallar</string>
|
||||
<string name="module_update">Güncelle</string>
|
||||
<string name="module_updated">Güncellendi</string>
|
||||
<string name="module_downloading">Modül indiriliyor: %s</string>
|
||||
<string name="module_start_downloading">İndirmeye başla: %s</string>
|
||||
<string name="new_version_available">%s sürümü mevcut, yükseltmek için tıklayın.</string>
|
||||
@@ -140,6 +146,10 @@
|
||||
<string name="close">Kapat</string>
|
||||
<string name="force_stop_app">Zorla durdur</string>
|
||||
<string name="restart_app">Yeniden Başlat</string>
|
||||
<string name="settings_amoled_mode">AMOLED modu</string>
|
||||
<string name="settings_amoled_mode_summary">Göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için AMOLED ekranlara uygun saf siyah tema etkinleştirilir.</string>
|
||||
<string name="restart_required">Yeniden Başlatma Gerekli</string>
|
||||
<string name="restart_app_message">Bu değişikliğin etkili olması için uygulamanın yeniden başlatılması gerekiyor.</string>
|
||||
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi.</string>
|
||||
<string name="su_not_allowed">SüperKullanıcı yetkisi verilemez: %s</string>
|
||||
<string name="module_changelog">Değişiklik Günlüğü</string>
|
||||
@@ -169,6 +179,7 @@
|
||||
<string name="settings_check_update_summary">Uygulama açıldığında otomatik olarak güncellemeleri kontrol et.</string>
|
||||
<string name="grant_root_failed">Root yetkisi verilemedi!</string>
|
||||
<string name="action">Eylem</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Aç</string>
|
||||
<string name="enable_web_debugging">WebView hata ayıklamasını etkinleştir</string>
|
||||
<string name="enable_web_debugging_summary">WebUI hata ayıklaması için kullanılabilir. Lütfen yalnızca gerekli olduğunda etkinleştirin.</string>
|
||||
@@ -198,8 +209,11 @@
|
||||
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
|
||||
<string name="settings_disable_su_summary">Geçici olarak herhangi bir uygulamanın su komutu aracılığıyla kök ayrıcalıkları elde etme yeteneğini devre dışı bırakır (mevcut kök süreçleri etkilenmez).</string>
|
||||
<string name="settings_language">Dil</string>
|
||||
<string name="settings_legacyui">Eski Arayüzü Kullan</string>
|
||||
<string name="settings_legacyui_summary">Önceki kullanıcı arayüzü stiline geç.</string>
|
||||
<string name="use_webuix">WebUI X\'i kullanın</string>
|
||||
<string name="use_webuix_summary">Daha fazla API\'yi destekleyen WebUI yerine WebUI X kullanın</string>
|
||||
<string name="use_webuix_eruda">WebUI X\'e Eruda Enjekte Et</string>
|
||||
<string name="use_webuix_eruda_summary">Hata ayıklamayı kolaylaştırmak için WebUI X\'e bir debug konsolu enjekte edin. Web hata ayıklamanın açık olması gerekir.</string>
|
||||
<string name="customization">Özelleştirme</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
<string name="home_working_version">Версія: %d</string>
|
||||
<string name="home_superuser_count">SuperUsers: %d</string>
|
||||
<string name="home_module_count">Модулі: %d</string>
|
||||
<string name="home_module_update_count">Оновлення: %d</string>
|
||||
<string name="home_failure">Підпис KernelSU Next v2 не знайдено в ядрі! [!KSU_NEXT || != size/hash]</string>
|
||||
<string name="home_failure_tip">Попросіть вашого розробника ядра інтегрувати KernelSU Next!</string>
|
||||
<string name="home_kernel">Версія ядра</string>
|
||||
<string name="hook_mode">Режим хуків</string>
|
||||
<string name="disabled">Вимкнено</string>
|
||||
<string name="enabled">Увімкнено</string>
|
||||
<string name="susfs_supported">Підтримується</string>
|
||||
<string name="susfs_supported">Доступно</string>
|
||||
<string name="home_susfs">SuSFS: %s</string>
|
||||
<string name="home_susfs_version">Версія SuSFS</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
@@ -44,11 +45,14 @@
|
||||
<string name="module_install_prompt_with_name">Наступні модуль(і) будуть встановлені: %1$s</string>
|
||||
<string name="module_sort_a_to_z">Сортувати (А-Я)</string>
|
||||
<string name="module_sort_z_to_a">Сортувати (Я-А)</string>
|
||||
<string name="module_size_low_to_high">Сортувати (Низький → Великий)</string>
|
||||
<string name="module_size_high_to_low">Сортувати (Великий → Низький)</string>
|
||||
<string name="uninstall">Видалити</string>
|
||||
<string name="restore">Відновити</string>
|
||||
<string name="module_install">Встановити</string>
|
||||
<string name="install">Встановити</string>
|
||||
<string name="reboot">Перезавантаження</string>
|
||||
<string name="uninstalled">Видалено</string>
|
||||
<string name="settings">Налаштування</string>
|
||||
<string name="reboot_userspace">М’яка перезавантаження</string>
|
||||
<string name="reboot_recovery">Перезавантаження в Recovery</string>
|
||||
@@ -87,19 +91,20 @@
|
||||
<string name="reboot_required">Потрібно перезавантаження</string>
|
||||
<string name="reboot_message">Зміни вступлять в силу після перезавантаження системи. Перезавантажити зараз?</string>
|
||||
<string name="module_restore">Відновити модуль</string>
|
||||
<string name="module_restore_message">Відновлення модулів із останньої резервної копії.</string>
|
||||
<string name="backup_restore">Резервне копіювання і відновлення</string>
|
||||
<string name="module_restore_message">Відновлення модулів із останнього бекапу.</string>
|
||||
<string name="backup_restore">Бекап і відновлення</string>
|
||||
<string name="module_backup">Бекап модуля</string>
|
||||
<string name="module_backup_message">Бекап поточних встановлених модулів.</string>
|
||||
<string name="allowlist_restore">Відновити список дозволів</string>
|
||||
<string name="allowlist_restore_message">Відновити список дозволів із останнього резервного копіювання.</string>
|
||||
<string name="allowlist_restore_message">Відновити список дозволів із останнього бекапу.</string>
|
||||
<string name="allowlist_backup">Бекап списку дозволів</string>
|
||||
<string name="allowlist_backup_message">Бекап поточного списку дозволів.</string>
|
||||
<string name="warning">Попередження</string>
|
||||
<string name="warning_message">Ця функція все ще перебуває у стадії бета-тестування. Будь ласка, переконайтеся, що ви створили резервні копії модулів перед використанням. Використовуйте це лише якщо розумієте можливі ризики. Будьте обережні.</string>
|
||||
<string name="warning_message">Ця функція все ще перебуває у стадії бета-тестування. Будь ласка, переконайтеся, що ви створили бекап модулів перед використанням. Використовуйте це лише якщо розумієте можливі ризики. Будьте обережні.</string>
|
||||
<string name="proceed">Продовжити</string>
|
||||
<string name="cancel">Скасувати</string>
|
||||
<string name="later">Пізніше</string>
|
||||
<string name="lkm_warning_message">Патч LKM базується на компонентах із закритим кодом. Продовжити?</string>
|
||||
<string name="home_next_kernelsu">🔥 Наступна збірка</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Наступна експериментальна гілка. Подивіться на GitHub!</string>
|
||||
@@ -109,7 +114,7 @@
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • Використовуйте на свій страх і ризик: можуть виникати збої, несподівана поведінка або проблеми з системою.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • Попередження: розробники не несуть відповідальності за втрату даних, пошкодження системи або інші наслідки, викликані використанням.</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> • Лише для тестування: призначено для користувачів, які розуміють ризики і готові вирішувати виникаючі проблеми.</string>
|
||||
<string name="about_source_code"><![CDATA[Переглянути вихідний код на %1$s]]></string>
|
||||
<string name="about_source_code"><![CDATA[Вихідний код на %1$s]]></string>
|
||||
<string name="profile" translatable="false">Профіль додатка</string>
|
||||
<string name="profile_default">За замовчуванням</string>
|
||||
<string name="profile_template">Шаблон</string>
|
||||
@@ -133,6 +138,7 @@
|
||||
<string name="profile_selinux_domain">Домен</string>
|
||||
<string name="profile_selinux_rules">Правила</string>
|
||||
<string name="module_update">Оновити</string>
|
||||
<string name="module_updated">Оновлено</string>
|
||||
<string name="module_downloading">Завантаження модуля: %s</string>
|
||||
<string name="module_start_downloading">Початок завантаження: %s</string>
|
||||
<string name="new_version_available">Доступна нова версія %s, натисніть для оновлення.</string>
|
||||
@@ -140,6 +146,10 @@
|
||||
<string name="close">Закрити</string>
|
||||
<string name="force_stop_app">Примусово зупинити</string>
|
||||
<string name="restart_app">Перезапустити</string>
|
||||
<string name="settings_amoled_mode">AMOLED-режим</string>
|
||||
<string name="settings_amoled_mode_summary">Увімкніть чисто чорну тему, корисну для екранів AMOLED, щоб зменшити навантаження на очі та заощадити заряд батареї.</string>
|
||||
<string name="restart_required">Потрібно перезавантажити</string>
|
||||
<string name="restart_app_message">Щоб ця зміна набула чинності, потрібно перезапустити програму.</string>
|
||||
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string>
|
||||
<string name="su_not_allowed">Надання прав суперкористувача заборонено для: %s</string>
|
||||
<string name="module_changelog">Журнал змін</string>
|
||||
@@ -169,6 +179,7 @@
|
||||
<string name="settings_check_update_summary">Автоматично перевіряти оновлення при відкритті додатка.</string>
|
||||
<string name="grant_root_failed">Не вдалося надати root-доступ!</string>
|
||||
<string name="action">Запустити</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">Відкрити</string>
|
||||
<string name="enable_web_debugging">Відладка WebView</string>
|
||||
<string name="enable_web_debugging_summary">Можна використовувати для відладки WebUI. Увімкніть лише при необхідності.</string>
|
||||
@@ -179,15 +190,15 @@
|
||||
<string name="install_next">Далі</string>
|
||||
<string name="select_file_tip">Рекомендовано образ розділу %1$s</string>
|
||||
<string name="select_kmi">Виберіть KMI</string>
|
||||
<string name="shrink_sparse_image">Зменшити modules.img образ</string>
|
||||
<string name="shrink_sparse_image_message">Змініть розмір modules.img образу, у якому знаходяться модулі, до його фактичного розміру. Зверніть увагу, що це може викликати ненормальну роботу модулів, тому використовуйте лише при необхідності (наприклад, для резервного копіювання).</string>
|
||||
<string name="shrink_sparse_image">Мінімізувати розріджене зображення</string>
|
||||
<string name="shrink_sparse_image_message">Змініть розмір розрідженого зображення, де розташований модуль, до його фактичного розміру. Зверніть увагу, що це може призвести до неправильної роботи модуля, тому використовуйте його лише за необхідності (наприклад, для бекапу).</string>
|
||||
<string name="settings_uninstall">Видалення</string>
|
||||
<string name="settings_uninstall_temporary">Тимчасове видалення</string>
|
||||
<string name="settings_uninstall_permanent">Повне видалення</string>
|
||||
<string name="settings_restore_stock_image">Відновити стандартний образ</string>
|
||||
<string name="settings_uninstall_temporary_message">Тимчасово видаліть KernelSU Next, відновивши початковий стан після наступного перезавантаження.</string>
|
||||
<string name="settings_uninstall_permanent_message">Повне і остаточне видалення KernelSU Next (Root та всіх модулів).</string>
|
||||
<string name="settings_restore_stock_image_message">Відновлення стандартного заводського образу (якщо є резервна копія), зазвичай використовується перед OTA; якщо потрібно видалити KernelSU Next, використовуйте "Повне видалення".</string>
|
||||
<string name="settings_restore_stock_image_message">Відновлення стандартного заводського образу (якщо є бекап), зазвичай використовується перед OTA; якщо потрібно видалити KernelSU Next, використовуйте "Повне видалення".</string>
|
||||
<string name="flashing">Прошивка</string>
|
||||
<string name="flash_success">Прошивка виконана успішно</string>
|
||||
<string name="flash_failed">Помилка прошивки</string>
|
||||
@@ -198,8 +209,14 @@
|
||||
<string name="settings_disable_su">Вимкн. сумісність із su</string>
|
||||
<string name="settings_disable_su_summary">Тимчасово вимкнути можливість додаткам отримувати права root через команду su (існуючі процеси з правами root не будуть зачеплені).</string>
|
||||
<string name="settings_language">Мова</string>
|
||||
<string name="settings_legacyui">Використовувати застарілий UI</string>
|
||||
<string name="settings_legacyui_summary">Перейти до попереднього стилю інтерфейсу користувача.</string>
|
||||
<string name="settings_banner">Увімкнути банери</string>
|
||||
<string name="settings_banner_summary">Показувати фонові банери для модулів.</string>
|
||||
<string name="use_webuix">Використовувати WebUI X</string>
|
||||
<string name="use_webuix_summary">Використовувати WebUI X замість WebUI, який підтримує більше API.</string>
|
||||
<string name="use_webuix_eruda">Інжект Eruda у WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Інжектити консоль відладки у WebUI X, щоб спростити відладку. Потрібно увімкнути відладку WebView.</string>
|
||||
<string name="customization">Кастомізація</string>
|
||||
<string name="developer">Розробник</string>
|
||||
</resources>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<string name="issue_report_body">发现错误或者有改进建议?</string>
|
||||
<string name="issue_report_body_2">快向我们报告吧!</string>
|
||||
<string name="issue_report_github">在 GitHub 报告</string>
|
||||
<string name="issue_report_telegram">在 Telegram 联系</string>
|
||||
<string name="issue_report_telegram">在 Telegram 获得最新消息</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">确认</string>
|
||||
@@ -12,42 +12,55 @@
|
||||
<string name="home">主页</string>
|
||||
<string name="home_not_installed">未安装</string>
|
||||
<string name="home_click_to_install">点击安装</string>
|
||||
<string name="lkm_mode_deprecated">LKM 模式现已弃用!</string>
|
||||
<string name="lkm_alternative_suggestion">请使用 GKI 内核或手动将 KernelSU Next 集成到你的设备。</string>
|
||||
<string name="home_working">工作中</string>
|
||||
<string name="home_working_version">版本:%d</string>
|
||||
<string name="home_superuser_count">超级用户数:%d</string>
|
||||
<string name="home_module_count">模块数:%d</string>
|
||||
<string name="home_module_update_count">可更新模块: %d</string>
|
||||
<string name="home_failure">内核中未找到 KernelSU Next V2 签名! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next!</string>
|
||||
<string name="home_kernel">内核版本</string>
|
||||
<string name="hook_mode">Hook 模式</string>
|
||||
<string name="enable">启用</string>
|
||||
<string name="disable">禁用</string>
|
||||
<string name="enabled">已启用</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="susfs_supported">支持</string>
|
||||
<string name="home_susfs">SuSFS:%s</string>
|
||||
<string name="home_susfs_version">SuSFS 版本</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Android 版本</string>
|
||||
<string name="home_manager_version">管理器版本</string>
|
||||
<string name="home_abi">接口</string>
|
||||
<string name="home_selinux_status">SELinux 状态</string>
|
||||
<string name="selinux_status_disabled">被禁用</string>
|
||||
<string name="selinux_status_enforcing">强制执行</string>
|
||||
<string name="selinux_status_disabled">禁用</string>
|
||||
<string name="selinux_status_enforcing">严格模式</string>
|
||||
<string name="selinux_status_permissive">宽容模式</string>
|
||||
<string name="selinux_status_unknown">未知</string>
|
||||
<string name="superuser">超级用户</string>
|
||||
<string name="module_failed_to_enable">无法启用模块:%s</string>
|
||||
<string name="module_failed_to_disable">无法禁用模块:%s</string>
|
||||
<string name="module_empty">没有安装模块</string>
|
||||
<string name="module_failed_to_enable">启用模块失败数:%s</string>
|
||||
<string name="module_failed_to_disable">禁用模块失败数:%s</string>
|
||||
<string name="module_empty">什么都没有呢</string>
|
||||
<string name="module">模块</string>
|
||||
<string name="module_install_prompt_with_name">是否要继续安装模块 %1$s ?</string>
|
||||
<string name="module_sort_a_to_z">按 A-Z 排序</string>
|
||||
<string name="module_sort_z_to_a">按 Z-A 排序</string>
|
||||
<string name="module_sort_a_to_z">按 A - Z 排序</string>
|
||||
<string name="module_sort_z_to_a">按 Z - A 排序</string>
|
||||
<string name="module_size_low_to_high">按模块大小正序排序</string>
|
||||
<string name="module_size_high_to_low">按模块大小倒序排序</string>
|
||||
<string name="uninstall">卸载</string>
|
||||
<string name="restore">恢复</string>
|
||||
<string name="module_install">安装</string>
|
||||
<string name="install">安装</string>
|
||||
<string name="reboot">重启</string>
|
||||
<string name="uninstalled">已卸载</string>
|
||||
<string name="settings">设置</string>
|
||||
<string name="reboot_userspace">软重启</string>
|
||||
<string name="reboot_recovery">重启到 Recovery</string>
|
||||
<string name="reboot_bootloader">重启到 Bootloader</string>
|
||||
<string name="reboot_download">重启到 Download</string>
|
||||
<string name="reboot_edl">重启到 EDL</string>
|
||||
<string name="reboot_edl">重启到 EDL 模式</string>
|
||||
<string name="about">关于</string>
|
||||
<string name="module_uninstall_confirm">确定要卸载模块 %s 吗?</string>
|
||||
<string name="module_uninstall_success">%s 已卸载</string>
|
||||
@@ -62,20 +75,20 @@
|
||||
<string name="module_update_json">更新配置</string>
|
||||
<string name="module_update_json_empty">无更新配置</string>
|
||||
<string name="enable_developer_options">启用开发者模式</string>
|
||||
<string name="enable_developer_options_summary">显示隐藏的开发者专用设置和调试信息</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS 被内核禁用,模块不可用。</string>
|
||||
<string name="enable_developer_options_summary">显示隐藏的开发者专用设置和调试信息。</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS 被内核禁用,模块系统不可用。</string>
|
||||
<string name="refresh">刷新</string>
|
||||
<string name="show_system_apps">显示系统应用</string>
|
||||
<string name="hide_system_apps">隐藏系统应用</string>
|
||||
<string name="export_log">导出日志</string>
|
||||
<string name="safe_mode">安全模式</string>
|
||||
<string name="reboot_to_apply">重启生效</string>
|
||||
<string name="module_magisk_conflict">由于与 Magisk 冲突,模块不可用。</string>
|
||||
<string name="module_magisk_conflict">由于与 Magisk 冲突,模块系统不可用。</string>
|
||||
<string name="home_mount_system">模块系统</string>
|
||||
<string name="home_magic_mount">Magic Mount</string>
|
||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||
<string name="unavailable">不可用</string>
|
||||
<string name="use_overlay_fs">使用 OverlayFS(实验性)</string>
|
||||
<string name="use_overlay_fs">使用 OverlayFS</string>
|
||||
<string name="use_overlay_fs_summary">在 OverlayFS 和 Magic Mount 两种挂载系统之间进行切换。</string>
|
||||
<string name="reboot_required">需要重启</string>
|
||||
<string name="reboot_message">更改将在重启系统后生效。您想现在重启吗?</string>
|
||||
@@ -93,6 +106,7 @@
|
||||
<string name="proceed">继续</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="later">稍后</string>
|
||||
<string name="lkm_warning_message">此 LKM 补丁依赖于闭源组件,你确定要继续吗?</string>
|
||||
<string name="home_next_kernelsu">🔥 Next 构建</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next 实验性分支。在 GitHub 上查看!</string>
|
||||
@@ -102,7 +116,7 @@
|
||||
<string name="home_experimental_kernelsu_body_point_1"> • 风险自担:可能会发生崩溃、意外行为或导致系统故障。</string>
|
||||
<string name="home_experimental_kernelsu_body_point_2"> • 不做保证:开发者不对数据丢失、系统损坏等问题负责。</string>
|
||||
<string name="home_experimental_kernelsu_body_point_3"> • 仅供测试:此版适合了解风险并能轻松解决问题的用户。</string>
|
||||
<string name="about_source_code"><![CDATA[在 %1$s 查看源码]]></string>
|
||||
<string name="about_source_code"><![CDATA[在 %1$s 查看源代码]]></string>
|
||||
<string name="profile" translatable="false">App Profile</string>
|
||||
<string name="profile_default">默认</string>
|
||||
<string name="profile_template">模板</string>
|
||||
@@ -126,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">域</string>
|
||||
<string name="profile_selinux_rules">规则</string>
|
||||
<string name="module_update">更新</string>
|
||||
<string name="module_updated">已更新</string>
|
||||
<string name="module_downloading">正在下载模块: %s</string>
|
||||
<string name="module_start_downloading">开始下载: %s</string>
|
||||
<string name="new_version_available">发现新版本:%s,点击升级。</string>
|
||||
@@ -133,15 +148,19 @@
|
||||
<string name="close">关闭</string>
|
||||
<string name="force_stop_app">强制停止</string>
|
||||
<string name="restart_app">重新启动</string>
|
||||
<string name="settings_amoled_mode">AMOLED 模式</string>
|
||||
<string name="settings_amoled_mode_summary">启用适用于 AMOLED 屏幕的纯黑主题,可减少视觉疲劳并节省电量。</string>
|
||||
<string name="restart_required">需要重启</string>
|
||||
<string name="restart_app_message">请重启 APP 以确保更改生效。</string>
|
||||
<string name="failed_to_update_sepolicy">为 %s 更新 SELinux 规则失败</string>
|
||||
<string name="su_not_allowed">拒绝授予%s超级用户权限</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="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_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>
|
||||
@@ -159,9 +178,10 @@
|
||||
<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="settings_check_update_summary">在应用启动后自动检查是否有更新。</string>
|
||||
<string name="grant_root_failed">获取 root 失败!</string>
|
||||
<string name="action">执行</string>
|
||||
<string name="action">动作</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">打开</string>
|
||||
<string name="enable_web_debugging">启用 WebView 调试</string>
|
||||
<string name="enable_web_debugging_summary">可用于调试 WebUI,请仅在需要时启用。</string>
|
||||
@@ -173,7 +193,7 @@
|
||||
<string name="select_file_tip">建议选择 %1$s 分区镜像</string>
|
||||
<string name="select_kmi">选择 KMI</string>
|
||||
<string name="shrink_sparse_image">最小化稀疏文件</string>
|
||||
<string name="shrink_sparse_image_message">将模块所在的稀疏文件镜像调整为其实际大小,注意这可能导致模块工作异常,请仅在必要时(如备份)使用</string>
|
||||
<string name="shrink_sparse_image_message">将模块所在的稀疏文件镜像调整为其实际大小,注意这可能导致模块工作异常,请仅在必要时(如备份)使用。</string>
|
||||
<string name="settings_uninstall">卸载</string>
|
||||
<string name="settings_uninstall_temporary">临时卸载</string>
|
||||
<string name="settings_uninstall_permanent">完全卸载</string>
|
||||
@@ -189,6 +209,15 @@
|
||||
<string name="log_saved">日志已保存</string>
|
||||
<string name="send_log">分享日志</string>
|
||||
<string name="settings_disable_su">禁用超级用户指令</string>
|
||||
<string name="settings_disable_su_summary">临时禁止任何应用通过 su 命令获取 root 权限(已运行的 root 进程不受影响)</string>
|
||||
<string name="settings_disable_su_summary">临时禁止任何应用通过 su 命令获取 root 权限(正在运行的 root 进程不受影响)。</string>
|
||||
<string name="settings_language">语言</string>
|
||||
<string name="settings_legacyui">切换到传统 UI</string>
|
||||
<string name="settings_legacyui_summary">使用早期的用户界面风格。</string>
|
||||
<string name="settings_banner">启用横幅</string>
|
||||
<string name="settings_banner_summary">针对模块启用背景横幅。</string>
|
||||
<string name="use_webuix">使用 WebUI X</string>
|
||||
<string name="use_webuix_summary">使用更完善的 WebUI X 取代旧有 WebUI,请注意模块开发者可在模块信息中单独覆盖此项设置。</string>
|
||||
<string name="use_webuix_eruda">对 WebUI X 注入 Eruda</string>
|
||||
<string name="use_webuix_eruda_summary">使用 WebUI X 时注入控制台以便于调试,需要启用 WebView 调试功能。</string>
|
||||
<string name="customization">自定义</string>
|
||||
</resources>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<string name="issue_report_title">有任何問題?</string>
|
||||
<string name="issue_report_body">遇到錯誤或者需要反饋?</string>
|
||||
<string name="issue_report_body_2">請儘快告知我們!</string>
|
||||
<string name="issue_report_github">在 GitHub 回報</string>
|
||||
<string name="issue_report_telegram">透過 Telegram 聯繫</string>
|
||||
<string name="issue_report_github">去 GitHub 回報</string>
|
||||
<string name="issue_report_telegram">透過 Telegram 取得最新情報</string>
|
||||
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
|
||||
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
|
||||
<string name="confirm">確認</string>
|
||||
@@ -12,18 +12,28 @@
|
||||
<string name="home">主頁</string>
|
||||
<string name="home_not_installed">未安裝</string>
|
||||
<string name="home_click_to_install">點擊安裝</string>
|
||||
<string name="lkm_mode_deprecated">LKM 模式現已棄用!</string>
|
||||
<string name="lkm_alternative_suggestion">請使用 GKI 內核或手動將 KernelSU Next 整合到你的裝置。</string>
|
||||
<string name="home_working">工作中</string>
|
||||
<string name="home_working_version">版本: %d</string>
|
||||
<string name="home_superuser_count">超級使用者數: %d</string>
|
||||
<string name="home_module_count">模組數: %d</string>
|
||||
<string name="home_module_update_count">可升級模組: %d</string>
|
||||
<string name="home_failure">內核中未找到 KernelSU Next v2 簽名! [ !KSU_NEXT || != size/hash ]</string>
|
||||
<string name="home_failure_tip">請讓你的內核開發人員整合 KernelSU Next!</string>
|
||||
<string name="home_kernel">內核版本</string>
|
||||
<string name="hook_mode">Hook 方法</string>
|
||||
<string name="enable">啓用</string>
|
||||
<string name="disable">禁用</string>
|
||||
<string name="enabled">已經啓用</string>
|
||||
<string name="disabled">已經禁用</string>
|
||||
<string name="susfs_supported">支援</string>
|
||||
<string name="home_susfs">SuSFS:%s</string>
|
||||
<string name="home_susfs_version">SuSFS 版本</string>
|
||||
<string name="home_susfs_sus_su">SuS SU</string>
|
||||
<string name="home_android">Android 版本</string>
|
||||
<string name="home_manager_version">管理器版本</string>
|
||||
<string name="home_manager_version">管理員版本</string>
|
||||
<string name="home_abi">ABI</string>
|
||||
<string name="home_selinux_status">SELinux 狀態</string>
|
||||
<string name="selinux_status_disabled">被禁用</string>
|
||||
<string name="selinux_status_enforcing">強制執行</string>
|
||||
@@ -37,11 +47,14 @@
|
||||
<string name="module_install_prompt_with_name">是否要繼續安裝模組 %1$s ?</string>
|
||||
<string name="module_sort_a_to_z">按 A - Z 排序</string>
|
||||
<string name="module_sort_z_to_a">按 Z - A 排序</string>
|
||||
<string name="module_size_low_to_high">按模組大小正序排序</string>
|
||||
<string name="module_size_high_to_low">按模組大小倒序排序</string>
|
||||
<string name="uninstall">卸載</string>
|
||||
<string name="restore">恢復</string>
|
||||
<string name="module_install">安裝</string>
|
||||
<string name="install">安裝</string>
|
||||
<string name="reboot">重啟</string>
|
||||
<string name="uninstalled">已經卸載</string>
|
||||
<string name="settings">設定</string>
|
||||
<string name="reboot_userspace">軟重啟</string>
|
||||
<string name="reboot_recovery">重啟到 Recovery</string>
|
||||
@@ -63,7 +76,7 @@
|
||||
<string name="module_update_json_empty">無更新配置</string>
|
||||
<string name="enable_developer_options">啟用開發人員模式</string>
|
||||
<string name="enable_developer_options_summary">顯示隱藏的開發人員專用設置和調試信息</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS 被內核禁用,模組不可用。</string>
|
||||
<string name="module_overlay_fs_not_available">OverlayFS 被內核禁用,所有模組不可用。</string>
|
||||
<string name="refresh">刷新</string>
|
||||
<string name="show_system_apps">顯示系統應用</string>
|
||||
<string name="hide_system_apps">隱藏系統應用</string>
|
||||
@@ -75,7 +88,7 @@
|
||||
<string name="home_magic_mount">Magic Mount</string>
|
||||
<string name="home_overlayfs_mount">OverlayFS</string>
|
||||
<string name="unavailable">不可用</string>
|
||||
<string name="use_overlay_fs">使用 OverlayFS (實驗性功能)</string>
|
||||
<string name="use_overlay_fs">使用 OverlayFS</string>
|
||||
<string name="use_overlay_fs_summary">對於 KernelSU Next 的掛載系統,在使用 OverlayFS 和 Magic Mount 之間進行切換。</string>
|
||||
<string name="reboot_required">需要重啟</string>
|
||||
<string name="reboot_message">更改將在重啟系統後生效。您想現在重啟嗎?</string>
|
||||
@@ -93,6 +106,7 @@
|
||||
<string name="proceed">繼續</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="later">稍後</string>
|
||||
<string name="lkm_warning_message">該 LKM 補丁依賴閉源元件,確定繼續嗎?</string>
|
||||
<string name="home_next_kernelsu">🔥 Next 構建</string>
|
||||
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
|
||||
<string name="home_next_kernelsu_body">Next 實驗性分支。在 GitHub 上查看!</string>
|
||||
@@ -126,6 +140,7 @@
|
||||
<string name="profile_selinux_domain">域</string>
|
||||
<string name="profile_selinux_rules">規則</string>
|
||||
<string name="module_update">更新</string>
|
||||
<string name="module_updated">已經更新</string>
|
||||
<string name="module_downloading">正在下載模組: %s</string>
|
||||
<string name="module_start_downloading">開始下載: %s</string>
|
||||
<string name="new_version_available">發現新版本:%s,點擊升級。</string>
|
||||
@@ -133,22 +148,26 @@
|
||||
<string name="close">關閉</string>
|
||||
<string name="force_stop_app">強制停止</string>
|
||||
<string name="restart_app">重新啟動</string>
|
||||
<string name="settings_amoled_mode">AMOLED 模式</string>
|
||||
<string name="settings_amoled_mode_summary">啓用 AMOLED 屏幕專用的純黑主題,減少視覺疲勞的同時節約電池使用。</string>
|
||||
<string name="restart_required">需要重啓</string>
|
||||
<string name="restart_app_message">請重啓程式確保改動生效。</string>
|
||||
<string name="failed_to_update_sepolicy">為:%s 更新 SELinux 規則失敗</string>
|
||||
<string name="su_not_allowed">拒絕授予%s超級使用者權限</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="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_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_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>
|
||||
@@ -161,10 +180,11 @@
|
||||
<string name="settings_check_update">檢查更新</string>
|
||||
<string name="settings_check_update_summary">在應用啟動後自動檢查是否有最新版。</string>
|
||||
<string name="grant_root_failed">獲取 root 失敗!</string>
|
||||
<string name="action">執行</string>
|
||||
<string name="action">Action</string>
|
||||
<string name="webui">WebUI</string>
|
||||
<string name="open">打開</string>
|
||||
<string name="enable_web_debugging">啟用 WebView 偵錯</string>
|
||||
<string name="enable_web_debugging_summary">可用於偵錯 WebUI ,請僅在需要時啟用。</string>
|
||||
<string name="enable_web_debugging_summary">可用於偵錯 WebUI ,僅在需要時啟用。</string>
|
||||
<string name="direct_install">直接安裝(推薦)</string>
|
||||
<string name="select_file">選擇一個檔案</string>
|
||||
<string name="install_inactive_slot">安裝到未使用的槽位(OTA 後)</string>
|
||||
@@ -173,7 +193,7 @@
|
||||
<string name="select_file_tip">建議選擇 %1$s 分區映像檔</string>
|
||||
<string name="select_kmi">選擇 KMI</string>
|
||||
<string name="shrink_sparse_image">最小化稀疏檔案</string>
|
||||
<string name="shrink_sparse_image_message">將模組所在的稀疏檔案映像調整為其實際大小,注意這可能導致模組工作異常,請僅在必要時(如備份)使用</string>
|
||||
<string name="shrink_sparse_image_message">將模組所在的稀疏檔案映像調整為其實際大小,注意這可能導致模組工作異常,請僅在必要時(如備份)使用。</string>
|
||||
<string name="settings_uninstall">卸載</string>
|
||||
<string name="settings_uninstall_temporary">臨時卸載</string>
|
||||
<string name="settings_uninstall_permanent">永久卸載</string>
|
||||
@@ -189,6 +209,15 @@
|
||||
<string name="log_saved">日誌已保存</string>
|
||||
<string name="send_log">發送日誌</string>
|
||||
<string name="settings_disable_su">關閉 SU 相容</string>
|
||||
<string name="settings_disable_su_summary">暫時禁止任何應用通過 su 命令獲取 root 權限(已運行的 root 進程不受影響)</string>
|
||||
<string name="settings_disable_su_summary">暫時禁止任何應用通過 su 命令獲取 root 權限(已運行的 root 進程不受影響)。</string>
|
||||
<string name="settings_language">語言</string>
|
||||
<string name="settings_legacyui">換回傳統 UI</string>
|
||||
<string name="settings_legacyui_summary">使用早期版本 UI 風格。</string>
|
||||
<string name="settings_banner">啓用橫幅</string>
|
||||
<string name="settings_banner_summary">對模組啓用背景橫幅。</string>
|
||||
<string name="use_webuix">使用 WebUI X</string>
|
||||
<string name="use_webuix_summary">使用更爲完善的 WebUI X 而不是 WebUI,請注意模組開發人員能在模組信息中覆寫這個設置。</string>
|
||||
<string name="use_webuix_eruda">將 Eruda 注入 WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">在使用 WebUI X 時注入控制台以便於偵錯,需要啟用 WebView 偵錯功能。</string>
|
||||
<string name="customization">客制化</string>
|
||||
</resources>
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
<string name="restart_app">Restart</string>
|
||||
<string name="settings_amoled_mode">AMOLED mode</string>
|
||||
<string name="settings_amoled_mode_summary">Enable a pure black theme useful for AMOLED screens to reduce eye strain and save battery.</string>
|
||||
<string name="restart_required">Restart Required</string>
|
||||
<string name="restart_required">Restart required</string>
|
||||
<string name="restart_app_message">The app needs to restart for this change to take effect.</string>
|
||||
<string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string>
|
||||
<string name="su_not_allowed">Granting superuser isn\'t allowed for: %s</string>
|
||||
@@ -220,4 +220,6 @@
|
||||
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
|
||||
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
|
||||
<string name="customization">Customization</string>
|
||||
<string name="developer">Developer</string>
|
||||
<string name="sucompat_disabled">SUCOMPAT DISABLED</string>
|
||||
</resources>
|
||||
|
||||
@@ -28,8 +28,8 @@ cmaker {
|
||||
}
|
||||
|
||||
val androidMinSdkVersion = 26
|
||||
val androidTargetSdkVersion = 35
|
||||
val androidCompileSdkVersion = 35
|
||||
val androidTargetSdkVersion = 36
|
||||
val androidCompileSdkVersion = 36
|
||||
val androidCompileNdkVersion = "28.1.13356709"
|
||||
val androidSourceCompatibility = JavaVersion.VERSION_21
|
||||
val androidTargetCompatibility = JavaVersion.VERSION_21
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
[versions]
|
||||
agp = "8.10.0"
|
||||
agp = "8.10.1"
|
||||
kotlin = "2.1.21"
|
||||
ksp = "2.1.21-2.0.1"
|
||||
compose-bom = "2025.05.01"
|
||||
lifecycle = "2.9.0"
|
||||
ksp = "2.1.21-2.0.2"
|
||||
compose-bom = "2025.06.00"
|
||||
lifecycle = "2.9.1"
|
||||
navigation = "2.9.0"
|
||||
activity-compose = "1.10.1"
|
||||
kotlinx-coroutines = "1.10.2"
|
||||
@@ -11,7 +11,7 @@ coil-compose = "2.7.0"
|
||||
compose-destination = "2.2.0"
|
||||
sheets-compose-dialogs = "1.3.0"
|
||||
markdown = "4.6.2"
|
||||
webkit = "1.13.0"
|
||||
webkit = "1.14.0"
|
||||
appiconloader-coil = "1.5.0"
|
||||
parcelablelist = "2.0.1"
|
||||
libsu = "6.0.0"
|
||||
@@ -72,7 +72,7 @@ sheet-compose-dialogs-input = { group = "com.maxkeppeler.sheets-compose-dialogs"
|
||||
|
||||
markdown = { group = "io.noties.markwon", name = "core", version.ref = "markdown" }
|
||||
|
||||
lsposed-cxx = { module = "org.lsposed.libcxx:libcxx", version = "27.0.12077973" }
|
||||
lsposed-cxx = { module = "org.lsposed.libcxx:libcxx", version = "28.1.13356709" }
|
||||
|
||||
mmrl-webui = { group = "com.github.MMRLApp.MMRL", name = "webui", version.ref = "mmrl" }
|
||||
mmrl-platform = { group = "com.github.MMRLApp.MMRL", name = "platform", version.ref = "mmrl" }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
2
userspace/kpmmgr/.gitignore
vendored
2
userspace/kpmmgr/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/obj
|
||||
/libs
|
||||
@@ -1,6 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := kpmmgr
|
||||
LOCAL_SRC_FILES := kpmmgr.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
@@ -1,3 +0,0 @@
|
||||
APP_ABI := arm64-v8a
|
||||
APP_PLATFORM := android-24
|
||||
APP_STL := none
|
||||
@@ -1,118 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||
#define KSU_OPTIONS 0xdeadbeef
|
||||
|
||||
// KPM控制代码
|
||||
#define CMD_KPM_CONTROL 28
|
||||
#define CMD_KPM_CONTROL_MAX 7
|
||||
|
||||
// 控制代码
|
||||
// prctl(xxx, 28, "PATH", "ARGS")
|
||||
// success return 0, error return -N
|
||||
#define SUKISU_KPM_LOAD 28
|
||||
|
||||
// prctl(xxx, 29, "NAME")
|
||||
// success return 0, error return -N
|
||||
#define SUKISU_KPM_UNLOAD 29
|
||||
|
||||
// num = prctl(xxx, 30)
|
||||
// error return -N
|
||||
// success return +num or 0
|
||||
#define SUKISU_KPM_NUM 30
|
||||
|
||||
// prctl(xxx, 31, Buffer, BufferSize)
|
||||
// success return +out, error return -N
|
||||
#define SUKISU_KPM_LIST 31
|
||||
|
||||
// prctl(xxx, 32, "NAME", Buffer[256])
|
||||
// success return +out, error return -N
|
||||
#define SUKISU_KPM_INFO 32
|
||||
|
||||
// prctl(xxx, 33, "NAME", "ARGS")
|
||||
// success return KPM's result value
|
||||
// error return -N
|
||||
#define SUKISU_KPM_CONTROL 33
|
||||
|
||||
// prctl(xxx, 34, buffer, bufferSize)
|
||||
// success return KPM's result value
|
||||
// error return -N
|
||||
#define SUKISU_KPM_VERSION 34
|
||||
|
||||
#define CONTROL_CODE(n) (n)
|
||||
|
||||
void print_usage(const char *prog) {
|
||||
printf("Usage: %s <command> [args]\n", prog);
|
||||
printf("Commands:\n");
|
||||
printf(" load <path> <args> Load a KPM module\n");
|
||||
printf(" unload <name> Unload a KPM module\n");
|
||||
printf(" num Get number of loaded modules\n");
|
||||
printf(" list List loaded KPM modules\n");
|
||||
printf(" info <name> Get info of a KPM module\n");
|
||||
printf(" control <name> <args> Send control command to a KPM module\n");
|
||||
printf(" version Print KPM Loader version\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ret = -1;
|
||||
int out = -1; // 存储返回值
|
||||
|
||||
if (strcmp(argv[1], "load") == 0 && argc >= 3) {
|
||||
// 加载 KPM 模块
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_LOAD), argv[2], (argc > 3 ? argv[3] : NULL), &out);
|
||||
if(out > 0) {
|
||||
printf("Success");
|
||||
}
|
||||
} else if (strcmp(argv[1], "unload") == 0 && argc >= 3) {
|
||||
// 卸载 KPM 模块
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_UNLOAD), argv[2], NULL, &out);
|
||||
} else if (strcmp(argv[1], "num") == 0) {
|
||||
// 获取加载的 KPM 数量
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_NUM), NULL, NULL, &out);
|
||||
printf("%d", out);
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "list") == 0) {
|
||||
// 获取模块列表
|
||||
char buffer[1024] = {0};
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_LIST), buffer, sizeof(buffer), &out);
|
||||
if (out >= 0) {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
} else if (strcmp(argv[1], "info") == 0 && argc >= 3) {
|
||||
// 获取指定模块信息
|
||||
char buffer[256] = {0};
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_INFO), argv[2], buffer, &out);
|
||||
if (out >= 0) {
|
||||
printf("%s\n", buffer);
|
||||
}
|
||||
} else if (strcmp(argv[1], "control") == 0 && argc >= 4) {
|
||||
// 控制 KPM 模块
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_CONTROL), argv[2], argv[3], &out);
|
||||
} else if (strcmp(argv[1], "version") == 0) {
|
||||
char buffer[1024] = {0};
|
||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_VERSION), buffer, sizeof(buffer), &out);
|
||||
if (out >= 0) {
|
||||
printf("%s", buffer);
|
||||
}
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (out < 0) {
|
||||
printf("Error: %s\n", strerror(-out));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
170
userspace/ksud_magic/Cargo.lock
generated
170
userspace/ksud_magic/Cargo.lock
generated
@@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
@@ -81,9 +81,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@@ -96,33 +96,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.8"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
|
||||
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
@@ -184,9 +184,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -199,9 +199,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
version = "3.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -217,18 +217,18 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.23"
|
||||
version = "1.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766"
|
||||
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
@@ -246,9 +246,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.38"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -256,9 +256,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.38"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -268,9 +268,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.32"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -280,15 +280,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
@@ -536,12 +536,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.11"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
|
||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -573,9 +573,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"libz-rs-sys",
|
||||
@@ -594,9 +594,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
@@ -631,9 +631,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@@ -710,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
"hashbrown 0.15.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -807,9 +807,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
version = "0.2.173"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb"
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
@@ -843,9 +843,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a"
|
||||
checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
|
||||
dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
@@ -891,15 +891,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
@@ -945,12 +945,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.0"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2611b99ab098a31bdc8be48b4f1a285ca0ced28bd5b4f23e45efa8c63b09efa5"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
@@ -985,7 +982,7 @@ version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"chrono",
|
||||
"flate2",
|
||||
"hex",
|
||||
@@ -999,7 +996,7 @@ version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"chrono",
|
||||
"hex",
|
||||
]
|
||||
@@ -1088,17 +1085,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.34"
|
||||
source = "git+https://github.com/KernelSU-Next/rustix.git?branch=main#4a53fbc7cb7a07cabe87125cc21dbc27db316259"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"itoa",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
@@ -1112,31 +1109,31 @@ version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -1240,9 +1237,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
version = "2.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1258,8 +1255,8 @@ dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix 1.0.5",
|
||||
"windows-sys 0.52.0",
|
||||
"rustix 1.0.7",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1283,9 +1280,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.45.0"
|
||||
version = "1.45.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
|
||||
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -1306,9 +1303,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@@ -1407,13 +1404,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "7.0.3"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762"
|
||||
checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d"
|
||||
dependencies = [
|
||||
"either",
|
||||
"env_home",
|
||||
"rustix 1.0.5",
|
||||
"rustix 1.0.7",
|
||||
"winsafe",
|
||||
]
|
||||
|
||||
@@ -1439,7 +1435,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1485,9 +1481,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
@@ -1601,7 +1597,7 @@ version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1662,9 +1658,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8"
|
||||
checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
|
||||
@@ -38,7 +38,7 @@ rust-embed = { version = "8", features = [
|
||||
"debug-embed",
|
||||
"compression", # must clean build after updating binaries
|
||||
] }
|
||||
which = "7"
|
||||
which = "8"
|
||||
getopts = "0.2"
|
||||
sha256 = "1"
|
||||
sha1 = "0.10"
|
||||
|
||||
@@ -167,6 +167,21 @@ fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_vendor_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(vendor_ramdisk_cpio)
|
||||
.arg(cmd)
|
||||
.status()?;
|
||||
|
||||
ensure!(status.success(), "magiskboot cpio {} failed", cmd);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_magisk_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
@@ -234,6 +249,7 @@ pub fn restore(
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
is_kernelsu_patched,
|
||||
@@ -270,16 +286,29 @@ pub fn restore(
|
||||
}
|
||||
|
||||
if new_boot.is_none() {
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
if no_ramdisk {
|
||||
// vendor ramdisk restore
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
let status = do_vendor_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
} else {
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
}
|
||||
|
||||
println!("- Repacking boot image");
|
||||
@@ -441,11 +470,6 @@ fn do_patch(
|
||||
assets::copy_assets_to_file("ksuinit", init_file).context("copy ksuinit failed")?;
|
||||
}
|
||||
|
||||
// magiskboot unpack boot.img
|
||||
// magiskboot cpio ramdisk.cpio 'cp init init.real'
|
||||
// magiskboot cpio ramdisk.cpio 'add 0755 ksuinit init'
|
||||
// magiskboot cpio ramdisk.cpio 'add 0755 <kmod> kernelsu.ko'
|
||||
|
||||
println!("- Unpacking boot image");
|
||||
let status = Command::new(&magiskboot)
|
||||
.current_dir(workdir)
|
||||
@@ -468,17 +492,29 @@ fn do_patch(
|
||||
|
||||
let mut need_backup = false;
|
||||
if !is_kernelsu_patched {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
if no_ramdisk {
|
||||
// vendor ramdisk patching
|
||||
let status = do_vendor_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
} else {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
}
|
||||
|
||||
need_backup = flash;
|
||||
}
|
||||
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
if no_ramdisk {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else {
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
if need_backup {
|
||||
@@ -658,8 +694,12 @@ fn find_boot_image(
|
||||
|
||||
let init_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
|
||||
let vendor_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
|
||||
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/init_boot{slot_suffix}")
|
||||
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
|
||||
} else {
|
||||
format!("/dev/block/by-name/boot{slot_suffix}")
|
||||
};
|
||||
|
||||
186
userspace/ksud_overlayfs/Cargo.lock
generated
186
userspace/ksud_overlayfs/Cargo.lock
generated
@@ -13,9 +13,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
@@ -29,7 +29,7 @@ version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
@@ -81,9 +81,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@@ -96,33 +96,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.8"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
|
||||
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
@@ -168,7 +168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
@@ -184,9 +184,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -199,9 +199,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
version = "3.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -217,9 +217,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.23"
|
||||
version = "1.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766"
|
||||
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
@@ -232,9 +232,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
@@ -252,9 +252,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.38"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -262,9 +262,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.38"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -274,9 +274,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.32"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -286,15 +286,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
@@ -361,7 +361,7 @@ version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -495,7 +495,7 @@ version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -542,12 +542,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.11"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
|
||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -579,9 +579,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"libz-rs-sys",
|
||||
@@ -600,9 +600,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
@@ -613,7 +613,7 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi",
|
||||
@@ -637,9 +637,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@@ -729,7 +729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
"hashbrown 0.15.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -828,9 +828,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
version = "0.2.173"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb"
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
@@ -864,9 +864,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a"
|
||||
checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221"
|
||||
dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
@@ -921,9 +921,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
@@ -937,9 +937,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
@@ -985,12 +985,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.0"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2611b99ab098a31bdc8be48b4f1a285ca0ced28bd5b4f23e45efa8c63b09efa5"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
@@ -1025,7 +1022,7 @@ version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"chrono",
|
||||
"flate2",
|
||||
"hex",
|
||||
@@ -1039,7 +1036,7 @@ version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
"chrono",
|
||||
"hex",
|
||||
]
|
||||
@@ -1128,17 +1125,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.34"
|
||||
source = "git+https://github.com/KernelSU-Next/rustix.git?branch=main#4a53fbc7cb7a07cabe87125cc21dbc27db316259"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"itoa",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
@@ -1152,31 +1149,31 @@ version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.5"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno 0.3.11",
|
||||
"bitflags 2.9.1",
|
||||
"errno 0.3.12",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -1231,7 +1228,7 @@ version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
@@ -1242,7 +1239,7 @@ version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
@@ -1280,9 +1277,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
version = "2.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1298,8 +1295,8 @@ dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix 1.0.5",
|
||||
"windows-sys 0.52.0",
|
||||
"rustix 1.0.7",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1343,9 +1340,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.45.0"
|
||||
version = "1.45.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
|
||||
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -1366,9 +1363,9 @@ checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@@ -1413,7 +1410,7 @@ version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if 1.0.1",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -1467,13 +1464,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "7.0.3"
|
||||
version = "8.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762"
|
||||
checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d"
|
||||
dependencies = [
|
||||
"either",
|
||||
"env_home",
|
||||
"rustix 1.0.5",
|
||||
"rustix 1.0.7",
|
||||
"winsafe",
|
||||
]
|
||||
|
||||
@@ -1499,7 +1495,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1545,9 +1541,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
@@ -1661,7 +1657,7 @@ version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1722,9 +1718,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8"
|
||||
checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
|
||||
@@ -37,7 +37,7 @@ rust-embed = { version = "8", features = [
|
||||
"debug-embed",
|
||||
"compression", # must clean build after updating binaries
|
||||
] }
|
||||
which = "7"
|
||||
which = "8"
|
||||
getopts = "0.2"
|
||||
sha256 = "1"
|
||||
sha1 = "0.10"
|
||||
|
||||
@@ -167,6 +167,21 @@ fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_vendor_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> {
|
||||
let vendor_ramdisk_cpio = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("cpio")
|
||||
.arg(vendor_ramdisk_cpio)
|
||||
.arg(cmd)
|
||||
.status()?;
|
||||
|
||||
ensure!(status.success(), "magiskboot cpio {} failed", cmd);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_magisk_patched(magiskboot: &Path, workdir: &Path) -> Result<bool> {
|
||||
let status = Command::new(magiskboot)
|
||||
.current_dir(workdir)
|
||||
@@ -234,6 +249,7 @@ pub fn restore(
|
||||
.status()?;
|
||||
ensure!(status.success(), "magiskboot unpack failed");
|
||||
|
||||
let no_ramdisk = !workdir.join("ramdisk.cpio").exists();
|
||||
let is_kernelsu_patched = is_kernelsu_patched(&magiskboot, workdir)?;
|
||||
ensure!(
|
||||
is_kernelsu_patched,
|
||||
@@ -270,16 +286,29 @@ pub fn restore(
|
||||
}
|
||||
|
||||
if new_boot.is_none() {
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
if no_ramdisk {
|
||||
// vendor ramdisk restore
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
let status = do_vendor_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let vendor_ramdisk = workdir.join("vendor_ramdisk").join("init_boot.cpio");
|
||||
std::fs::remove_file(vendor_ramdisk)?;
|
||||
}
|
||||
} else {
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
// remove kernelsu.ko
|
||||
do_cpio_cmd(&magiskboot, workdir, "rm kernelsu.ko")?;
|
||||
|
||||
// if init.real exists, restore it
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init.real").is_ok();
|
||||
if status {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init.real init")?;
|
||||
} else {
|
||||
let ramdisk = workdir.join("ramdisk.cpio");
|
||||
std::fs::remove_file(ramdisk)?;
|
||||
}
|
||||
}
|
||||
|
||||
println!("- Repacking boot image");
|
||||
@@ -301,7 +330,7 @@ pub fn restore(
|
||||
let output_dir = std::env::current_dir()?;
|
||||
let now = chrono::Utc::now();
|
||||
let output_image = output_dir.join(format!(
|
||||
"kernelsu_restore_{}.img",
|
||||
"kernelsu_next_restore_{}.img",
|
||||
now.format("%Y%m%d_%H%M%S")
|
||||
));
|
||||
|
||||
@@ -441,11 +470,6 @@ fn do_patch(
|
||||
assets::copy_assets_to_file("ksuinit", init_file).context("copy ksuinit failed")?;
|
||||
}
|
||||
|
||||
// magiskboot unpack boot.img
|
||||
// magiskboot cpio ramdisk.cpio 'cp init init.real'
|
||||
// magiskboot cpio ramdisk.cpio 'add 0755 ksuinit init'
|
||||
// magiskboot cpio ramdisk.cpio 'add 0755 <kmod> kernelsu.ko'
|
||||
|
||||
println!("- Unpacking boot image");
|
||||
let status = Command::new(&magiskboot)
|
||||
.current_dir(workdir)
|
||||
@@ -468,17 +492,29 @@ fn do_patch(
|
||||
|
||||
let mut need_backup = false;
|
||||
if !is_kernelsu_patched {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
if no_ramdisk {
|
||||
// vendor ramdisk patching
|
||||
let status = do_vendor_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
} else {
|
||||
// kernelsu.ko is not exist, backup init if necessary
|
||||
let status = do_cpio_cmd(&magiskboot, workdir, "exists init");
|
||||
if status.is_ok() {
|
||||
do_cpio_cmd(&magiskboot, workdir, "mv init init.real")?;
|
||||
}
|
||||
need_backup = flash;
|
||||
}
|
||||
|
||||
need_backup = flash;
|
||||
}
|
||||
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
if no_ramdisk {
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_vendor_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
} else {
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 init init")?;
|
||||
do_cpio_cmd(&magiskboot, workdir, "add 0755 kernelsu.ko kernelsu.ko")?;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
if need_backup {
|
||||
@@ -658,8 +694,12 @@ fn find_boot_image(
|
||||
|
||||
let init_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/init_boot{slot_suffix}")).exists();
|
||||
let vendor_boot_exist =
|
||||
Path::new(&format!("/dev/block/by-name/vendor_boot{slot_suffix}")).exists();
|
||||
let boot_partition = if !is_replace_kernel && init_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/init_boot{slot_suffix}")
|
||||
} else if !is_replace_kernel && vendor_boot_exist && !skip_init {
|
||||
format!("/dev/block/by-name/vendor_boot{slot_suffix}")
|
||||
} else {
|
||||
format!("/dev/block/by-name/boot{slot_suffix}")
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user