diff --git a/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/config.yml b/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000000..d4f07b614a0e --- /dev/null +++ b/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Feature Request + url: https://github.com/tiann/KernelSU/issues/1705 + about: "We do not accept external Feature Requests, see this link for more details." diff --git a/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/feature_request.yml b/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index f094b0234e5e..000000000000 --- a/drivers/staging/kernelsu/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Feature Request -description: "Suggest an idea for this project" -title: "[Feature]" -labels: "feature" -body: - - type: markdown - id: feature-info - attributes: - value: "## Feature Infomation" - - type: textarea - id: feature-main - validations: - required: true - attributes: - label: "Is your feature request related to a problem? Please describe." - description: "A clear and concise description of what the problem is." - placeholder: "I'm always frustrated when [...]" - - type: textarea - id: feature-solution - validations: - required: true - attributes: - label: "Describe the solution you'd like." - description: "A clear and concise description of what you want to happen." - - type: textarea - id: feature-describe - validations: - required: true - attributes: - label: "Describe alternatives you've considered." - description: "A clear and concise description of any alternative solutions or features you've considered." - - type: textarea - id: feature-extra - validations: - required: false - attributes: - label: "Additional context" - description: "Add any other context or screenshots about the feature request here." - diff --git a/drivers/staging/kernelsu/.github/dependabot.yml b/drivers/staging/kernelsu/.github/dependabot.yml index 018b1c009ce3..95e3839ef7ad 100644 --- a/drivers/staging/kernelsu/.github/dependabot.yml +++ b/drivers/staging/kernelsu/.github/dependabot.yml @@ -4,18 +4,35 @@ updates: directory: / schedule: interval: daily - + groups: + actions: + patterns: + - "*" - package-ecosystem: cargo directory: userspace/ksud schedule: interval: daily - + allow: + - dependency-type: "all" + groups: + crates: + patterns: + - "*" - package-ecosystem: gradle directory: manager schedule: interval: daily - + groups: + maven: + patterns: + - "*" - package-ecosystem: npm directory: website schedule: interval: daily + allow: + - dependency-type: "all" + groups: + npm: + patterns: + - "*" diff --git a/drivers/staging/kernelsu/.github/scripts/build_a12.sh b/drivers/staging/kernelsu/.github/scripts/build_a12.sh index d6abf750cfee..04e09b9fb28e 100644 --- a/drivers/staging/kernelsu/.github/scripts/build_a12.sh +++ b/drivers/staging/kernelsu/.github/scripts/build_a12.sh @@ -51,7 +51,7 @@ build_from_image() { echo "[+] Images to upload" find . -type f -name "*.gz" - # find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU/scripts/ksubot.py {} + + # find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU-Next/scripts/ksubot.py {} + } for dir in Image*; do diff --git a/drivers/staging/kernelsu/.github/scripts/build_a13.sh b/drivers/staging/kernelsu/.github/scripts/build_a13.sh index 929e1be077e2..6ef5f18a54d8 100644 --- a/drivers/staging/kernelsu/.github/scripts/build_a13.sh +++ b/drivers/staging/kernelsu/.github/scripts/build_a13.sh @@ -30,7 +30,7 @@ build_from_image() { echo '[+] Images to upload' find . -type f -name "*.gz" - # find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU/scripts/ksubot.py {} + + # find . -type f -name "*.gz" -exec python3 "$GITHUB_WORKSPACE"/KernelSU-Next/scripts/ksubot.py {} + } for dir in Image*; do diff --git a/drivers/staging/kernelsu/.github/workflows/add-device.yml b/drivers/staging/kernelsu/.github/workflows/add-device.yml index 0b3a01a7ab11..c98c2ac4f9b9 100644 --- a/drivers/staging/kernelsu/.github/workflows/add-device.yml +++ b/drivers/staging/kernelsu/.github/workflows/add-device.yml @@ -26,7 +26,7 @@ jobs: - name: Make pull request if: steps.handle-add-device.outputs.success == 'true' id: cpr - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "[add device]: ${{ steps.handle-add-device.outputs.device }}" @@ -37,6 +37,7 @@ jobs: branch: "add-device-${{ github.event.issue.number }}" labels: add-device delete-branch: true + sign-commits: true - name: Check outputs if: ${{ steps.cpr.outputs.pull-request-number }} run: | diff --git a/drivers/staging/kernelsu/.github/workflows/avd-kernel.yml b/drivers/staging/kernelsu/.github/workflows/avd-kernel.yml index c09bda5ae8ca..5ee0f83c3c77 100644 --- a/drivers/staging/kernelsu/.github/workflows/avd-kernel.yml +++ b/drivers/staging/kernelsu/.github/workflows/avd-kernel.yml @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v4 with: - path: KernelSU + path: KernelSU-Next fetch-depth: 0 - name: Setup need_upload @@ -70,37 +70,37 @@ jobs: cd $GITHUB_WORKSPACE sudo apt-get install repo -y mkdir android-kernel && cd android-kernel - repo init --depth=1 -u https://android.googlesource.com/kernel/manifest -m "$GITHUB_WORKSPACE/KernelSU/.github/manifests/${{ inputs.manifest_name }}" --repo-rev=v2.16 + repo init --depth=1 -u https://android.googlesource.com/kernel/manifest -m "$GITHUB_WORKSPACE/KernelSU-Next/.github/manifests/${{ inputs.manifest_name }}" --repo-rev=v2.16 repo --version repo --trace sync -c -j$(nproc --all) --no-tags df -h - - name: Setup KernelSU + - name: Setup KernelSU-Next env: PATCH_PATH: ${{ inputs.patch_path }} IS_DEBUG_KERNEL: ${{ inputs.debug }} run: | cd $GITHUB_WORKSPACE/android-kernel - echo "[+] KernelSU setup" + echo "[+] KernelSU-Next setup" GKI_ROOT=$(pwd) echo "[+] GKI_ROOT: $GKI_ROOT" - echo "[+] Copy KernelSU driver to $GKI_ROOT/common/drivers" - ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu - echo "[+] Add KernelSU driver to Makefile" + echo "[+] Copy KernelSU-Next driver to $GKI_ROOT/common/drivers" + ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $GKI_ROOT/common/drivers/kernelsu + echo "[+] Add KernelSU-Next driver to Makefile" DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile DRIVER_KCONFIG=$GKI_ROOT/common/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 $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found" + echo "[+] Apply KernelSU-Next patches" + cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found" if [ "$IS_DEBUG_KERNEL" = "true" ]; then echo "[+] Enable debug features for kernel" - printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU/kernel/Makefile + printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU-Next/kernel/Makefile fi repo status - echo "[+] KernelSU setup done." - cd $GITHUB_WORKSPACE/KernelSU + 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 @@ -110,8 +110,8 @@ jobs: run: | rm common/android/abi_gki_protected_exports_* || echo "No protected exports!" git config --global user.email "bot@kernelsu.org" - git config --global user.name "KernelSUBot" - cd common/ && git add -A && git commit -a -m "Add KernelSU" + git config --global user.name "KernelSU-NextBot" + cd common/ && git add -A && git commit -a -m "Add KernelSU-Next" repo status - name: Build kernel diff --git a/drivers/staging/kernelsu/.github/workflows/build-debug-kernel.yml b/drivers/staging/kernelsu/.github/workflows/build-debug-kernel.yml index a0cab91b2238..5ddb4b3d3014 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-debug-kernel.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-debug-kernel.yml @@ -7,9 +7,9 @@ jobs: uses: ./.github/workflows/gki-kernel.yml with: version: android12-5.10 - version_name: android12-5.10.209 - tag: android12-5.10-2024-05 - os_patch_level: 2024-05 + version_name: android12-5.10.218 + tag: android12-5.10-2024-08 + os_patch_level: 2024-08 patch_path: "5.10" debug: true build-debug-kernel-a13: @@ -17,11 +17,11 @@ jobs: matrix: include: - version: "5.10" - sub_level: 209 - os_patch_level: 2024-05 + sub_level: 218 + os_patch_level: 2024-08 - version: "5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 151 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml with: version: android13-${{ matrix.version }} @@ -34,15 +34,29 @@ jobs: matrix: include: - version: "5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 158 + os_patch_level: 2024-08 - version: "6.1" - sub_level: 75 - os_patch_level: 2024-05 + sub_level: 90 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml with: version: android14-${{ matrix.version }} version_name: android14-${{ matrix.version }}.${{ matrix.sub_level }} tag: android14-${{ matrix.version }}-${{ matrix.os_patch_level }} patch_path: ${{ matrix.version }} + debug: true + build-debug-kernel-a15: + strategy: + matrix: + include: + - version: "6.6" + sub_level: 30 + os_patch_level: 2024-08 + uses: ./.github/workflows/gki-kernel.yml + with: + version: android15-${{ matrix.version }} + version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }} + tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }} + patch_path: ${{ matrix.version }} debug: true \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-a12.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-a12.yml index 89f9c984dc36..56a0688b2c7a 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-a12.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-kernel-a12.yml @@ -1,14 +1,14 @@ name: Build Kernel - Android 12 on: push: - branches: ["main", "ci", "checkci"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a12.yml" - ".github/workflows/gki-kernel.yml" - ".github/scripts/build_a12.sh" - "kernel/**" pull_request: - branches: ["main"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a12.yml" - ".github/workflows/gki-kernel.yml" @@ -17,7 +17,7 @@ on: workflow_call: jobs: build-kernel: - if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci' + if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next' strategy: matrix: include: @@ -27,6 +27,8 @@ jobs: os_patch_level: 2024-03 - sub_level: 209 os_patch_level: 2024-05 + - sub_level: 218 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml secrets: inherit with: @@ -39,7 +41,7 @@ jobs: upload-artifacts: needs: build-kernel runs-on: ubuntu-latest - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }} + if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }} env: CHAT_ID: ${{ secrets.CHAT_ID }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} @@ -53,7 +55,7 @@ jobs: - uses: actions/checkout@v4 with: - path: KernelSU + path: KernelSU-Next fetch-depth: 0 - name: List artifacts @@ -63,7 +65,7 @@ jobs: - name: Download prebuilt toolchain run: | AOSP_MIRROR=https://android.googlesource.com - BRANCH=main-kernel-build-2023 + BRANCH=main-kernel-build-2024 git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1 @@ -92,11 +94,11 @@ jobs: export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4 export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py - cd $GITHUB_WORKSPACE/KernelSU + cd $GITHUB_WORKSPACE/KernelSU-Next export VERSION=$(($(git rev-list --count HEAD) + 10200)) echo "VERSION: $VERSION" cd - - bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a12.sh + bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a12.sh - name: Display structure of boot files run: ls -R @@ -108,11 +110,11 @@ jobs: path: Image-android12*/*.img.gz check-build-kernel: - if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci' + if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next' uses: ./.github/workflows/gki-kernel.yml with: version: android12-5.10 - version_name: android12-5.10.209 - tag: android12-5.10-2024-05 - os_patch_level: 2024-05 + version_name: android12-5.10.218 + tag: android12-5.10-2024-08 + os_patch_level: 2024-08 patch_path: "5.10" \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-a13.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-a13.yml index 9390b48e7f6f..431ed5cf04ad 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-a13.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-kernel-a13.yml @@ -1,14 +1,14 @@ name: Build Kernel - Android 13 on: push: - branches: ["main", "ci", "checkci"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a13.yml" - ".github/workflows/gki-kernel.yml" - ".github/scripts/build_a13.sh" - "kernel/**" pull_request: - branches: ["main"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a13.yml" - ".github/workflows/gki-kernel.yml" @@ -17,7 +17,7 @@ on: workflow_call: jobs: build-kernel: - if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci' + if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next' strategy: matrix: include: @@ -33,6 +33,15 @@ jobs: - version: "5.10" sub_level: 209 os_patch_level: 2024-05 + - version: "5.10" + sub_level: 210 + os_patch_level: 2024-06 + - version: "5.10" + sub_level: 214 + os_patch_level: 2024-07 + - version: "5.10" + sub_level: 218 + os_patch_level: 2024-08 - version: "5.15" sub_level: 123 os_patch_level: 2023-11 @@ -45,6 +54,12 @@ jobs: - version: "5.15" sub_level: 148 os_patch_level: 2024-05 + - version: "5.15" + sub_level: 149 + os_patch_level: 2024-07 + - version: "5.15" + sub_level: 151 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml secrets: inherit with: @@ -57,7 +72,7 @@ jobs: upload-artifacts: needs: build-kernel runs-on: ubuntu-latest - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }} + if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }} env: CHAT_ID: ${{ secrets.CHAT_ID }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} @@ -71,7 +86,7 @@ jobs: - uses: actions/checkout@v4 with: - path: KernelSU + path: KernelSU-Next fetch-depth: 0 - name: List artifacts @@ -81,7 +96,7 @@ jobs: - name: Download prebuilt toolchain run: | AOSP_MIRROR=https://android.googlesource.com - BRANCH=main-kernel-build-2023 + BRANCH=main-kernel-build-2024 git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1 @@ -110,11 +125,11 @@ jobs: export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4 export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py - cd $GITHUB_WORKSPACE/KernelSU + cd $GITHUB_WORKSPACE/KernelSU-Next export VERSION=$(($(git rev-list --count HEAD) + 10200)) echo "VERSION: $VERSION" cd - - bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh + bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh - name: Display structure of boot files run: ls -R @@ -126,16 +141,16 @@ jobs: path: Image-android13*/*.img.gz check-build-kernel: - if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci' + if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next' strategy: matrix: include: - version: "5.10" - sub_level: 209 - os_patch_level: 2024-05 + sub_level: 218 + os_patch_level: 2024-08 - version: "5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 151 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml with: version: android13-${{ matrix.version }} diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-a14.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-a14.yml index a06f02b1f732..dd6e19cfc8d2 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-a14.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-kernel-a14.yml @@ -1,14 +1,14 @@ name: Build Kernel - Android 14 on: push: - branches: ["main", "ci", "checkci"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a14.yml" - ".github/workflows/gki-kernel.yml" - ".github/scripts/build_a13.sh" - "kernel/**" pull_request: - branches: ["main"] + branches: [ "next" ] paths: - ".github/workflows/build-kernel-a14.yml" - ".github/workflows/gki-kernel.yml" @@ -17,7 +17,7 @@ on: workflow_call: jobs: build-kernel: - if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci' + if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next' strategy: matrix: include: @@ -33,6 +33,15 @@ jobs: - version: "5.15" sub_level: 148 os_patch_level: 2024-05 + - version: "5.15" + sub_level: 149 + os_patch_level: 2024-06 + - version: "5.15" + sub_level: 153 + os_patch_level: 2024-07 + - version: "5.15" + sub_level: 158 + os_patch_level: 2024-08 - version: "6.1" sub_level: 25 os_patch_level: 2023-10 @@ -48,6 +57,15 @@ jobs: - version: "6.1" sub_level: 75 os_patch_level: 2024-05 + - version: "6.1" + sub_level: 78 + os_patch_level: 2024-06 + - version: "6.1" + sub_level: 84 + os_patch_level: 2024-07 + - version: "6.1" + sub_level: 90 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml secrets: inherit with: @@ -60,7 +78,7 @@ jobs: upload-artifacts: needs: build-kernel runs-on: ubuntu-latest - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/ci' }} + if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }} env: CHAT_ID: ${{ secrets.CHAT_ID }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} @@ -74,7 +92,7 @@ jobs: - uses: actions/checkout@v4 with: - path: KernelSU + path: KernelSU-Next fetch-depth: 0 - name: List artifacts @@ -84,7 +102,7 @@ jobs: - name: Download prebuilt toolchain run: | AOSP_MIRROR=https://android.googlesource.com - BRANCH=main-kernel-build-2023 + BRANCH=main-kernel-build-2024 git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1 @@ -113,11 +131,11 @@ jobs: export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4 export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py - cd $GITHUB_WORKSPACE/KernelSU + cd $GITHUB_WORKSPACE/KernelSU-Next export VERSION=$(($(git rev-list --count HEAD) + 10200)) echo "VERSION: $VERSION" cd - - bash $GITHUB_WORKSPACE/KernelSU/.github/scripts/build_a13.sh + bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh - name: Display structure of boot files run: ls -R @@ -129,16 +147,16 @@ jobs: path: Image-android14*/*.img.gz check-build-kernel: - if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci' + if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next' strategy: matrix: include: - version: "5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 158 + os_patch_level: 2024-08 - version: "6.1" - sub_level: 75 - os_patch_level: 2024-05 + sub_level: 90 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml with: version: android14-${{ matrix.version }} diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-a15.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-a15.yml new file mode 100644 index 000000000000..881cda299e5a --- /dev/null +++ b/drivers/staging/kernelsu/.github/workflows/build-kernel-a15.yml @@ -0,0 +1,121 @@ +name: Build Kernel - Android 15 +on: + push: + branches: [ "next" ] + paths: + - ".github/workflows/build-kernel-a15.yml" + - ".github/workflows/gki-kernel.yml" + - ".github/scripts/build_a13.sh" + - "kernel/**" + pull_request: + branches: [ "next" ] + paths: + - ".github/workflows/build-kernel-a15.yml" + - ".github/workflows/gki-kernel.yml" + - ".github/scripts/build-a13.sh" + - "kernel/**" + workflow_call: +jobs: + build-kernel: + if: github.event_name != 'pull_request' && github.ref != 'refs/heads/next' + strategy: + matrix: + include: + - version: "6.6" + sub_level: 30 + os_patch_level: 2024-08 + uses: ./.github/workflows/gki-kernel.yml + secrets: inherit + with: + version: android15-${{ matrix.version }} + version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }} + tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }} + os_patch_level: ${{ matrix.os_patch_level }} + patch_path: ${{ matrix.version }} + + upload-artifacts: + needs: build-kernel + runs-on: ubuntu-latest + if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/next' ) || github.ref_type == 'tag' || github.ref == 'refs/heads/next' }} + env: + CHAT_ID: ${{ secrets.CHAT_ID }} + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} + MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }} + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + COMMIT_URL: ${{ github.event.head_commit.url }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + + - uses: actions/checkout@v4 + with: + path: KernelSU-Next + fetch-depth: 0 + + - name: List artifacts + run: | + tree + + - name: Download prebuilt toolchain + run: | + AOSP_MIRROR=https://android.googlesource.com + BRANCH=main-kernel-build-2024 + git clone $AOSP_MIRROR/platform/prebuilts/build-tools -b $BRANCH --depth 1 build-tools + git clone $AOSP_MIRROR/kernel/prebuilts/build-tools -b $BRANCH --depth 1 kernel-build-tools + git clone $AOSP_MIRROR/platform/system/tools/mkbootimg -b $BRANCH --depth 1 + pip3 install telethon + + - name: Set boot sign key + env: + BOOT_SIGN_KEY: ${{ secrets.BOOT_SIGN_KEY }} + run: | + if [ ! -z "$BOOT_SIGN_KEY" ]; then + echo "$BOOT_SIGN_KEY" > ./kernel-build-tools/linux-x86/share/avb/testkey_rsa2048.pem + fi + + - name: Bot session cache + id: bot_session_cache + uses: actions/cache@v4 + if: false + with: + path: scripts/ksubot.session + key: ${{ runner.os }}-bot-session + + - name: Build boot images + run: | + export AVBTOOL=$GITHUB_WORKSPACE/kernel-build-tools/linux-x86/bin/avbtool + export GZIP=$GITHUB_WORKSPACE/build-tools/path/linux-x86/gzip + export LZ4=$GITHUB_WORKSPACE/build-tools/path/linux-x86/lz4 + export MKBOOTIMG=$GITHUB_WORKSPACE/mkbootimg/mkbootimg.py + export UNPACK_BOOTIMG=$GITHUB_WORKSPACE/mkbootimg/unpack_bootimg.py + cd $GITHUB_WORKSPACE/KernelSU-Next + export VERSION=$(($(git rev-list --count HEAD) + 10200)) + echo "VERSION: $VERSION" + cd - + bash $GITHUB_WORKSPACE/KernelSU-Next/.github/scripts/build_a13.sh + + - name: Display structure of boot files + run: ls -R + + - name: Upload images artifact + uses: actions/upload-artifact@v4 + with: + name: boot-images-android15 + path: Image-android15*/*.img.gz + + check-build-kernel: + if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/next' + strategy: + matrix: + include: + - version: "6.6" + sub_level: 30 + os_patch_level: 2024-08 + uses: ./.github/workflows/gki-kernel.yml + with: + version: android15-${{ matrix.version }} + version_name: android15-${{ matrix.version }}.${{ matrix.sub_level }} + tag: android15-${{ matrix.version }}-${{ matrix.os_patch_level }} + os_patch_level: ${{ matrix.os_patch_level }} + patch_path: ${{ matrix.version }} \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-arcvm.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-arcvm.yml deleted file mode 100644 index 18c97c2f949d..000000000000 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-arcvm.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: Build Kernel - ChromeOS ARCVM -on: - push: - branches: ["main", "ci", "checkci"] - paths: - - ".github/workflows/build-kernel-arcvm.yml" - - "kernel/**" - pull_request: - branches: ["main"] - 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-20.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=12 - 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 - uses: actions/checkout@v4 - with: - path: KernelSU - 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 - working-directory: kernel - run: | - echo "[+] KernelSU setup" - KERNEL_ROOT=$GITHUB_WORKSPACE/kernel - echo "[+] KERNEL_ROOT: $KERNEL_ROOT" - echo "[+] Copy KernelSU driver to $KERNEL_ROOT/drivers" - ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $KERNEL_ROOT/drivers/kernelsu - - echo "[+] Add KernelSU driver to Makefile" - DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile - grep -q "kernelsu" $DRIVER_MAKEFILE || echo "obj-y += kernelsu/" >> $DRIVER_MAKEFILE - - echo "[+] Apply KernelSU patches" - cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/5.10/*.patch || echo "[-] No patch found" - - echo "[+] Patch script/setlocalversion" - sed -i 's/-dirty//g' $KERNEL_ROOT/scripts/setlocalversion - - echo "[+] KernelSU setup done." - cd $GITHUB_WORKSPACE/KernelSU - KSU_VERSION=$(($(git rev-list --count HEAD) + 10200)) - echo "KernelSU version: $KSU_VERSION" - echo "kernelsu_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 }}" diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-avd.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-avd.yml deleted file mode 100644 index 504a5207ee10..000000000000 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-avd.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Build Kernel - AVD -on: - push: - branches: ["main", "ci", "checkci"] - paths: - - ".github/workflows/build-kernel-avd.yml" - - ".github/workflows/avd-kernel.yml" - - ".github/workflows/manifests/*xml" - - "kernel/**" - pull_request: - branches: ["main"] - paths: - - ".github/workflows/build-kernel-avd.yml" - - ".github/workflows/avd-kernel.yml" - - ".github/workflows/manifests/*.xml" - - "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 diff --git a/drivers/staging/kernelsu/.github/workflows/build-kernel-wsa.yml b/drivers/staging/kernelsu/.github/workflows/build-kernel-wsa.yml deleted file mode 100644 index 9a313de9a1db..000000000000 --- a/drivers/staging/kernelsu/.github/workflows/build-kernel-wsa.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Build Kernel - WSA -on: - push: - branches: ["main", "ci", "checkci"] - paths: - - ".github/workflows/build-kernel-wsa.yml" - - ".github/workflows/wsa-kernel.yml" - - "kernel/**" - pull_request: - branches: ["main"] - paths: - - ".github/workflows/build-kernel-wsa.yml" - - ".github/workflows/wsa-kernel.yml" - - "kernel/**" - workflow_call: - workflow_dispatch: - -jobs: - build: - if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci' - strategy: - matrix: - arch: [x86_64, arm64] - version: ["5.15.94.2", "5.15.104.1", "5.15.104.2", "5.15.104.3", "5.15.104.4"] - uses: ./.github/workflows/wsa-kernel.yml - with: - arch: ${{ matrix.arch }} - version: ${{ matrix.version }} - - check_build: - if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci' - uses: ./.github/workflows/wsa-kernel.yml - strategy: - matrix: - arch: [x86_64, arm64] - with: - arch: ${{ matrix.arch }} - version: "5.15.104.4" \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/build-lkm.yml b/drivers/staging/kernelsu/.github/workflows/build-lkm.yml index 5a14ce1b4826..a406753cf272 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-lkm.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-lkm.yml @@ -1,11 +1,11 @@ -name: Build LKM for KernelSU +name: Build LKM for KernelSU-Next on: push: - branches: ["main", "ci", "checkci"] + branches: [ "next" ] paths: - ".github/workflows/build-lkm.yml" pull_request: - branches: ["main"] + branches: [ "next" ] paths: - ".github/workflows/build-lkm.yml" workflow_call: @@ -15,20 +15,23 @@ jobs: matrix: include: - version: "android12-5.10" - sub_level: 209 - os_patch_level: 2024-05 + sub_level: 218 + os_patch_level: 2024-08 - version: "android13-5.10" - sub_level: 209 - os_patch_level: 2024-05 + sub_level: 218 + os_patch_level: 2024-08 - version: "android13-5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 151 + os_patch_level: 2024-08 - version: "android14-5.15" - sub_level: 148 - os_patch_level: 2024-05 + sub_level: 158 + os_patch_level: 2024-08 - version: "android14-6.1" - sub_level: 75 - os_patch_level: 2024-05 + sub_level: 90 + os_patch_level: 2024-08 + - version: "android15-6.6" + sub_level: 30 + os_patch_level: 2024-08 uses: ./.github/workflows/gki-kernel.yml with: version: ${{ matrix.version }} diff --git a/drivers/staging/kernelsu/.github/workflows/build-manager.yml b/drivers/staging/kernelsu/.github/workflows/build-manager.yml index b5013641c661..b185348ef918 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-manager.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-manager.yml @@ -2,17 +2,18 @@ name: Build Manager on: push: - branches: [ "main", "ci" ] + branches: [ "next" ] paths: - '.github/workflows/build-manager.yml' - 'manager/**' - 'kernel/**' - 'userspace/ksud/**' pull_request: - branches: [ "main" ] + branches: [ "next" ] paths: - 'manager/**' workflow_call: + workflow_dispatch: jobs: build-lkm: @@ -26,18 +27,6 @@ jobs: include: - target: aarch64-linux-android os: ubuntu-latest - - target: x86_64-linux-android - os: ubuntu-latest - - target: x86_64-pc-windows-gnu # windows pc - os: ubuntu-latest - - target: x86_64-apple-darwin # Intel mac - os: macos-latest - - target: aarch64-apple-darwin # M chip mac - os: macos-latest - - target: aarch64-unknown-linux-musl # arm64 Linux - os: ubuntu-latest - - target: x86_64-unknown-linux-musl # x86 Linux - os: ubuntu-latest uses: ./.github/workflows/ksud.yml with: target: ${{ matrix.target }} @@ -56,17 +45,7 @@ jobs: with: fetch-depth: 0 - - name: Setup need_upload - id: need_upload - run: | - if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then - echo "UPLOAD=true" >> $GITHUB_OUTPUT - else - echo "UPLOAD=false" >> $GITHUB_OUTPUT - fi - - name: Write key - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }} run: | if [ ! -z "${{ secrets.KEYSTORE }}" ]; then { @@ -85,9 +64,10 @@ jobs: java-version: 21 - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 - with: - gradle-home-cache-cleanup: true + uses: gradle/actions/setup-gradle@v4 + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 - name: Download arm64 ksud uses: actions/download-artifact@v4 @@ -95,18 +75,10 @@ jobs: name: ksud-aarch64-linux-android path: . - - name: Download x86_64 ksud - uses: actions/download-artifact@v4 - with: - name: ksud-x86_64-linux-android - path: . - - name: Copy ksud to app jniLibs run: | mkdir -p app/src/main/jniLibs/arm64-v8a - mkdir -p app/src/main/jniLibs/x86_64 cp -f ../aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud.so - cp -f ../x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud.so - name: Build with Gradle run: | @@ -121,40 +93,12 @@ jobs: - name: Upload build artifact uses: actions/upload-artifact@v4 - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }} with: name: manager path: manager/app/build/outputs/apk/release/*.apk - name: Upload mappings uses: actions/upload-artifact@v4 - if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }} with: name: "mappings" path: "manager/app/build/outputs/mapping/release/" - - - name: Bot session cache - if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true' - id: bot_session_cache - uses: actions/cache@v4 - with: - path: scripts/ksubot.session - key: ${{ runner.os }}-bot-session - - - name: Upload to telegram - if: github.event_name != 'pull_request' && steps.need_upload.outputs.UPLOAD == 'true' - env: - CHAT_ID: ${{ secrets.CHAT_ID }} - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }} - COMMIT_MESSAGE: ${{ github.event.head_commit.message }} - COMMIT_URL: ${{ github.event.head_commit.url }} - RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - TITLE: Manager - run: | - if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then - export VERSION=$(git rev-list --count HEAD) - APK=$(find ./app/build/outputs/apk/release -name "*.apk") - pip3 install telethon - python3 $GITHUB_WORKSPACE/scripts/ksubot.py $APK - fi \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/build-su.yml b/drivers/staging/kernelsu/.github/workflows/build-su.yml index 2fbb93a9a485..25fc289858de 100644 --- a/drivers/staging/kernelsu/.github/workflows/build-su.yml +++ b/drivers/staging/kernelsu/.github/workflows/build-su.yml @@ -1,13 +1,13 @@ name: Build SU on: push: - branches: [ "main", "ci" ] + branches: [ "next" ] paths: - '.github/workflows/build-su.yml' - 'userspace/su/**' - 'scripts/ksubot.py' pull_request: - branches: [ "main" ] + branches: [ "next" ] paths: - 'userspace/su/**' jobs: @@ -26,14 +26,11 @@ jobs: else echo "UPLOAD=false" >> $GITHUB_OUTPUT fi - - uses: nttld/setup-ndk@v1 - with: - ndk-version: r26d - name: Build su working-directory: ./userspace/su - run: ndk-build + run: $ANDROID_NDK/ndk-build - name: Upload a Build Artifact uses: actions/upload-artifact@v4 with: name: su - path: ./userspace/su/libs \ No newline at end of file + path: ./userspace/su/libs diff --git a/drivers/staging/kernelsu/.github/workflows/clippy.yml b/drivers/staging/kernelsu/.github/workflows/clippy.yml index 2ea5bc48b5eb..30552d770b82 100644 --- a/drivers/staging/kernelsu/.github/workflows/clippy.yml +++ b/drivers/staging/kernelsu/.github/workflows/clippy.yml @@ -3,7 +3,7 @@ name: Clippy check on: push: branches: - - main + - next paths: - '.github/workflows/clippy.yml' - 'userspace/ksud/**' diff --git a/drivers/staging/kernelsu/.github/workflows/gki-kernel.yml b/drivers/staging/kernelsu/.github/workflows/gki-kernel.yml index a70977d9a9d4..6a96811f1197 100644 --- a/drivers/staging/kernelsu/.github/workflows/gki-kernel.yml +++ b/drivers/staging/kernelsu/.github/workflows/gki-kernel.yml @@ -84,7 +84,7 @@ jobs: - uses: actions/checkout@v4 with: - path: KernelSU + path: KernelSU-Next fetch-depth: 0 - name: Setup need_upload @@ -115,41 +115,41 @@ jobs: repo --trace sync -c -j$(nproc --all) --no-tags df -h - - name: Setup KernelSU + - name: Setup KernelSU-Next env: PATCH_PATH: ${{ inputs.patch_path }} IS_DEBUG_KERNEL: ${{ inputs.debug }} run: | cd $GITHUB_WORKSPACE/android-kernel - echo "[+] KernelSU setup" + echo "[+] KernelSU-Next setup" GKI_ROOT=$(pwd) echo "[+] GKI_ROOT: $GKI_ROOT" - echo "[+] Copy KernelSU driver to $GKI_ROOT/common/drivers" - ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu - echo "[+] Add KernelSU driver to Makefile" + echo "[+] Copy KernelSU-Next driver to $GKI_ROOT/common/drivers" + ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $GKI_ROOT/common/drivers/kernelsu + echo "[+] Add KernelSU-Next driver to Makefile" DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile DRIVER_KCONFIG=$GKI_ROOT/common/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 $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found" + echo "[+] Apply KernelSU-Next patches" + cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found" if [ "$IS_DEBUG_KERNEL" = "true" ]; then echo "[+] Enable debug features for kernel" - printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU/kernel/Makefile + printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU-Next/kernel/Makefile fi repo status - echo "[+] KernelSU setup done." + echo "[+] KernelSU-Next setup done." - name: Symbol magic run: | echo "[+] Export all symbol from abi_gki_aarch64.xml" COMMON_ROOT=$GITHUB_WORKSPACE/android-kernel/common - KSU_ROOT=$GITHUB_WORKSPACE/KernelSU + KSU_ROOT=$GITHUB_WORKSPACE/KernelSU-Next ABI_XML=$COMMON_ROOT/android/abi_gki_aarch64.xml SYMBOL_LIST=$COMMON_ROOT/android/abi_gki_aarch64 # python3 $KSU_ROOT/scripts/abi_gki_all.py $ABI_XML > $SYMBOL_LIST - echo "[+] Add KernelSU symbols" + echo "[+] Add KernelSU-Next symbols" cat $KSU_ROOT/kernel/export_symbol.txt | awk '{sub("[ \t]+","");print " "$0}' >> $SYMBOL_LIST - name: Setup ccache @@ -193,8 +193,8 @@ jobs: run: | rm common/android/abi_gki_protected_exports_* || echo "No protected exports!" git config --global user.email "bot@kernelsu.org" - git config --global user.name "KernelSUBot" - cd common/ && git add -A && git commit -a -m "Add KernelSU" + git config --global user.name "KernelSU-NextBot" + cd common/ && git add -A && git commit -a -m "Add KernelSU-Next" repo status - name: Build Kernel/LKM diff --git a/drivers/staging/kernelsu/.github/workflows/release.yml b/drivers/staging/kernelsu/.github/workflows/release.yml index 26b3171c8e68..c5923c6567ca 100644 --- a/drivers/staging/kernelsu/.github/workflows/release.yml +++ b/drivers/staging/kernelsu/.github/workflows/release.yml @@ -18,11 +18,8 @@ jobs: build-a14-kernel: uses: ./.github/workflows/build-kernel-a14.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 + build-a15-kernel: + uses: ./.github/workflows/build-kernel-a15.yml secrets: inherit release: needs: @@ -30,8 +27,6 @@ jobs: - build-a12-kernel - build-a13-kernel - build-a14-kernel - - build-wsa-kernel - - build-arcvm-kernel runs-on: ubuntu-latest steps: - name: Download artifacts @@ -45,24 +40,6 @@ 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 @@ -74,6 +51,4 @@ jobs: android*-lkm/*_kernelsu.ko AnyKernel3-*.zip boot-images-*/Image-*/*.img.gz - kernel-WSA*.zip - kernel-ARCVM*.zip - ksud-* + ksud-* \ No newline at end of file diff --git a/drivers/staging/kernelsu/.github/workflows/rustfmt.yml b/drivers/staging/kernelsu/.github/workflows/rustfmt.yml index 18a178b69eba..fb04ce8c8af3 100644 --- a/drivers/staging/kernelsu/.github/workflows/rustfmt.yml +++ b/drivers/staging/kernelsu/.github/workflows/rustfmt.yml @@ -3,13 +3,13 @@ name: Rustfmt check on: push: branches: - - 'main' + - 'next' paths: - '.github/workflows/rustfmt.yml' - 'userspace/ksud/**' pull_request: branches: - - 'main' + - 'next' paths: - '.github/workflows/rustfmt.yml' - 'userspace/ksud/**' diff --git a/drivers/staging/kernelsu/.github/workflows/shellcheck.yml b/drivers/staging/kernelsu/.github/workflows/shellcheck.yml index f864e05fa3a5..55ddfbfb12e9 100644 --- a/drivers/staging/kernelsu/.github/workflows/shellcheck.yml +++ b/drivers/staging/kernelsu/.github/workflows/shellcheck.yml @@ -3,13 +3,13 @@ name: ShellCheck on: push: branches: - - 'main' + - 'next' paths: - '.github/workflows/shellcheck.yml' - '**/*.sh' pull_request: branches: - - 'main' + - 'next' paths: - '.github/workflows/shellcheck.yml' - '**/*.sh' diff --git a/drivers/staging/kernelsu/README.md b/drivers/staging/kernelsu/README.md new file mode 100644 index 000000000000..a55bf52c5109 --- /dev/null +++ b/drivers/staging/kernelsu/README.md @@ -0,0 +1,49 @@ +# KernelSU Next + +logo + +A Kernel-based root solution for Android devices. + +[![Latest release](https://img.shields.io/github/v/release/rifsxd/KernelSU?label=Release&logo=github)](https://github.com/rifsxd/KernelSU/releases/latest) +[![Nightly Release](https://img.shields.io/badge/Nightly%20release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/rifsxd/KernelSU/workflows/build-manager/next/manager) +[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) +[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) + +## Features + +1. Kernel-based `su` and root access management. +2. Module system based on [Magic Mount](https://github.com/topjohnwu/Magisk/blob/c512496847d182526f2043295ecfd275398eccac/docs/releases/26100.md#new-magic-mount-implementation). +3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage. + +## Compatibility State + +KernelSU Next officially supports most Android kernels starting from 4.14 upto 6.6. + - GKI 2.0 (5.10+) kernels can run pre-built images and LKM/KMI. + - GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver. + - EOL (<4.19) kernels also need to be rebuilt with KernelSU driver. (3.18+ is experimental) + +Currently, only `arm64-v8a` is supported. + +## Usage + +- [Installation Instruction](https://kernelsu.org/guide/installation.html) +- [How to build?](https://kernelsu.org/guide/how-to-build.html) +- [Official Website](https://kernelsu.org/) + +## Security + +For information on reporting security vulnerabilities in KernelSU, see [SECURITY.md](/SECURITY.md). + +## License + +- Files under the `kernel` directory are [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). +- All other parts except the `kernel` directory are [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html). + +## Credits + +- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): the KernelSU idea. +- [Magisk](https://github.com/topjohnwu/Magisk): the powerful root tool. +- [genuine](https://github.com/brevent/genuine/): apk v2 signature validation. +- [Diamorphine](https://github.com/m0nad/Diamorphine): some rootkit skills. +- [KernelSU](https://github.com/tiann/KernelSU): thanks to tiann or else KernelSU Next wouldn't even exist. +- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff for saving KernelSU! diff --git a/drivers/staging/kernelsu/assets/kernelsu_next.png b/drivers/staging/kernelsu/assets/kernelsu_next.png new file mode 100755 index 000000000000..d27020a106ec Binary files /dev/null and b/drivers/staging/kernelsu/assets/kernelsu_next.png differ diff --git a/drivers/staging/kernelsu/docs/README.md b/drivers/staging/kernelsu/docs/README.md deleted file mode 100644 index 0128cd3d221e..000000000000 --- a/drivers/staging/kernelsu/docs/README.md +++ /dev/null @@ -1,57 +0,0 @@ -**English** | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -A Kernel-based root solution for Android devices. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Features - -1. Kernel-based `su` and root access management. -2. Module system based on [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage. - -## Compatibility State - -KernelSU officially supports Android GKI 2.0 devices (kernel 5.10+). Older kernels (4.14+) are also compatible, but the kernel will have to be built manually. - -With this, WSA, ChromeOS, and container-based Android are all supported. - -Currently, only `arm64-v8a` and `x86_64` are supported. - -## Usage - -- [Installation Instruction](https://kernelsu.org/guide/installation.html) -- [How to build?](https://kernelsu.org/guide/how-to-build.html) -- [Official Website](https://kernelsu.org/) - -## Translation - -To help translate KernelSU or improve existing translations, please use [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR of Manager's translation is no longer accepted, because it will conflict with Weblate. - -## Discussion - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Security - -For information on reporting security vulnerabilities in KernelSU, see [SECURITY.md](/SECURITY.md). - -## License - -- Files under the `kernel` directory are [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- All other parts except the `kernel` directory are [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Credits - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): the KernelSU idea. -- [Magisk](https://github.com/topjohnwu/Magisk): the powerful root tool. -- [genuine](https://github.com/brevent/genuine/): apk v2 signature validation. -- [Diamorphine](https://github.com/m0nad/Diamorphine): some rootkit skills. diff --git a/drivers/staging/kernelsu/docs/README_CN.md b/drivers/staging/kernelsu/docs/README_CN.md deleted file mode 100644 index dc34b86ab139..000000000000 --- a/drivers/staging/kernelsu/docs/README_CN.md +++ /dev/null @@ -1,57 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | **简体中文** | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -一个 Android 上基于内核的 root 方案。 - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## 特性 - -- 基于内核的 `su` 和权限管理。 -- 基于 [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模块系统。 -- [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html): 把 Root 权限关进笼子里。 - -## 兼容状态 - -KernelSU 官方支持 GKI 2.0 的设备(内核版本5.10以上);旧内核也是兼容的(最低4.14+),不过需要自己编译内核。 - -WSA, ChromeOS 和运行在容器上的 Android 也可以与 KernelSU 一起工作。 - -目前支持架构 : `arm64-v8a` 和 `x86_64`。 - -## 使用方法 - -- [安装教程](https://kernelsu.org/zh_CN/guide/installation.html) -- [如何构建?](https://kernelsu.org/zh_CN/guide/how-to-build.html) -- [官方网站](https://kernelsu.org/zh_CN/) - -## 参与翻译 - -要将 KernelSU 翻译成您的语言,或完善现有的翻译,请使用 [Weblate](https://hosted.weblate.org/engage/kernelsu/)。现已不再接受有关管理器翻译的PR,因为这会与Weblate冲突。 - -## 讨论 - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## 安全性 - -有关报告 KernelSU 安全漏洞的信息,请参阅 [SECURITY.md](/SECURITY.md)。 - -## 许可证 - -- 目录 `kernel` 下所有文件为 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。 -- 除 `kernel` 目录的其他部分均为 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。 - -## 鸣谢 - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU 的灵感。 -- [Magisk](https://github.com/topjohnwu/Magisk):强大的 root 工具箱。 -- [genuine](https://github.com/brevent/genuine/):apk v2 签名验证。 -- [Diamorphine](https://github.com/m0nad/Diamorphine):一些 rootkit 技巧。 diff --git a/drivers/staging/kernelsu/docs/README_ES.md b/drivers/staging/kernelsu/docs/README_ES.md deleted file mode 100644 index ed4f699b791d..000000000000 --- a/drivers/staging/kernelsu/docs/README_ES.md +++ /dev/null @@ -1,56 +0,0 @@ -[English](README.md) | **Español** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Una solución root basada en el kernel para dispositivos Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localización-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Seguir-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/Licencia-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Características - -1. Binario `su` basado en el kernel y gestión de acceso root. -2. Sistema de módulos basado en [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). - -## Estado de compatibilidad - -**KernelSU** soporta de forma oficial dispositivos Android con **GKI 2.0** (a partir de la versión **5.10** del kernel). Los kernels antiguos (a partir de la versión **4.14**) también son compatibles, pero necesitas compilarlos por tu cuenta. - -Con esto, WSA, ChromeOS y Android basado en contenedores están todos compatibles. - -Actualmente, solo se admiten las arquitecturas `arm64-v8a` y `x86_64`. - -## Uso - -- [¿Cómo instalarlo?](https://kernelsu.org/guide/installation.html) -- [¿Cómo compilarlo?](https://kernelsu.org/guide/how-to-build.html) -- [Site oficial](https://kernelsu.org/) - -## Traducción - -Para ayudar a traducir KernelSU o mejorar las traducciones existentes, utilice [Weblate](https://hosted.weblate.org/engage/kernelsu/). Ya no se aceptan PR de la traducción de Manager porque entrará en conflicto con Weblate. - -## Discusión - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Seguridad - -Para obtener información sobre cómo informar vulnerabilidades de seguridad en KernelSU, consulte [SECURITY.md](/SECURITY.md). - -## Licencia - -- Los archivos bajo el directorio `kernel` están licenciados bajo [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Todas las demás partes, a excepción del directorio `kernel`, están licenciados bajo [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Créditos - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): la idea de KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): la poderosa herramienta root. -- [genuine](https://github.com/brevent/genuine/): validación de firma apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): algunas habilidades de rootkit. diff --git a/drivers/staging/kernelsu/docs/README_ID.md b/drivers/staging/kernelsu/docs/README_ID.md deleted file mode 100644 index 511683a7503d..000000000000 --- a/drivers/staging/kernelsu/docs/README_ID.md +++ /dev/null @@ -1,53 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | **Indonesia** | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Solusi root berbasis Kernel untuk perangkat Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Fitur - -1. Manajemen akses root dan `su` berbasis kernel. -2. Sistem modul berdasarkan [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [Profil Aplikasi](https://kernelsu.org/guide/app-profile.html): Kunci daya root di dalam sangkar. - -## Status Kompatibilitas - -KernelSU secara resmi mendukung perangkat Android GKI 2.0 (dengan kernel 5.10+), kernel lama (4.14+) juga kompatibel, tetapi Anda perlu membuat kernel sendiri. - -WSA, ChromeOS, dan Android berbasis wadah juga dapat bekerja dengan KernelSU terintegrasi. - -Dan ABI yang didukung saat ini adalah: `arm64-v8a` dan `x86_64` - -## Penggunaan - -- [Petunjuk Instalasi](https://kernelsu.org/id_ID/guide/installation.html) -- [Bagaimana cara membuat?](https://kernelsu.org/id_ID/guide/how-to-build.html) -- [Situs Web Resmi](https://kernelsu.org/id_ID/) - -## Terjemahan - -Untuk menerjemahkan KernelSU ke dalam bahasa Anda atau menyempurnakan terjemahan yang sudah ada, harap gunakan [Weblat](https://hosted.weblate.org/engage/kernelsu/). - -## Diskusi - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Lisensi - -- File di bawah direktori `kernel` adalah [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Semua bagian lain kecuali direktori `kernel` adalah [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Kredit - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ide KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): alat root yang ampuh. -- [genuine](https://github.com/brevent/genuine/): validasi tanda tangan apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): beberapa keterampilan rootkit. diff --git a/drivers/staging/kernelsu/docs/README_IN.md b/drivers/staging/kernelsu/docs/README_IN.md deleted file mode 100644 index 7396ab5c2b10..000000000000 --- a/drivers/staging/kernelsu/docs/README_IN.md +++ /dev/null @@ -1,53 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | **हिंदी** - -# KernelSU - -logo - -Android उपकरणों के लिए कर्नेल-आधारित रूट समाधान। - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## विशेषताएँ - -1. कर्नेल-आधारित `su` और रूट एक्सेस प्रबंधन। -2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) पर आधारित मॉड्यूल प्रणाली। -3. [App Profile](https://kernelsu.org/guide/app-profile.html): Root शक्ति को पिंजरे में बंद कर दो। - -## अनुकूलता अवस्था - -KernelSU आधिकारिक तौर पर Android GKI 2.0 डिवाइस (कर्नेल 5.10+) का समर्थन करता है। पुराने कर्नेल (4.14+) भी संगत हैं, लेकिन कर्नेल को मैन्युअल रूप से बनाना होगा। - -इसके साथ, WSA, ChromeOS और कंटेनर-आधारित Android सभी समर्थित हैं। - -वर्तमान में, केवल `arm64-v8a` और `x86_64` समर्थित हैं। - -## प्रयोग - -- [स्थापना निर्देश](https://kernelsu.org/guide/installation.html) -- [कैसे बनाना है ?](https://kernelsu.org/guide/how-to-build.html) -- [आधिकारिक वेबसाइट](https://kernelsu.org/) - -## अनुवाद करना - -KernelSU का अनुवाद करने या मौजूदा अनुवादों को बेहतर बनाने में सहायता के लिए, कृपया इसका उपयोग करें [Weblate](https://hosted.weblate.org/engage/kernelsu/). - -## बहस - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## लाइसेंस - -- `Kernel` निर्देशिका के अंतर्गत फ़ाइलें हैं [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -- `Kernel` निर्देशिका को छोड़कर अन्य सभी भाग हैं [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html) - -## आभार सूची - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU विचार। -- [Magisk](https://github.com/topjohnwu/Magisk): शक्तिशाली root उपकरण। -- [genuine](https://github.com/brevent/genuine/): apk v2 हस्ताक्षर सत्यापन। -- [Diamorphine](https://github.com/m0nad/Diamorphine): कुछ रूटकिट कौशल। diff --git a/drivers/staging/kernelsu/docs/README_IW.md b/drivers/staging/kernelsu/docs/README_IW.md deleted file mode 100644 index 5997487e2a08..000000000000 --- a/drivers/staging/kernelsu/docs/README_IW.md +++ /dev/null @@ -1,53 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | **עברית** | [हिंदी](README_IN.md) - -# KernelSU - -logo - -פתרון לניהול root מבוסס על Kernel עבור מכשירי Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## תכונות - -1. ניהול root ו־`su` מבוססים על Kernel. -2. מערכת מודולים מבוססת [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [פרופיל אפליקציה](https://kernelsu.org/guide/app-profile.html): נעילת גישת root בכלוב. - -## מצב תאימות - -KernelSU תומך במכשירי Android GKI 2.0 (kernel 5.10+) באופן רשמי. לליבות ישנות (4.14+) יש גם תאימות, אך יידרש לבנות את הליבה באופן ידני. - -באמצעות זה, תמיכה זמינה גם ל-WSA, ChromeOS ומכשירי Android המבוססים על מיכלים. - -כרגע, רק `arm64-v8a` ו־`x86_64` נתמכים. - -## שימוש - -- [הוראות התקנה](https://kernelsu.org/guide/installation.html) -- [איך לבנות?](https://kernelsu.org/guide/how-to-build.html) -- [האתר רשמי](https://kernelsu.org/) - -## תרגום - -כדי לעזור בתרגום של KernelSU או לשפר תרגומים קיימים, יש להשתמש ב-[Weblate](https://hosted.weblate.org/engage/kernelsu/). - -## דיון - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## רשיון - -- קבצים תחת הספרייה `kernel` מוגנים על פי [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- כל החלקים האחרים, למעט הספרייה `kernel`, מוגנים על פי [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## קרדיטים - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): הרעיון של KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): הכלי הסופר חזק לניהול root. -- [genuine](https://github.com/brevent/genuine/): אימות חתימת apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): כמה יכולות רוט. diff --git a/drivers/staging/kernelsu/docs/README_JP.md b/drivers/staging/kernelsu/docs/README_JP.md deleted file mode 100644 index 093618753775..000000000000 --- a/drivers/staging/kernelsu/docs/README_JP.md +++ /dev/null @@ -1,53 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **日本語** | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Android におけるカーネルベースの root ソリューションです。 - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## 特徴 - -1. カーネルベースの `su` と権限管理。 -2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) に基づくモジュールシステム。 -3. [アプリのプロファイル](https://kernelsu.org/guide/app-profile.html): root の権限をケージ内に閉じ込めます。 - -## 対応状況 - -KernelSU は GKI 2.0 デバイス(カーネルバージョン 5.10 以上)を公式にサポートしています。古いカーネル(4.14以上)とも互換性がありますが、自分でカーネルをビルドする必要があります。 - -WSA 、ChromeOS とコンテナ上で動作する Android でも KernelSU を統合して動かせます。 - -現在サポートしているアーキテクチャは `arm64-v8a` および `x86_64` です。 - -## 使用方法 - -- [インストール方法はこちら](https://kernelsu.org/ja_JP/guide/installation.html) -- [ビルド方法はこちら](https://kernelsu.org/guide/how-to-build.html) -- [公式サイト](https://kernelsu.org/ja_JP/) - -## 翻訳 - -KernelSU をあなたの言語に翻訳するか、既存の翻訳を改善するには、[Weblate](https://hosted.weblate.org/engage/kernelsu/) を使用してください。Manager翻訳した PR は、Weblate と競合するため受け入れられなくなりました。 - -## ディスカッション - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## ライセンス - -- `kernel` ディレクトリの下にあるすべてのファイル: [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。 -- `kernel` ディレクトリ以外のすべてのファイル: [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。 - -## クレジット - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU のアイデア元。 -- [Magisk](https://github.com/topjohnwu/Magisk):強力な root ツール。 -- [genuine](https://github.com/brevent/genuine/):apk v2 の署名検証。 -- [Diamorphine](https://github.com/m0nad/Diamorphine): rootkit のスキル。 diff --git a/drivers/staging/kernelsu/docs/README_KR.md b/drivers/staging/kernelsu/docs/README_KR.md deleted file mode 100644 index 3226008920a1..000000000000 --- a/drivers/staging/kernelsu/docs/README_KR.md +++ /dev/null @@ -1,57 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | **한국어** | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -안드로이드 기기에서 사용되는 커널 기반 루팅 솔루션입니다. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## 기능들 - -1. 커널 기반 `su` 및 루트 액세스 관리. -2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 기반 모듈 시스템. -3. [App Profile](https://kernelsu.org/guide/app-profile.html): 루트 권한을 케이지에 가둡니다. - -## 호환 상태 - -KernelSU는 공식적으로 안드로이드 GKI 2.0 디바이스(커널 5.10 이상)를 지원합니다. 오래된 커널(4.14 이상)도 사용할 수 있지만, 커널을 수동으로 빌드해야 합니다. - -KernelSU는 WSA, ChromeOS, 컨테이너 기반 안드로이드 모두를 지원합니다. - -현재는 `arm64-v8a`와 `x86_64`만 지원됩니다. - -## 사용 방법 - -- [설치 방법](https://kernelsu.org/guide/installation.html) -- [어떻게 빌드하나요?](https://kernelsu.org/guide/how-to-build.html) -- [공식 웹사이트](https://kernelsu.org/) - -## 번역 - -KernelSU 번역을 돕거나 기존 번역을 개선하려면 [Weblate](https://hosted.weblate.org/engage/kernelsu/)를 이용해 주세요. 매니저의 번역은 Weblate와 충돌할 수 있으므로 더 이상 허용되지 않습니다. - -## 토론 - -- 텔레그램: [@KernelSU](https://t.me/KernelSU) - -## 보안 - -KernelSU의 보안 취약점 보고에 대한 자세한 내용은 [SECURITY.md](/SECURITY.md)를 참조하세요. - -## 저작권 - -- `kernel` 디렉터리 아래의 파일은 [GPL-2.0 전용](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)입니다. -- `kernel` 디렉토리를 제외한 다른 모든 부분은 [GPL-3.0-이상](https://www.gnu.org/licenses/gpl-3.0.html)입니다. - -## 크래딧 - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU의 아이디어. -- [Magisk](https://github.com/topjohnwu/Magisk): 강력한 루팅 도구. -- [genuine](https://github.com/brevent/genuine/): apk v2 서명 유효성 검사. -- [Diamorphine](https://github.com/m0nad/Diamorphine): 일부 rootkit 스킬. diff --git a/drivers/staging/kernelsu/docs/README_PL.md b/drivers/staging/kernelsu/docs/README_PL.md deleted file mode 100644 index ab9066296dd9..000000000000 --- a/drivers/staging/kernelsu/docs/README_PL.md +++ /dev/null @@ -1,55 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | **Polski** | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Rozwiązanie root oparte na jądrze dla urządzeń z systemem Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Cechy - -1. Oparte na jądrze `su` i zarządzanie dostępem roota. -2. System modułów oparty na [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). - -## Kompatybilność - -KernelSU oficjalnie obsługuje urządzenia z Androidem GKI 2.0 (z jądrem 5.10+), starsze jądra (4.14+) są również kompatybilne, ale musisz sam skompilować jądro. - -WSA i Android oparty na kontenerach również powinny działać ze zintegrowanym KernelSU. - -Aktualnie obsługiwane ABI to : `arm64-v8a` i `x86_64`. - -## Użycie - -- [Instalacja](https://kernelsu.org/guide/installation.html) -- [Jak skompilować?](https://kernelsu.org/guide/how-to-build.html) - -## Tłumaczenie - -Aby pomóc w tłumaczeniu KernelSU lub ulepszyć istniejące tłumaczenia, użyj [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR tłumaczenia Managera nie jest już akceptowany, ponieważ będzie kolidował z Weblate. - -## Dyskusja - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Bezpieczeństwo - -Informacje na temat zgłaszania luk w zabezpieczeniach w KernelSU można znaleźć w pliku [SECURITY.md](/SECURITY.md). - -## Licencja - -- Pliki w katalogu `kernel` są na licencji [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Wszystkie inne części poza katalogiem `kernel` są na licencji [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Podziękowania - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): pomysłodawca KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): implementacja sepolicy. -- [genuine](https://github.com/brevent/genuine/): walidacja podpisu apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): cenna znajomość rootkitów. diff --git a/drivers/staging/kernelsu/docs/README_PT-BR.md b/drivers/staging/kernelsu/docs/README_PT-BR.md deleted file mode 100644 index b5421e7f9be0..000000000000 --- a/drivers/staging/kernelsu/docs/README_PT-BR.md +++ /dev/null @@ -1,57 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | **Português (Brasil)** | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Uma solução root baseada em kernel para dispositivos Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localização-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Seguir-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/Licença-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Características - -1. `su` e gerenciamento de acesso root baseado em kernel. -2. Sistema modular baseado em [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [Perfil do Aplicativo](https://kernelsu.org/pt_BR/guide/app-profile.html): Tranque o poder root em uma gaiola. - -## Estado de compatibilidade - -O KernelSU oferece suporte oficial a dispositivos Android GKI 2.0 (kernel 5.10+). Kernels mais antigos (4.14+) também são compatíveis, mas o kernel terá que ser construído manualmente. - -Com isso, WSA, ChromeOS e Android baseado em contêiner são todos suportados. - -Atualmente, apenas `arm64-v8a` e `x86_64` são suportados. - -## Uso - - - [Instalação](https://kernelsu.org/pt_BR/guide/installation.html) - - [Como compilar o KernelSU?](https://kernelsu.org/pt_BR/guide/how-to-build.html) - - [Site oficial](https://kernelsu.org/pt_BR/) - -## Tradução - -Para contribuir com a tradução do KernelSU ou aprimorar traduções existentes, por favor, utilize o [Weblate](https://hosted.weblate.org/engage/kernelsu/). PR para a tradução do Gerenciador não são mais aceitas, pois podem entrar em conflito com o Weblate. - -## Discussão - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Segurança - -Para obter informações sobre como relatar vulnerabilidades de segurança do KernelSU, consulte [SECURITY.md](/SECURITY.md). - -## Licença - -- Os arquivos no diretório `kernel` são [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Todas as outras partes, exceto o diretório `kernel` são [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Créditos - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): a ideia do KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): a poderosa ferramenta root. -- [genuine](https://github.com/brevent/genuine/): validação de assinatura apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): algumas habilidades de rootkit. diff --git a/drivers/staging/kernelsu/docs/README_RU.md b/drivers/staging/kernelsu/docs/README_RU.md deleted file mode 100644 index 7e50f47adfe5..000000000000 --- a/drivers/staging/kernelsu/docs/README_RU.md +++ /dev/null @@ -1,49 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | **Русский** | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Решение на основе ядра root для Android-устройств. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Особенности - -1. Управление `su` и root-доступом на основе ядра. -2. Система модулей на основе [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [Профиль приложений](https://kernelsu.org/ru_RU/guide/app-profile.html): Запри корневую силу в клетке. - -## Совместимость - -KernelSU официально поддерживает устройства на базе Android GKI 2.0 (с ядром 5.10+), старые ядра (4.14+) также совместимы, но для этого необходимо собрать ядро самостоятельно. - -WSA и Android на основе контейнеров также должны работать с интегрированным KernelSU. - -В настоящее время поддерживаются следующие ABI: `arm64-v8a` и `x86_64`. - -## Использование - -- [Установка](https://kernelsu.org/ru_RU/guide/installation.html) -- [Как собрать?](https://kernelsu.org/ru_RU/guide/how-to-build.html) -- [официальный сайт](https://kernelsu.org/ru_RU/) - -## Обсуждение - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Лицензия - -- Файлы в директории `kernel` [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Все остальные части, кроме директории `kernel` [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Благодарности - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): идея KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): реализация sepolicy. -- [genuine](https://github.com/brevent/genuine/): проверка подписи apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): некоторые навыки руткита. diff --git a/drivers/staging/kernelsu/docs/README_TR.md b/drivers/staging/kernelsu/docs/README_TR.md deleted file mode 100644 index bc3363e8b490..000000000000 --- a/drivers/staging/kernelsu/docs/README_TR.md +++ /dev/null @@ -1,57 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | **Türkçe** | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Android cihazlar için kernel tabanlı root çözümü. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Özellikler - -1. Kernel-tabanlı `su` ve root erişimi yönetimi. -2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS)'ye dayalı modül sistemi. -3. [Uygulama profili](https://kernelsu.org/guide/app-profile.html): Root gücünü bir kafese kapatın. - -## Uyumluluk Durumu - -KernelSU resmi olarak Android GKI 2.0 cihazlarını (5.10+ kernelli) destekler, eski kernellerle de (4.14+) uyumludur, ancak kerneli kendinizin derlemeniz gerekir. - -Bununla birlikte; WSA, ChromeOS ve konteyner tabanlı Android'in tamamı desteklenmektedir. - -Şimdilik sadece `arm64-v8a` ve `x86_64` desteklenmektedir. - -## Kullanım - -- [Yükleme yönergeleri](https://kernelsu.org/guide/installation.html) -- [Nasıl derlenir?](https://kernelsu.org/guide/how-to-build.html) -- [Resmi WEB sitesi](https://kernelsu.org/) - -## Çeviri - -KernelSU'nun başka dillere çevrilmesine veya mevcut çevirilerin iyileştirilmesine yardımcı olmak için lütfen [Weblate](https://hosted.weblate.org/engage/kernelsu/) kullanın. Yönetici uygulamasının PR ile çevirisi, Weblate ile çakışacağından artık kabul edilmeyecektir. - -## Tartışma - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Güvenlik - -KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için, bkz [SECURITY.md](/SECURITY.md). - -## Lisans - -- `kernel` klasöründeki dosyalar [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır. -- `kernel` klasörü dışındaki bütün diğer bölümler [GPL-3-veya-sonraki](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır. - -## Krediler - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri. -- [Magisk](https://github.com/topjohnwu/Magisk): güçlü root aracı. -- [genuine](https://github.com/brevent/genuine/): apk v2 imza doğrulaması. -- [Diamorphine](https://github.com/m0nad/Diamorphine): bazı rootkit becerileri. diff --git a/drivers/staging/kernelsu/docs/README_TW.md b/drivers/staging/kernelsu/docs/README_TW.md deleted file mode 100644 index d025e1742a67..000000000000 --- a/drivers/staging/kernelsu/docs/README_TW.md +++ /dev/null @@ -1,56 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | **繁體中文** | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | [Tiếng Việt](README_VI.md) | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -一個基於核心的 Android 裝置 Root 解決方案 - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## 功能 - -- 基於核心的 `su` 和 Root 存取權管理。 -- 基於 [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) 的模組系統。 -- [App Profile](https://kernelsu.org/zh_TW/guide/app-profile.html): 將 Root 的權限鎖在牢籠中. - -## 相容性狀態 - -KernelSU 官方支援 Android GKI 2.0 的裝置 (核心版本 5.10+ );舊版核心同樣相容 (最低 4.14+ ),但需要自行編譯核心。 - -WSA和ChromeOS和執行在容器中的 Android 也可以與 KernelSU 一同運作。 - -目前支援架構:`arm64-v8a` 和 `x86_64`。 - -## 使用方法 - -- [安裝教學](https://kernelsu.org/zh_TW/guide/installation.html) -- [如何建置?](https://kernelsu.org/zh_TW/guide/how-to-build.html) -- [官方網站](https://kernelsu.org/zh_TW/) - -## 翻譯 - -若要協助翻譯 KernelSU 或改進現有翻譯,請使用 [Weblate](https://hosted.weblate.org/engage/kernelsu/)。 翻譯管理器的PR不再被接受,因為它會與Weblate衝突。 - -### 討論 - -- Telegram:[@KernelSU](https://t.me/KernelSU) - -## 安全 -有關報告 KernelSU 中的安全漏洞的資訊,請參閱 [SECURITY.md](/SECURITY.md)。 - -## 授權 - -- 目錄 `kernel` 下所有檔案為 [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。 -- 除 `kernel` 目錄的其他部分均為 [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。 - -## 致謝 - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/):KernelSU 的靈感。 -- [Magisk](https://github.com/topjohnwu/Magisk):sepolicy 實作。 -- [genuine](https://github.com/brevent/genuine/):apk v2 簽章驗證。 -- [Diamorphine](https://github.com/m0nad/Diamorphine):一些 rootkit 技巧。 diff --git a/drivers/staging/kernelsu/docs/README_VI.md b/drivers/staging/kernelsu/docs/README_VI.md deleted file mode 100644 index 7dd3b4227aec..000000000000 --- a/drivers/staging/kernelsu/docs/README_VI.md +++ /dev/null @@ -1,53 +0,0 @@ -[English](README.md) | [Español](README_ES.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [日本語](README_JP.md) | [한국어](README_KR.md) | [Polski](README_PL.md) | [Português (Brasil)](README_PT-BR.md) | [Türkçe](README_TR.md) | [Русский](README_RU.md) | **Tiếng Việt** | [Indonesia](README_ID.md) | [עברית](README_IW.md) | [हिंदी](README_IN.md) - -# KernelSU - -logo - -Giải pháp root thông qua thay đổi trên Kernel hệ điều hành cho các thiết bị Android. - -[![Latest release](https://img.shields.io/github/v/release/tiann/KernelSU?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest) -[![Weblate](https://img.shields.io/badge/Localization-Weblate-teal?logo=weblate)](https://hosted.weblate.org/engage/kernelsu) -[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/KernelSU) -[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) -[![GitHub License](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE) - -## Tính năng - -1. Hỗ trợ gói thực thi `su` và quản lý quyền root. -2. Hệ thống mô-đun thông qua [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). -3. [App Profile](https://kernelsu.org/guide/app-profile.html): Hạn chế quyền root của ứng dụng. - -## Tình trạng tương thích - -KernelSU chính thức hỗ trợ các thiết bị Android với kernel GKI 2.0 (phiên bản kernel 5.10+), các phiên bản kernel cũ hơn (4.14+) cũng tương thích, nhưng bạn cần phải tự biên dịch. - -WSA, ChromeOS và Android dựa trên container(container-based) cũng được hỗ trợ bởi KernelSU. - -Hiên tại Giao diện nhị phân của ứng dụng (ABI) được hỗ trợ bao gồm `arm64-v8a` và `x86_64`. - -## Sử dụng - -- [Hướng dẫn cài đặt](https://kernelsu.org/vi_VN/guide/installation.html) -- [Cách để build?](https://kernelsu.org/vi_VN/guide/how-to-build.html) -- [Website Chính Thức](https://kernelsu.org/vi_VN/) - -## Hỗ trợ dịch - -Nếu bạn muốn hỗ trợ dịch KernelSU sang một ngôn ngữ khác hoặc cải thiện các bản dịch trước, vui lòng sử dụng [Weblate](https://hosted.weblate.org/engage/kernelsu/). - -## Thảo luận - -- Telegram: [@KernelSU](https://t.me/KernelSU) - -## Giấy phép - -- Tất cả các file trong thư mục `kernel` dùng giấy phép [GPL-2-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html). -- Tất cả các thành phần khác ngoại trừ thư mục `kernel` dùng giấy phép [GPL-3-or-later](https://www.gnu.org/licenses/gpl-3.0.html). - -## Lời cảm ơn - -- [kernel-assisted-superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): ý tưởng cho KernelSU. -- [Magisk](https://github.com/topjohnwu/Magisk): công cụ root mạnh mẽ. -- [genuine](https://github.com/brevent/genuine/): phương pháp xác thực apk v2. -- [Diamorphine](https://github.com/m0nad/Diamorphine): các phương pháp ẩn của rootkit. diff --git a/drivers/staging/kernelsu/js/README.md b/drivers/staging/kernelsu/js/README.md index 4af3a7185863..91de2b45b9c6 100644 --- a/drivers/staging/kernelsu/js/README.md +++ b/drivers/staging/kernelsu/js/README.md @@ -109,3 +109,12 @@ Show a toast message. import { toast } from 'kernelsu'; toast('Hello, world!'); ``` + +### moduleInfo + +Get Module info. +```javascript +import { moduleInfo } from 'kernelsu'; +// print moduleId in console +console.log(moduleInfo()); +``` \ No newline at end of file diff --git a/drivers/staging/kernelsu/js/index.d.ts b/drivers/staging/kernelsu/js/index.d.ts index b65248e378f7..c9278175c891 100644 --- a/drivers/staging/kernelsu/js/index.d.ts +++ b/drivers/staging/kernelsu/js/index.d.ts @@ -37,9 +37,12 @@ declare function fullScreen(isFullScreen: boolean); declare function toast(message: string); +declare function moduleInfo(): string; + export { exec, spawn, fullScreen, - toast + toast, + moduleInfo } diff --git a/drivers/staging/kernelsu/js/index.js b/drivers/staging/kernelsu/js/index.js index 4b64e9c4c455..29b928acd6f1 100644 --- a/drivers/staging/kernelsu/js/index.js +++ b/drivers/staging/kernelsu/js/index.js @@ -113,3 +113,7 @@ export function fullScreen(isFullScreen) { export function toast(message) { ksu.toast(message); } + +export function moduleInfo() { + return ksu.moduleInfo(); +} diff --git a/drivers/staging/kernelsu/js/package.json b/drivers/staging/kernelsu/js/package.json index 02b350f33c79..12002a05328e 100644 --- a/drivers/staging/kernelsu/js/package.json +++ b/drivers/staging/kernelsu/js/package.json @@ -1,6 +1,6 @@ { "name": "kernelsu", - "version": "1.0.6", + "version": "1.0.7", "description": "Library for KernelSU's module WebUI", "main": "index.js", "types": "index.d.ts", diff --git a/drivers/staging/kernelsu/kernel/Kconfig b/drivers/staging/kernelsu/kernel/Kconfig index 67f177f4708a..1f3802f6decc 100644 --- a/drivers/staging/kernelsu/kernel/Kconfig +++ b/drivers/staging/kernelsu/kernel/Kconfig @@ -16,4 +16,12 @@ config KSU_DEBUG help Enable KernelSU debug mode. +config KSU_ALLOWLIST_WORKAROUND + bool "KernelSU Session Keyring Init workaround" + depends on KSU + default n + help + Enable session keyring init workaround for problematic devices. + Useful for situations where the SU allowlist is not kept after a reboot. + endmenu diff --git a/drivers/staging/kernelsu/kernel/Makefile b/drivers/staging/kernelsu/kernel/Makefile index d277c5bc3b01..04d0899d7837 100644 --- a/drivers/staging/kernelsu/kernel/Makefile +++ b/drivers/staging/kernelsu/kernel/Makefile @@ -25,7 +25,7 @@ $(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200)) $(info -- KernelSU version: $(KSU_VERSION)) ccflags-y += -DKSU_VERSION=$(KSU_VERSION) else # If there is no .git file, the default version will be passed. -KSU_GIT_VERSION := 1672 +KSU_GIT_VERSION := 1869 $(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200)) ccflags-y += -DKSU_VERSION=$(KSU_VERSION) endif @@ -46,6 +46,15 @@ ifndef KSU_EXPECTED_HASH KSU_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6 endif +ifndef KSU_NEXT_EXPECTED_SIZE +KSU_NEXT_EXPECTED_SIZE := 0x3e6 +endif + +ifndef KSU_NEXT_EXPECTED_HASH +KSU_NEXT_EXPECTED_HASH := 79e590113c4c4c0c222978e413a5faa801666957b1212a328e46c00c69821bf7 +endif + + ifdef KSU_MANAGER_PACKAGE ccflags-y += -DKSU_MANAGER_PACKAGE=\"$(KSU_MANAGER_PACKAGE)\" $(info -- KernelSU Manager package name: $(KSU_MANAGER_PACKAGE)) @@ -54,14 +63,58 @@ endif # $(info -- KernelSU Manager signature size: $(KSU_EXPECTED_SIZE)) # $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH)) +$(info -- KernelSU next Manager signature size: $(KSU_NEXT_EXPECTED_SIZE)) +$(info -- KernelSU next Manager signature hash: $(KSU_NEXT_EXPECTED_HASH)) + ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" -ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0) +ccflags-y += -DEXPECTED_NEXT_SIZE=$(KSU_NEXT_EXPECTED_SIZE) +ccflags-y += -DEXPECTED_NEXT_HASH=\"$(KSU_NEXT_EXPECTED_HASH)\" + ccflags-y += -DKSU_UMOUNT -else -$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?) -$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount) + +ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0) +$(info -- KSU_NEXT: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c) +CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\ +{\n\t\ + struct mount *mnt = real_mount(path->mnt);\n\t\ + if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))\n\t\t\ + return -EINVAL;\n\t\ + if (!may_mount())\n\t\t\ + return -EPERM;\n\t\ + if (path->dentry != path->mnt->mnt_root)\n\t\t\ + return -EINVAL;\n\t\ + if (!check_mnt(mnt))\n\t\t\ + return -EINVAL;\n\t\ + if (mnt->mnt.mnt_flags & MNT_LOCKED)\n\t\t\ + return -EINVAL;\n\t\ + if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))\n\t\t\ + return -EPERM;\n\t\ + return 0;\n\ +}\n +$(shell sed -i '/^static bool is_mnt_ns_file/i $(CAN_UMOUNT)' $(srctree)/fs/namespace.c;) +endif + +ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/namespace.c; echo $$?),0) +$(info -- KSU_NEXT: adding function 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/namespace.c) +PATH_UMOUNT = int path_umount(struct path *path, int flags)\n\ +{\n\t\ + struct mount *mnt = real_mount(path->mnt);\n\t\ + int ret;\n\t\ + ret = can_umount(path, flags);\n\t\ + if (!ret)\n\t\t\ + ret = do_umount(mnt, flags);\n\t\ + dput(path->dentry);\n\t\ + mntput_no_expire(mnt);\n\t\ + return ret;\n\ +}\n +$(shell sed -i '/^static bool is_mnt_ns_file/i $(PATH_UMOUNT)' $(srctree)/fs/namespace.c;) +endif + +ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/internal.h; echo $$?),0) +$(shell sed -i '/^extern void __init mnt_init/a int path_umount(struct path *path, int flags);' $(srctree)/fs/internal.h;) +$(info -- KSU_NEXT: adding 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/internal.h) endif ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat diff --git a/drivers/staging/kernelsu/kernel/apk_sign.c b/drivers/staging/kernelsu/kernel/apk_sign.c index ba8b73f2eb2b..6d42841cd577 100644 --- a/drivers/staging/kernelsu/kernel/apk_sign.c +++ b/drivers/staging/kernelsu/kernel/apk_sign.c @@ -316,5 +316,6 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops, bool is_manager_apk(char *path) { - return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); + return (check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH) + || check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH)); } \ No newline at end of file diff --git a/drivers/staging/kernelsu/kernel/core_hook.c b/drivers/staging/kernelsu/kernel/core_hook.c index 92f2e13a052b..a2eea44c1f85 100644 --- a/drivers/staging/kernelsu/kernel/core_hook.c +++ b/drivers/staging/kernelsu/kernel/core_hook.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -197,7 +198,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry) return 0; } - if (strcmp(buf, "/system/packages.list")) { + if (!strstr(buf, "/system/packages.list")) { return 0; } pr_info("renameat: %s -> %s, new path: %s\n", old_dentry->d_iname, @@ -449,14 +450,12 @@ static bool should_umount(struct path *path) return false; } -static int ksu_umount_mnt(struct path *path, int flags) +static void ksu_umount_mnt(struct path *path, int flags) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT) - return path_umount(path, flags); -#else - // TODO: umount for non GKI kernel - return -ENOSYS; -#endif + int err = path_umount(path, flags); + if (err) { + pr_info("umount %s failed: %d\n", path->dentry->d_iname, err); + } } static void try_umount(const char *mnt, bool check_mnt, int flags) @@ -476,11 +475,13 @@ static void try_umount(const char *mnt, bool check_mnt, int flags) if (check_mnt && !should_umount(&path)) { return; } - - err = ksu_umount_mnt(&path, flags); - if (err) { - pr_warn("umount %s failed: %d\n", mnt, err); - } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_UMOUNT) + ksu_umount_mnt(&path, flags); +#else + #error You should backport path_umount to fs/namespace.c ! + #error Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount + #error Read: https://github.com/tiann/KernelSU/pull/1464 +#endif } int ksu_handle_setuid(struct cred *new, const struct cred *old) @@ -624,8 +625,9 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3, ksu_handle_prctl(option, arg2, arg3, arg4, arg5); return -ENOSYS; } + // kernel 4.4 and 4.9 -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, unsigned perm) { @@ -641,6 +643,7 @@ static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, return 0; } #endif + static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) { @@ -658,7 +661,7 @@ static struct security_hook_list ksu_hooks[] = { LSM_HOOK_INIT(task_prctl, ksu_task_prctl), LSM_HOOK_INIT(inode_rename, ksu_inode_rename), LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) LSM_HOOK_INIT(key_permission, ksu_key_permission) #endif }; diff --git a/drivers/staging/kernelsu/kernel/kernel_compat.c b/drivers/staging/kernelsu/kernel/kernel_compat.c index b242bc637398..eb6e8b22ee1f 100644 --- a/drivers/staging/kernelsu/kernel/kernel_compat.c +++ b/drivers/staging/kernelsu/kernel/kernel_compat.c @@ -9,28 +9,23 @@ #include #include "klog.h" // IWYU pragma: keep #include "kernel_compat.h" // Add check Huawei Device - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) #include #include #include struct key *init_session_keyring = NULL; - static inline int install_session_keyring(struct key *keyring) { struct cred *new; int ret; - new = prepare_creds(); if (!new) return -ENOMEM; - ret = install_session_keyring_to_cred(new, keyring); if (ret < 0) { abort_creds(new); return ret; } - return commit_creds(new); } #endif @@ -77,9 +72,19 @@ void ksu_android_ns_fs_check() task_unlock(current); } +int ksu_access_ok(const void *addr, unsigned long size) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) + /* For kernels before 5.0.0, pass the type argument to access_ok. */ + return access_ok(VERIFY_READ, addr, size); +#else + /* For kernels 5.0.0 and later, ignore the type argument. */ + return access_ok(addr, size); +#endif +} + struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) if (init_session_keyring != NULL && !current_cred()->session_keyring && (current->flags & PF_WQ_WORKER)) { pr_info("installing init session keyring for older kernel\n"); @@ -154,23 +159,19 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, { mm_segment_t old_fs = get_fs(); long ret; - if (unlikely(count <= 0)) return 0; - set_fs(USER_DS); pagefault_disable(); ret = strncpy_from_user(dst, unsafe_addr, count); pagefault_enable(); set_fs(old_fs); - if (ret >= count) { ret = count; dst[ret - 1] = '\0'; } else if (ret > 0) { ret++; } - return ret; } #endif diff --git a/drivers/staging/kernelsu/kernel/kernel_compat.h b/drivers/staging/kernelsu/kernel/kernel_compat.h index ba9981857fd1..b0d664a944e3 100644 --- a/drivers/staging/kernelsu/kernel/kernel_compat.h +++ b/drivers/staging/kernelsu/kernel/kernel_compat.h @@ -24,11 +24,12 @@ extern long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, long count); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) extern struct key *init_session_keyring; #endif extern void ksu_android_ns_fs_check(); +extern int ksu_access_ok(const void *addr, unsigned long size); extern struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode); extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, diff --git a/drivers/staging/kernelsu/kernel/ksu.c b/drivers/staging/kernelsu/kernel/ksu.c index 3639edc21503..5f3e6f31795a 100644 --- a/drivers/staging/kernelsu/kernel/ksu.c +++ b/drivers/staging/kernelsu/kernel/ksu.c @@ -94,7 +94,6 @@ module_exit(kernelsu_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("weishu"); MODULE_DESCRIPTION("Android KernelSU"); - #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); -#endif +#endif \ No newline at end of file diff --git a/drivers/staging/kernelsu/kernel/ksud.c b/drivers/staging/kernelsu/kernel/ksud.c index 68e473524284..2ac537d342f4 100644 --- a/drivers/staging/kernelsu/kernel/ksud.c +++ b/drivers/staging/kernelsu/kernel/ksud.c @@ -487,7 +487,6 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) #else argv.ptr.native = PT_REGS_PARM3(regs); #endif - return ksu_handle_execveat_ksud(fd, filename_ptr, &argv, NULL, NULL); } @@ -522,7 +521,6 @@ __maybe_unused static int vfs_read_handler_pre(struct kprobe *p, char __user **buf_ptr = (char **)&PT_REGS_PARM2(regs); size_t *count_ptr = (size_t *)&PT_REGS_PARM3(regs); loff_t **pos_ptr = (loff_t **)&PT_REGS_CCALL_PARM4(regs); - return ksu_handle_vfs_read(file_ptr, buf_ptr, count_ptr, pos_ptr); } diff --git a/drivers/staging/kernelsu/kernel/selinux/selinux.c b/drivers/staging/kernelsu/kernel/selinux/selinux.c index c333e8a800e6..421fba4669f0 100644 --- a/drivers/staging/kernelsu/kernel/selinux/selinux.c +++ b/drivers/staging/kernelsu/kernel/selinux/selinux.c @@ -86,7 +86,7 @@ bool getenforce() #endif } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) && \ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) && \ !defined(KSU_COMPAT_HAS_CURRENT_SID) /* * get the subjective security ID of the current task @@ -131,7 +131,7 @@ bool is_zygote(void *sec) return result; } -#define DEVPTS_DOMAIN "u:object_r:devpts:s0" +#define DEVPTS_DOMAIN "u:object_r:ksu_file:s0" u32 ksu_get_devpts_sid() { @@ -142,4 +142,4 @@ u32 ksu_get_devpts_sid() pr_info("get devpts sid err %d\n", err); } return devpts_sid; -} \ No newline at end of file +} diff --git a/drivers/staging/kernelsu/kernel/selinux/selinux.h b/drivers/staging/kernelsu/kernel/selinux/selinux.h index 07120c253268..91894c8c8183 100644 --- a/drivers/staging/kernelsu/kernel/selinux/selinux.h +++ b/drivers/staging/kernelsu/kernel/selinux/selinux.h @@ -20,6 +20,18 @@ bool is_zygote(void *cred); void apply_kernelsu_rules(); +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT +bool susfs_is_sid_equal(void *sec, u32 sid2); +u32 susfs_get_sid_from_name(const char *secctx_name); +u32 susfs_get_current_sid(void); +void susfs_set_zygote_sid(void); +bool susfs_is_current_zygote_domain(void); +void susfs_set_ksu_sid(void); +bool susfs_is_current_ksu_domain(void); +void susfs_set_init_sid(void); +bool susfs_is_current_init_domain(void); +#endif + u32 ksu_get_devpts_sid(); #endif diff --git a/drivers/staging/kernelsu/kernel/selinux/sepolicy.c b/drivers/staging/kernelsu/kernel/selinux/sepolicy.c index acdc45ad81f7..d7528b7acd9a 100644 --- a/drivers/staging/kernelsu/kernel/selinux/sepolicy.c +++ b/drivers/staging/kernelsu/kernel/selinux/sepolicy.c @@ -568,15 +568,12 @@ static bool add_filename_trans(struct policydb *db, const char *s, db->compat_filename_trans_count++; return ebitmap_set_bit(&trans->stypes, src->value - 1, 1) == 0; #else // < 5.7.0, has no filename_trans_key, but struct filename_trans - struct filename_trans key; key.ttype = tgt->value; key.tclass = cls->value; key.name = (char *)o; - struct filename_trans_datum *trans = hashtab_search(db->filename_trans, &key); - if (trans == NULL) { trans = (struct filename_trans_datum *)kcalloc(sizeof(*trans), 1, GFP_ATOMIC); @@ -596,7 +593,6 @@ static bool add_filename_trans(struct policydb *db, const char *s, trans->otype = def->value; hashtab_insert(db->filename_trans, new_key, trans); } - return ebitmap_set_bit(&db->filename_trans_ttypes, src->value - 1, 1) == 0; #endif @@ -711,22 +707,18 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) size_t new_size = sizeof(struct ebitmap) * db->p_types.nprim; struct ebitmap *new_type_attr_map = (krealloc(db->type_attr_map, new_size, GFP_ATOMIC)); - struct type_datum **new_type_val_to_struct = krealloc(db->type_val_to_struct, sizeof(*db->type_val_to_struct) * db->p_types.nprim, GFP_ATOMIC); - if (!new_type_attr_map) { pr_err("add_type: alloc type_attr_map failed\n"); return false; } - if (!new_type_val_to_struct) { pr_err("add_type: alloc type_val_to_struct failed\n"); return false; } - char **new_val_to_name_types = krealloc(db->sym_val_to_name[SYM_TYPES], sizeof(char *) * db->symtab[SYM_TYPES].nprim, @@ -735,73 +727,59 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) pr_err("add_type: alloc val_to_name failed\n"); return false; } - db->type_attr_map = new_type_attr_map; ebitmap_init(&db->type_attr_map[value - 1], HISI_SELINUX_EBITMAP_RO); ebitmap_set_bit(&db->type_attr_map[value - 1], value - 1, 1); - db->type_val_to_struct = new_type_val_to_struct; db->type_val_to_struct[value - 1] = type; - db->sym_val_to_name[SYM_TYPES] = new_val_to_name_types; db->sym_val_to_name[SYM_TYPES][value - 1] = key; - int i; for (i = 0; i < db->p_roles.nprim; ++i) { ebitmap_set_bit(&db->role_val_to_struct[i]->types, value - 1, 1); } - return true; #else // flex_array is not extensible, we need to create a new bigger one instead struct flex_array *new_type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO); - struct flex_array *new_type_val_to_struct = flex_array_alloc(sizeof(struct type_datum *), db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO); - struct flex_array *new_val_to_name_types = flex_array_alloc(sizeof(char *), db->symtab[SYM_TYPES].nprim, GFP_ATOMIC | __GFP_ZERO); - if (!new_type_attr_map_array) { pr_err("add_type: alloc type_attr_map_array failed\n"); return false; } - if (!new_type_val_to_struct) { pr_err("add_type: alloc type_val_to_struct failed\n"); return false; } - if (!new_val_to_name_types) { pr_err("add_type: alloc val_to_name failed\n"); return false; } - // preallocate so we don't have to worry about the put ever failing if (flex_array_prealloc(new_type_attr_map_array, 0, db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO)) { pr_err("add_type: prealloc type_attr_map_array failed\n"); return false; } - if (flex_array_prealloc(new_type_val_to_struct, 0, db->p_types.nprim, GFP_ATOMIC | __GFP_ZERO)) { pr_err("add_type: prealloc type_val_to_struct_array failed\n"); return false; } - if (flex_array_prealloc(new_val_to_name_types, 0, db->symtab[SYM_TYPES].nprim, GFP_ATOMIC | __GFP_ZERO)) { pr_err("add_type: prealloc val_to_name_types failed\n"); return false; } - int j; void *old_elem; // copy the old data or pointers to new flex arrays @@ -811,14 +789,12 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) flex_array_put(new_type_attr_map_array, j, old_elem, GFP_ATOMIC | __GFP_ZERO); } - for (j = 0; j < db->type_val_to_struct_array->total_nr_elements; j++) { old_elem = flex_array_get_ptr(db->type_val_to_struct_array, j); if (old_elem) flex_array_put_ptr(new_type_val_to_struct, j, old_elem, GFP_ATOMIC | __GFP_ZERO); } - for (j = 0; j < db->symtab[SYM_TYPES].nprim; j++) { old_elem = flex_array_get_ptr(db->sym_val_to_name[SYM_TYPES], j); @@ -826,21 +802,17 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) flex_array_put_ptr(new_val_to_name_types, j, old_elem, GFP_ATOMIC | __GFP_ZERO); } - // store the pointer of old flex arrays first, when assigning new ones we // should free it struct flex_array *old_fa; - old_fa = db->type_attr_map_array; db->type_attr_map_array = new_type_attr_map_array; if (old_fa) { flex_array_free(old_fa); } - ebitmap_init(flex_array_get(db->type_attr_map_array, value - 1)); ebitmap_set_bit(flex_array_get(db->type_attr_map_array, value - 1), value - 1, 1); - old_fa = db->type_val_to_struct_array; db->type_val_to_struct_array = new_type_val_to_struct; if (old_fa) { @@ -848,7 +820,6 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) } flex_array_put_ptr(db->type_val_to_struct_array, value - 1, type, GFP_ATOMIC | __GFP_ZERO); - old_fa = db->sym_val_to_name[SYM_TYPES]; db->sym_val_to_name[SYM_TYPES] = new_val_to_name_types; if (old_fa) { @@ -856,7 +827,6 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) } flex_array_put_ptr(db->sym_val_to_name[SYM_TYPES], value - 1, key, GFP_ATOMIC | __GFP_ZERO); - int i; for (i = 0; i < db->p_roles.nprim; ++i) { ebitmap_set_bit(&db->role_val_to_struct[i]->types, value - 1, @@ -864,7 +834,6 @@ static bool add_type(struct policydb *db, const char *type_name, bool attr) } return true; #endif - #else return false; #endif diff --git a/drivers/staging/kernelsu/kernel/setup.sh b/drivers/staging/kernelsu/kernel/setup.sh index e688dbaf3ae5..0242211f0a4b 100755 --- a/drivers/staging/kernelsu/kernel/setup.sh +++ b/drivers/staging/kernelsu/kernel/setup.sh @@ -31,19 +31,19 @@ perform_cleanup() { [ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed." grep -q "kernelsu" "$DRIVER_MAKEFILE" && sed -i '/kernelsu/d' "$DRIVER_MAKEFILE" && echo "[-] Makefile reverted." grep -q "drivers/kernelsu/Kconfig" "$DRIVER_KCONFIG" && sed -i '/drivers\/kernelsu\/Kconfig/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted." - if [ -d "$GKI_ROOT/KernelSU" ]; then - rm -rf "$GKI_ROOT/KernelSU" && echo "[-] KernelSU directory deleted." + if [ -d "$GKI_ROOT/KernelSU-Next" ]; then + rm -rf "$GKI_ROOT/KernelSU-Next" && echo "[-] KernelSU-Next directory deleted." fi } # Sets up or update KernelSU environment setup_kernelsu() { - echo "[+] Setting up KernelSU..." - test -d "$GKI_ROOT/KernelSU" || git clone https://github.com/tiann/KernelSU && echo "[+] Repository cloned." - cd "$GKI_ROOT/KernelSU" + echo "[+] Setting up KernelSU-Next..." + test -d "$GKI_ROOT/KernelSU-Next" || git clone https://github.com/rifsxd/KernelSU-Next && echo "[+] Repository cloned." + cd "$GKI_ROOT/KernelSU-Next" git stash && echo "[-] Stashed current changes." if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then - git checkout main && echo "[-] Switched to main branch." + git checkout next && echo "[-] Switched to next branch." fi git pull && echo "[+] Repository updated." if [ -z "${1-}" ]; then @@ -52,7 +52,7 @@ setup_kernelsu() { git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch" fi cd "$DRIVER_DIR" - ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created." + ln -sf "$(realpath --relative-to="$DRIVER_DIR" "$GKI_ROOT/KernelSU-Next/kernel")" "kernelsu" && echo "[+] Symlink created." # Add entries in Makefile and Kconfig if not already existing grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile." diff --git a/drivers/staging/kernelsu/kernel/sucompat.c b/drivers/staging/kernelsu/kernel/sucompat.c index 9b45cd0d9490..5849aaf3629a 100644 --- a/drivers/staging/kernelsu/kernel/sucompat.c +++ b/drivers/staging/kernelsu/kernel/sucompat.c @@ -208,7 +208,6 @@ __maybe_unused static int faccessat_handler_pre(struct kprobe *p, int *mode = (int *)&PT_REGS_PARM3(regs); // Both sys_ and do_ is C function int *flags = (int *)&PT_REGS_CCALL_PARM4(regs); - return ksu_handle_faccessat(dfd, filename_user, mode, flags); } @@ -235,7 +234,6 @@ __maybe_unused static int newfstatat_handler_pre(struct kprobe *p, // int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,int flag) int *flags = (int *)&PT_REGS_CCALL_PARM4(regs); #endif - return ksu_handle_stat(dfd, filename_user, flags); } @@ -256,7 +254,6 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) int *fd = (int *)&PT_REGS_PARM1(regs); struct filename **filename_ptr = (struct filename **)&PT_REGS_PARM2(regs); - return ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL); } diff --git a/drivers/staging/kernelsu/kernel/throne_tracker.c b/drivers/staging/kernelsu/kernel/throne_tracker.c index c709a6921a23..725c910336ac 100644 --- a/drivers/staging/kernelsu/kernel/throne_tracker.c +++ b/drivers/staging/kernelsu/kernel/throne_tracker.c @@ -240,13 +240,13 @@ void search_manager(const char *path, int depth, struct list_head *uid_data) file = ksu_filp_open_compat(pos->dirpath, O_RDONLY | O_NOFOLLOW, 0); if (IS_ERR(file)) { pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file)); - return; + goto skip_iterate; } iterate_dir(file, &ctx.ctx); filp_close(file, NULL); } - +skip_iterate: list_del(&pos->list); if (pos != &data) kfree(pos); diff --git a/drivers/staging/kernelsu/manager/.gitignore b/drivers/staging/kernelsu/manager/.gitignore index dd42da43f547..a595ddf709dd 100644 --- a/drivers/staging/kernelsu/manager/.gitignore +++ b/drivers/staging/kernelsu/manager/.gitignore @@ -1,9 +1,10 @@ *.iml .gradle -local.properties .idea +.kotlin .DS_Store build captures .cxx +local.properties key.jks diff --git a/drivers/staging/kernelsu/manager/app/build.gradle.kts b/drivers/staging/kernelsu/manager/app/build.gradle.kts index 1c85d8af7e8a..01f7884a0cf7 100644 --- a/drivers/staging/kernelsu/manager/app/build.gradle.kts +++ b/drivers/staging/kernelsu/manager/app/build.gradle.kts @@ -1,4 +1,7 @@ +@file:Suppress("UnstableApiUsage") + import com.android.build.gradle.internal.api.BaseVariantOutputImpl +import com.android.build.gradle.tasks.PackageAndroidArtifact plugins { alias(libs.plugins.agp.app) @@ -20,7 +23,7 @@ apksign { } android { - namespace = "me.weishu.kernelsu" + namespace = "com.rifsxd.ksunext" buildTypes { release { @@ -34,6 +37,7 @@ android { aidl = true buildConfig = true compose = true + prefab = true } kotlinOptions { @@ -45,7 +49,13 @@ android { useLegacyPackaging = true } resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" + // https://stackoverflow.com/a/58956288 + // It will break Layout Inspector, but it's unused for release build. + excludes += "META-INF/*.version" + // https://github.com/Kotlin/kotlinx.coroutines?tab=readme-ov-file#avoiding-including-the-debug-infrastructure-in-the-resulting-apk + excludes += "DebugProbesKt.bin" + // https://issueantenna.com/repo/kotlin/kotlinx.coroutines/issues/3158 + excludes += "kotlin-tooling-metadata.json" } } @@ -58,15 +68,28 @@ android { applicationVariants.all { outputs.forEach { val output = it as BaseVariantOutputImpl - output.outputFileName = "KernelSU_${managerVersionName}_${managerVersionCode}-$name.apk" + output.outputFileName = "KernelSU_Next_${managerVersionName}_${managerVersionCode}-$name.apk" } - kotlin.sourceSets { getByName(name) { kotlin.srcDir("build/generated/ksp/$name/kotlin") } } } + + // https://stackoverflow.com/a/77745844 + tasks.withType { + doFirst { appMetadata.asFile.orNull?.writeText("") } + } + + dependenciesInfo { + includeInApk = false + includeInBundle = false + } + + androidResources { + generateLocaleConfig = true + } } dependencies { @@ -87,12 +110,7 @@ dependencies { implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.com.google.accompanist.drawablepainter) - implementation(libs.com.google.accompanist.navigation.animation) - implementation(libs.com.google.accompanist.systemuicontroller) - implementation(libs.com.google.accompanist.webview) - - implementation(libs.compose.destinations.animations.core) + implementation(libs.compose.destinations.core) ksp(libs.compose.destinations.ksp) implementation(libs.com.github.topjohnwu.libsu.core) @@ -113,4 +131,6 @@ dependencies { implementation(libs.markdown) implementation(libs.androidx.webkit) + + implementation(libs.lsposed.cxx) } \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/proguard-rules.pro b/drivers/staging/kernelsu/manager/app/proguard-rules.pro index dcaf39ce70fe..e69de29bb2d1 100644 --- a/drivers/staging/kernelsu/manager/app/proguard-rules.pro +++ b/drivers/staging/kernelsu/manager/app/proguard-rules.pro @@ -1,9 +0,0 @@ --dontwarn org.bouncycastle.jsse.BCSSLParameters --dontwarn org.bouncycastle.jsse.BCSSLSocket --dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider --dontwarn org.conscrypt.Conscrypt$Version --dontwarn org.conscrypt.Conscrypt --dontwarn org.conscrypt.ConscryptHostnameVerifier --dontwarn org.openjsse.javax.net.ssl.SSLParameters --dontwarn org.openjsse.javax.net.ssl.SSLSocket --dontwarn org.openjsse.net.ssl.OpenJSSE diff --git a/drivers/staging/kernelsu/manager/app/src/main/AndroidManifest.xml b/drivers/staging/kernelsu/manager/app/src/main/AndroidManifest.xml index 32c920ab4c3b..11cda5f21cd1 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/AndroidManifest.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/AndroidManifest.xml @@ -12,8 +12,8 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:supportsRtl="true" android:networkSecurityConfig="@xml/network_security_config" + android:supportsRtl="true" android:theme="@style/Theme.KernelSU" tools:targetApi="34"> - - - - GetStringUTFChars(pkg, nullptr); auto result = become_manager(cpkg); env->ReleaseStringUTFChars(pkg, cpkg); @@ -21,13 +21,13 @@ Java_me_weishu_kernelsu_Natives_becomeManager(JNIEnv *env, jobject, jstring pkg) extern "C" JNIEXPORT jint JNICALL -Java_me_weishu_kernelsu_Natives_getVersion(JNIEnv *env, jobject) { +Java_com_rifsxd_ksunext_Natives_getVersion(JNIEnv *env, jobject) { return get_version(); } extern "C" JNIEXPORT jintArray JNICALL -Java_me_weishu_kernelsu_Natives_getAllowList(JNIEnv *env, jobject) { +Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) { int uids[1024]; int size = 0; bool result = get_allow_list(uids, &size); @@ -42,13 +42,13 @@ Java_me_weishu_kernelsu_Natives_getAllowList(JNIEnv *env, jobject) { extern "C" JNIEXPORT jboolean JNICALL -Java_me_weishu_kernelsu_Natives_isSafeMode(JNIEnv *env, jclass clazz) { +Java_com_rifsxd_ksunext_Natives_isSafeMode(JNIEnv *env, jclass clazz) { return is_safe_mode(); } extern "C" JNIEXPORT jboolean JNICALL -Java_me_weishu_kernelsu_Natives_isLkmMode(JNIEnv *env, jclass clazz) { +Java_com_rifsxd_ksunext_Natives_isLkmMode(JNIEnv *env, jclass clazz) { return is_lkm_mode(); } @@ -111,7 +111,7 @@ static void fillArrayWithList(JNIEnv *env, jobject list, int *data, int count) { extern "C" JNIEXPORT jobject JNICALL -Java_me_weishu_kernelsu_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, jint uid) { +Java_com_rifsxd_ksunext_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, jint uid) { if (env->GetStringLength(pkg) > KSU_MAX_PACKAGE_NAME) { return nullptr; } @@ -129,7 +129,7 @@ Java_me_weishu_kernelsu_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, bool useDefaultProfile = !get_app_profile(key, &profile); - auto cls = env->FindClass("me/weishu/kernelsu/Natives$Profile"); + auto cls = env->FindClass("com/rifsxd/ksunext/Natives$Profile"); auto constructor = env->GetMethodID(cls, "", "()V"); auto obj = env->NewObject(cls, constructor); auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;"); @@ -207,8 +207,8 @@ Java_me_weishu_kernelsu_Natives_getAppProfile(JNIEnv *env, jobject, jstring pkg, extern "C" JNIEXPORT jboolean JNICALL -Java_me_weishu_kernelsu_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobject profile) { - auto cls = env->FindClass("me/weishu/kernelsu/Natives$Profile"); +Java_com_rifsxd_ksunext_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobject profile) { + auto cls = env->FindClass("com/rifsxd/ksunext/Natives$Profile"); auto keyField = env->GetFieldID(cls, "name", "Ljava/lang/String;"); auto currentUidField = env->GetFieldID(cls, "currentUid", "I"); @@ -293,6 +293,6 @@ Java_me_weishu_kernelsu_Natives_setAppProfile(JNIEnv *env, jobject clazz, jobjec } extern "C" JNIEXPORT jboolean JNICALL -Java_me_weishu_kernelsu_Natives_uidShouldUmount(JNIEnv *env, jobject thiz, jint uid) { +Java_com_rifsxd_ksunext_Natives_uidShouldUmount(JNIEnv *env, jobject thiz, jint uid) { return uid_should_umount(uid); } \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt similarity index 96% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt index 0503b42f0f43..3e2255a32aa1 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/KernelSUApplication.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/KernelSUApplication.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu +package com.rifsxd.ksunext import android.app.Application import coil.Coil diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Kernels.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Kernels.kt similarity index 97% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Kernels.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Kernels.kt index 860e46fcb149..a730322200f8 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Kernels.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Kernels.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu +package com.rifsxd.ksunext import android.system.Os diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt similarity index 93% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt index bb788293aa31..87bab578ded6 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/Natives.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/Natives.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu +package com.rifsxd.ksunext import android.os.Parcelable import androidx.annotation.Keep @@ -15,12 +15,14 @@ object Natives { // 10931: app profile struct add 'version' field // 10946: add capabilities // 10977: change groups_count and groups to avoid overflow write - // 11071: Fix the issue of failing to set a custom SELinux type. - const val MINIMAL_SUPPORTED_KERNEL = 11071 + // 11071: Fix the issue of failing to set a custom SELinux type + // 11998: Next experimental modifications. + const val MINIMAL_SUPPORTED_KERNEL = 11998 // 11640: Support query working mode, LKM or GKI + // 12016: Next now supports GKI -> LKM/KMI modes! // when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant. - const val MINIMAL_SUPPORTED_KERNEL_LKM = 11648 + const val MINIMAL_SUPPORTED_KERNEL_LKM = 12016 const val KERNEL_SU_DOMAIN = "u:r:su:s0" const val ROOT_UID = 0 diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Capabilities.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Capabilities.kt similarity index 99% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Capabilities.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Capabilities.kt index d52518c2b4e0..9eb98a121aaa 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Capabilities.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Capabilities.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.profile +package com.rifsxd.ksunext.profile /** * @author weishu diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Groups.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Groups.kt similarity index 99% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Groups.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Groups.kt index 2ddb94dc91a1..b1bbfd816d0c 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/profile/Groups.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/profile/Groups.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.profile +package com.rifsxd.ksunext.profile /** * https://cs.android.com/android/platform/superproject/main/+/main:system/core/libcutils/include/private/android_filesystem_config.h diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/KsuService.java b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/KsuService.java similarity index 96% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/KsuService.java rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/KsuService.java index 2ebcc786391d..624721f7e10b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/KsuService.java +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/KsuService.java @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui; +package com.rifsxd.ksunext.ui; import android.content.Context; import android.content.Intent; @@ -17,7 +17,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; -import me.weishu.kernelsu.IKsuInterface; +import com.rifsxd.ksunext.IKsuInterface; import rikka.parcelablelist.ParcelableListSlice; /** diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt similarity index 52% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt index 042155fbee62..5ea6d89584e8 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/MainActivity.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/MainActivity.kt @@ -1,14 +1,27 @@ -package me.weishu.kernelsu.ui +package com.rifsxd.ksunext.ui +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.displayCutout +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.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -18,39 +31,54 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.navigation.NavBackStackEntry import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController import com.ramcosta.composedestinations.DestinationsNavHost -import com.ramcosta.composedestinations.navigation.popBackStack +import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle +import com.ramcosta.composedestinations.generated.NavGraphs import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.ksuApp -import me.weishu.kernelsu.ui.screen.BottomBarDestination -import me.weishu.kernelsu.ui.screen.NavGraphs -import me.weishu.kernelsu.ui.theme.KernelSUTheme -import me.weishu.kernelsu.ui.util.LocalSnackbarHost -import me.weishu.kernelsu.ui.util.rootAvailable +import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator +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.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.rootAvailable class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { + + // Enable edge to edge + enableEdgeToEdge() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + window.isNavigationBarContrastEnforced = false + } + super.onCreate(savedInstanceState) setContent { KernelSUTheme { val navController = rememberNavController() - val snackbarHostState = remember { SnackbarHostState() } + val snackBarHostState = remember { SnackbarHostState() } Scaffold( bottomBar = { BottomBar(navController) }, - snackbarHost = { SnackbarHost(snackbarHostState) } + contentWindowInsets = WindowInsets(0, 0, 0, 0) ) { innerPadding -> CompositionLocalProvider( - LocalSnackbarHost provides snackbarHostState, + LocalSnackbarHost provides snackBarHostState, ) { DestinationsNavHost( modifier = Modifier.padding(innerPadding), navGraph = NavGraphs.root, - navController = navController + navController = navController, + defaultTransitions = object : NavHostAnimatedDestinationStyle() { + override val enterTransition: AnimatedContentTransitionScope.() -> EnterTransition + get() = { fadeIn(animationSpec = tween(340)) } + override val exitTransition: AnimatedContentTransitionScope.() -> ExitTransition + get() = { fadeOut(animationSpec = tween(340)) } + } ) } } @@ -61,9 +89,15 @@ class MainActivity : ComponentActivity() { @Composable private fun BottomBar(navController: NavHostController) { + val navigator = navController.rememberDestinationsNavigator() val isManager = Natives.becomeManager(ksuApp.packageName) val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable() - NavigationBar(tonalElevation = 8.dp) { + 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) @@ -71,11 +105,10 @@ private fun BottomBar(navController: NavHostController) { selected = isCurrentDestOnBackStack, onClick = { if (isCurrentDestOnBackStack) { - navController.popBackStack(destination.direction, false) + navigator.popBackStack(destination.direction, false) } - - navController.navigate(destination.direction.route) { - popUpTo(NavGraphs.root.route) { + navigator.navigate(destination.direction) { + popUpTo(NavGraphs.root) { saveState = true } launchSingleTop = true diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/AboutCard.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/AboutCard.kt new file mode 100644 index 000000000000..c27c93d1161b --- /dev/null +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/AboutCard.kt @@ -0,0 +1,124 @@ +package com.rifsxd.ksunext.ui.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.fromHtml +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import com.rifsxd.ksunext.BuildConfig +import com.rifsxd.ksunext.R + +@Preview +@Composable +fun AboutCard() { + ElevatedCard( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(24.dp) + ) { + AboutCardContent() + } + } +} + +@Composable +fun AboutDialog(dismiss: () -> Unit) { + Dialog( + onDismissRequest = { dismiss() } + ) { + AboutCard() + } +} + +@Composable +private fun AboutCardContent() { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Row { + Surface( + modifier = Modifier.size(40.dp), + color = colorResource(id = R.color.ic_launcher_background), + shape = CircleShape + ) { + Image( + painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = "icon", + modifier = Modifier.scale(1.2f) + ) + } + + Spacer(modifier = Modifier.width(12.dp)) + + Column { + + Text( + stringResource(id = R.string.app_name), + style = MaterialTheme.typography.titleSmall, + fontSize = 18.sp + ) + Text( + BuildConfig.VERSION_NAME, + style = MaterialTheme.typography.bodySmall, + fontSize = 14.sp + ) + + Spacer(modifier = Modifier.height(8.dp)) + + val annotatedString = AnnotatedString.Companion.fromHtml( + htmlString = stringResource( + id = R.string.about_source_code, + "GitHub" + ), + linkStyles = TextLinkStyles( + style = SpanStyle( + color = MaterialTheme.colorScheme.primary, + textDecoration = TextDecoration.Underline + ), + pressedStyle = SpanStyle( + color = MaterialTheme.colorScheme.primary, + background = MaterialTheme.colorScheme.secondaryContainer, + textDecoration = TextDecoration.Underline + ) + ) + ) + Text( + text = annotatedString, + style = TextStyle( + fontSize = 14.sp + ) + ) + } + } + } +} diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/Dialog.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/Dialog.kt similarity index 97% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/Dialog.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/Dialog.kt index e2c3fa453e0d..361e1ef9f13b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/Dialog.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/Dialog.kt @@ -1,6 +1,7 @@ -package me.weishu.kernelsu.ui.component +package com.rifsxd.ksunext.ui.component import android.graphics.text.LineBreaker +import android.os.Build import android.os.Parcelable import android.text.Layout import android.text.method.LinkMovementMethod @@ -96,8 +97,8 @@ interface ConfirmDialogHandle : DialogHandle { } private abstract class DialogHandleBase( - protected val visible: MutableState, - protected val coroutineScope: CoroutineScope + val visible: MutableState, + val coroutineScope: CoroutineScope ) : DialogHandle { override val isShown: Boolean get() = visible.value @@ -432,7 +433,9 @@ private fun MarkdownContent(content: String) { TextView(context).apply { movementMethod = LinkMovementMethod.getInstance() setSpannableFactory(NoCopySpannableFactory.getInstance()) - breakStrategy = LineBreaker.BREAK_STRATEGY_SIMPLE + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + breakStrategy = LineBreaker.BREAK_STRATEGY_SIMPLE + } hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/KeyEventBlocker.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/KeyEventBlocker.kt similarity index 95% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/KeyEventBlocker.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/KeyEventBlocker.kt index b3268131268a..5aa806ca2b5b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/KeyEventBlocker.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/KeyEventBlocker.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.component +package com.rifsxd.ksunext.ui.component import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.Box diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SearchBar.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SearchBar.kt similarity index 90% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SearchBar.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SearchBar.kt index 8195cdddd40b..800b59ca81ed 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SearchBar.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SearchBar.kt @@ -1,12 +1,16 @@ -package me.weishu.kernelsu.ui.component +package com.rifsxd.ksunext.ui.component import android.util.Log import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons @@ -19,6 +23,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect @@ -48,6 +53,7 @@ fun SearchAppBar( onBackClick: (() -> Unit)? = null, onConfirm: (() -> Unit)? = null, dropdownContent: @Composable (() -> Unit)? = null, + scrollBehavior: TopAppBarScrollBehavior? = null ) { val keyboardController = LocalSoftwareKeyboardController.current val focusRequester = remember { FocusRequester() } @@ -132,10 +138,13 @@ fun SearchAppBar( dropdownContent() } - } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior ) } +@OptIn(ExperimentalMaterial3Api::class) @Preview @Composable private fun SearchAppBarPreview() { diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SettingsItem.kt similarity index 55% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SettingsItem.kt index 6db20b163cde..080ee3c96b59 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/SettingsItem.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/SettingsItem.kt @@ -1,14 +1,18 @@ -package me.weishu.kernelsu.ui.component +package com.rifsxd.ksunext.ui.component -import androidx.compose.foundation.clickable +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.selection.toggleable import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.RadioButton import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.semantics.Role @Composable fun SwitchItem( @@ -19,10 +23,18 @@ fun SwitchItem( enabled: Boolean = true, onCheckedChange: (Boolean) -> Unit ) { + val interactionSource = remember { MutableInteractionSource() } + ListItem( - modifier = Modifier.clickable { - onCheckedChange.invoke(!checked) - }, + modifier = Modifier + .toggleable( + value = checked, + interactionSource = interactionSource, + role = Role.Switch, + enabled = enabled, + indication = LocalIndication.current, + onValueChange = onCheckedChange + ), headlineContent = { Text(title) }, @@ -30,7 +42,12 @@ fun SwitchItem( { Icon(icon, title) } }, trailingContent = { - Switch(checked = checked, enabled = enabled, onCheckedChange = onCheckedChange) + Switch( + checked = checked, + enabled = enabled, + onCheckedChange = onCheckedChange, + interactionSource = interactionSource + ) }, supportingContent = { if (summary != null) { @@ -52,6 +69,6 @@ fun RadioItem( }, leadingContent = { RadioButton(selected = selected, onClick = onClick) - }, + } ) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/AppProfileConfig.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/AppProfileConfig.kt similarity index 92% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/AppProfileConfig.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/AppProfileConfig.kt index 065ff6d0cf02..695c427bad06 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/AppProfileConfig.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/AppProfileConfig.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.component.profile +package com.rifsxd.ksunext.ui.component.profile import androidx.compose.foundation.layout.Column import androidx.compose.material3.OutlinedTextField @@ -11,9 +11,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.SwitchItem +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.SwitchItem @Composable fun AppProfileConfig( diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/RootProfileConfig.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/RootProfileConfig.kt similarity index 91% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/RootProfileConfig.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/RootProfileConfig.kt index d2cb3f342e51..fc32a7fbba68 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/RootProfileConfig.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/RootProfileConfig.kt @@ -1,11 +1,10 @@ -@file:OptIn(ExperimentalMaterial3Api::class) - -package me.weishu.kernelsu.ui.component.profile +package com.rifsxd.ksunext.ui.component.profile import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardActions @@ -20,12 +19,14 @@ import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.MenuAnchorType import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -48,12 +49,12 @@ import com.maxkeppeler.sheets.input.models.ValidationResult import com.maxkeppeler.sheets.list.ListDialog import com.maxkeppeler.sheets.list.models.ListOption import com.maxkeppeler.sheets.list.models.ListSelection -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.profile.Capabilities -import me.weishu.kernelsu.profile.Groups -import me.weishu.kernelsu.ui.component.rememberCustomDialog -import me.weishu.kernelsu.ui.util.isSepolicyValid +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.profile.Capabilities +import com.rifsxd.ksunext.profile.Groups +import com.rifsxd.ksunext.ui.component.rememberCustomDialog +import com.rifsxd.ksunext.ui.util.isSepolicyValid @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -86,7 +87,7 @@ fun RootProfileConfig( ) { OutlinedTextField( modifier = Modifier - .menuAnchor() + .menuAnchor(MenuAnchorType.PrimaryNotEditable) .fillMaxWidth(), readOnly = true, label = { Text(stringResource(R.string.profile_namespace)) }, @@ -184,7 +185,7 @@ fun RootProfileConfig( } } -@OptIn(ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class) @Composable fun GroupsPanel(selected: List, closeSelection: (selection: Set) -> Unit) { val selectGroupsDialog = rememberCustomDialog { dismiss: () -> Unit -> @@ -234,14 +235,20 @@ fun GroupsPanel(selected: List, closeSelection: (selection: Set) ) } - OutlinedCard(modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .clickable { - selectGroupsDialog.show() - }) { + OutlinedCard( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { - Column(modifier = Modifier.padding(16.dp)) { + Column( + modifier = Modifier + .fillMaxSize() + .clickable { + selectGroupsDialog.show() + } + .padding(16.dp) + ) { Text(stringResource(R.string.profile_groups)) FlowRow { selected.forEach { group -> @@ -256,7 +263,7 @@ fun GroupsPanel(selected: List, closeSelection: (selection: Set) } } -@OptIn(ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class) @Composable fun CapsPanel( selected: Collection, @@ -299,14 +306,20 @@ fun CapsPanel( ) } - OutlinedCard(modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .clickable { - selectCapabilitiesDialog.show() - }) { + OutlinedCard( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { - Column(modifier = Modifier.padding(16.dp)) { + Column( + modifier = Modifier + .fillMaxSize() + .clickable { + selectCapabilitiesDialog.show() + } + .padding(16.dp) + ) { Text(stringResource(R.string.profile_capabilities)) FlowRow { selected.forEach { group -> @@ -329,10 +342,10 @@ private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) { mutableStateOf(false) } var lastValidUid by remember { - mutableStateOf(uid) + mutableIntStateOf(uid) } - val keyboardController = LocalSoftwareKeyboardController.current + OutlinedTextField( modifier = Modifier.fillMaxWidth(), label = { Text(label) }, @@ -365,6 +378,7 @@ private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) { }) } +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun SELinuxPanel( profile: Natives.Profile, @@ -452,7 +466,7 @@ private fun SELinuxPanel( ), label = { Text(text = stringResource(R.string.profile_selinux_context)) }, value = profile.context, - onValueChange = { }, + onValueChange = { } ) }) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/TemplateConfig.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/TemplateConfig.kt similarity index 91% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/TemplateConfig.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/TemplateConfig.kt index d09a23434f85..686dc948d739 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/profile/TemplateConfig.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/component/profile/TemplateConfig.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.component.profile +package com.rifsxd.ksunext.ui.component.profile import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons @@ -12,6 +12,7 @@ import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem +import androidx.compose.material3.MenuAnchorType import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -22,11 +23,11 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.util.listAppProfileTemplates -import me.weishu.kernelsu.ui.util.setSepolicy -import me.weishu.kernelsu.ui.viewmodel.getTemplateInfoById +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.util.listAppProfileTemplates +import com.rifsxd.ksunext.ui.util.setSepolicy +import com.rifsxd.ksunext.ui.viewmodel.getTemplateInfoById /** * @author weishu @@ -54,7 +55,7 @@ fun TemplateConfig( ) { OutlinedTextField( modifier = Modifier - .menuAnchor() + .menuAnchor(MenuAnchorType.PrimaryNotEditable) .fillMaxWidth(), readOnly = true, label = { Text(stringResource(R.string.profile_template)) }, diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/AppProfile.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/AppProfile.kt similarity index 80% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/AppProfile.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/AppProfile.kt index ca53388f8ea4..871fb1817415 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/AppProfile.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/AppProfile.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import androidx.annotation.StringRes import androidx.compose.animation.Crossfade @@ -7,10 +7,14 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.BoxWithConstraints 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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -28,8 +32,11 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem 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.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -39,6 +46,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity @@ -50,42 +58,43 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import coil.request.ImageRequest import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination +import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import kotlinx.coroutines.launch -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.SwitchItem -import me.weishu.kernelsu.ui.component.profile.AppProfileConfig -import me.weishu.kernelsu.ui.component.profile.RootProfileConfig -import me.weishu.kernelsu.ui.component.profile.TemplateConfig -import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination -import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination -import me.weishu.kernelsu.ui.util.LocalSnackbarHost -import me.weishu.kernelsu.ui.util.forceStopApp -import me.weishu.kernelsu.ui.util.getSepolicy -import me.weishu.kernelsu.ui.util.launchApp -import me.weishu.kernelsu.ui.util.restartApp -import me.weishu.kernelsu.ui.util.setSepolicy -import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel -import me.weishu.kernelsu.ui.viewmodel.getTemplateInfoById +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.SwitchItem +import com.rifsxd.ksunext.ui.component.profile.AppProfileConfig +import com.rifsxd.ksunext.ui.component.profile.RootProfileConfig +import com.rifsxd.ksunext.ui.component.profile.TemplateConfig +import com.rifsxd.ksunext.ui.util.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.forceStopApp +import com.rifsxd.ksunext.ui.util.getSepolicy +import com.rifsxd.ksunext.ui.util.launchApp +import com.rifsxd.ksunext.ui.util.restartApp +import com.rifsxd.ksunext.ui.util.setSepolicy +import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel +import com.rifsxd.ksunext.ui.viewmodel.getTemplateInfoById /** * @author weishu * @date 2023/5/16. */ -@Destination +@OptIn(ExperimentalMaterial3Api::class) +@Destination @Composable fun AppProfileScreen( navigator: DestinationsNavigator, appInfo: SuperUserViewModel.AppInfo, ) { val context = LocalContext.current - val snackbarHost = LocalSnackbarHost.current + val snackBarHost = LocalSnackbarHost.current + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() val scope = rememberCoroutineScope() - 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 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 packageName = appInfo.packageName val initialProfile = Natives.getAppProfile(packageName, appInfo.uid) @@ -97,18 +106,25 @@ fun AppProfileScreen( } Scaffold( - topBar = { TopBar { navigator.popBackStack() } }, + topBar = { + TopBar( + onBack = { navigator.popBackStack() }, + scrollBehavior = scrollBehavior + ) + }, + snackbarHost = { SnackbarHost(hostState = snackBarHost) }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { paddingValues -> AppProfileInner( modifier = Modifier .padding(paddingValues) + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(rememberScrollState()), packageName = appInfo.packageName, appLabel = appInfo.label, appIcon = { AsyncImage( - model = ImageRequest.Builder(context).data(appInfo.packageInfo).crossfade(true) - .build(), + model = ImageRequest.Builder(context).data(appInfo.packageInfo).crossfade(true).build(), contentDescription = appInfo.label, modifier = Modifier .padding(4.dp) @@ -129,12 +145,12 @@ fun AppProfileScreen( scope.launch { if (it.allowSu && !it.rootUseDefault && it.rules.isNotEmpty()) { if (!setSepolicy(profile.name, it.rules)) { - snackbarHost.showSnackbar(failToUpdateSepolicy) + snackBarHost.showSnackbar(failToUpdateSepolicy) return@launch } } if (!Natives.setAppProfile(it)) { - snackbarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid)) + snackBarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid)) } else { profile = it } @@ -174,7 +190,9 @@ private fun AppProfileInner( ) Crossfade(targetState = isRootGranted, label = "") { current -> - Column { + Column( + modifier = Modifier.padding(bottom = 6.dp + 48.dp + 6.dp /* SnackBar height */) + ) { if (current) { val initialMode = if (profile.rootUseDefault) { Mode.Default @@ -238,7 +256,10 @@ private enum class Mode(@StringRes private val res: Int) { @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun TopBar(onBack: () -> Unit) { +private fun TopBar( + onBack: () -> Unit, + scrollBehavior: TopAppBarScrollBehavior? = null +) { TopAppBar( title = { Text(stringResource(R.string.profile)) @@ -248,6 +269,8 @@ private fun TopBar(onBack: () -> Unit) { onClick = onBack ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior ) } @@ -303,7 +326,8 @@ private fun AppMenuBox(packageName: String, content: @Composable () -> Unit) { touchPoint = it expanded = true } - }) { + } + ) { content() diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/BottomBarDestination.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/BottomBarDestination.kt similarity index 53% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/BottomBarDestination.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/BottomBarDestination.kt index 9345ced52ff0..12da30d75f2d 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/BottomBarDestination.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/BottomBarDestination.kt @@ -1,15 +1,16 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import androidx.annotation.StringRes import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.outlined.* import androidx.compose.ui.graphics.vector.ImageVector +import com.ramcosta.composedestinations.generated.destinations.HomeScreenDestination +import com.ramcosta.composedestinations.generated.destinations.ModuleScreenDestination +import com.ramcosta.composedestinations.generated.destinations.SuperUserScreenDestination +import com.ramcosta.composedestinations.generated.destinations.SettingScreenDestination import com.ramcosta.composedestinations.spec.DirectionDestinationSpec -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.screen.destinations.HomeScreenDestination -import me.weishu.kernelsu.ui.screen.destinations.SuperUserScreenDestination -import me.weishu.kernelsu.ui.screen.destinations.ModuleScreenDestination +import com.rifsxd.ksunext.R enum class BottomBarDestination( val direction: DirectionDestinationSpec, @@ -19,6 +20,7 @@ enum class BottomBarDestination( val rootRequired: Boolean, ) { Home(HomeScreenDestination, R.string.home, Icons.Filled.Home, Icons.Outlined.Home, false), - SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.Security, Icons.Outlined.Security, true), - Module(ModuleScreenDestination, R.string.module, Icons.Filled.Apps, Icons.Outlined.Apps, true) + SuperUser(SuperUserScreenDestination, R.string.superuser, Icons.Filled.AdminPanelSettings, Icons.Outlined.AdminPanelSettings, true), + Module(ModuleScreenDestination, R.string.module, Icons.Filled.Layers, Icons.Outlined.Layers, true), + Settings(SettingScreenDestination, R.string.settings, Icons.Filled.Settings, Icons.Outlined.Settings, false) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt new file mode 100644 index 000000000000..bc523336fe86 --- /dev/null +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/ExecuteModuleAction.kt @@ -0,0 +1,143 @@ +package com.rifsxd.ksunext.ui.screen + +import android.os.Environment +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Save +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.KeyEventBlocker +import com.rifsxd.ksunext.ui.util.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.runModuleAction +import java.io.File +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +@Composable +@Destination +fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String) { + var text by rememberSaveable { mutableStateOf("") } + val logContent = rememberSaveable { StringBuilder() } + val snackBarHost = LocalSnackbarHost.current + val scope = rememberCoroutineScope() + val scrollState = rememberScrollState() + var actionResult: Boolean + + LaunchedEffect(Unit) { + if (text.isNotEmpty()) { + return@LaunchedEffect + } + withContext(Dispatchers.IO) { + runModuleAction( + moduleId = moduleId, + onStdout = { + text += "$it\n" + logContent.append(it).append("\n") + }, + onStderr = { + logContent.append(it).append("\n") + } + ).let { + actionResult = it + } + } + if (actionResult) navigator.popBackStack() + } + + Scaffold( + topBar = { + TopBar( + onBack = { + navigator.popBackStack() + }, + onSave = { + scope.launch { + val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault()) + val date = format.format(Date()) + val file = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + "KernelSU_module_action_log_${date}.log" + ) + file.writeText(logContent.toString()) + snackBarHost.showSnackbar("Log saved to ${file.absolutePath}") + } + } + ) + }, + snackbarHost = { SnackbarHost(snackBarHost) } + ) { innerPadding -> + KeyEventBlocker { + it.key == Key.VolumeDown || it.key == Key.VolumeUp + } + Column( + modifier = Modifier + .fillMaxSize(1f) + .padding(innerPadding) + .verticalScroll(scrollState), + ) { + LaunchedEffect(text) { + scrollState.animateScrollTo(scrollState.maxValue) + } + Text( + modifier = Modifier.padding(8.dp), + text = text, + fontSize = MaterialTheme.typography.bodySmall.fontSize, + fontFamily = FontFamily.Monospace, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun TopBar(onBack: () -> Unit = {}, onSave: () -> Unit = {}) { + TopAppBar( + title = { Text(stringResource(R.string.action)) }, + navigationIcon = { + IconButton( + onClick = onBack + ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } + }, + actions = { + IconButton(onClick = onSave) { + Icon( + imageVector = Icons.Filled.Save, + contentDescription = stringResource(id = R.string.save_log), + ) + } + } + ) +} \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt similarity index 80% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt index 1e3d48fdae05..0930ff355d0e 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Flash.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Flash.kt @@ -1,11 +1,15 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import android.net.Uri import android.os.Environment import android.os.Parcelable import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize +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 @@ -18,8 +22,12 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme 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.LaunchedEffect import androidx.compose.runtime.getValue @@ -30,26 +38,28 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp 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.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.KeyEventBlocker -import me.weishu.kernelsu.ui.util.LkmSelection -import me.weishu.kernelsu.ui.util.LocalSnackbarHost -import me.weishu.kernelsu.ui.util.flashModule -import me.weishu.kernelsu.ui.util.installBoot -import me.weishu.kernelsu.ui.util.reboot -import me.weishu.kernelsu.ui.util.restoreBoot -import me.weishu.kernelsu.ui.util.uninstallPermanently +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.KeyEventBlocker +import com.rifsxd.ksunext.ui.util.LkmSelection +import com.rifsxd.ksunext.ui.util.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.flashModule +import com.rifsxd.ksunext.ui.util.installBoot +import com.rifsxd.ksunext.ui.util.reboot +import com.rifsxd.ksunext.ui.util.restoreBoot +import com.rifsxd.ksunext.ui.util.uninstallPermanently import java.io.File import java.text.SimpleDateFormat import java.util.Date @@ -65,8 +75,9 @@ enum class FlashingStatus { * @author weishu * @date 2023/1/1. */ +@OptIn(ExperimentalMaterial3Api::class) @Composable -@Destination +@Destination fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { var text by rememberSaveable { mutableStateOf("") } @@ -76,6 +87,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { val snackBarHost = LocalSnackbarHost.current val scope = rememberCoroutineScope() val scrollState = rememberScrollState() + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) var flashing by rememberSaveable { mutableStateOf(FlashingStatus.FLASHING) } @@ -121,7 +133,8 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { file.writeText(logContent.toString()) snackBarHost.showSnackbar("Log saved to ${file.absolutePath}") } - } + }, + scrollBehavior = scrollBehavior ) }, floatingActionButton = { @@ -139,8 +152,9 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { text = { Text(text = reboot) }, ) } - - } + }, + snackbarHost = { SnackbarHost(hostState = snackBarHost) }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { innerPadding -> KeyEventBlocker { it.key == Key.VolumeDown || it.key == Key.VolumeUp @@ -149,6 +163,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { modifier = Modifier .fillMaxSize(1f) .padding(innerPadding) + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(scrollState), ) { LaunchedEffect(text) { @@ -202,7 +217,12 @@ fun flashIt( @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun TopBar(status: FlashingStatus, onBack: () -> Unit = {}, onSave: () -> Unit = {}) { +private fun TopBar( + status: FlashingStatus, + onBack: () -> Unit = {}, + onSave: () -> Unit = {}, + scrollBehavior: TopAppBarScrollBehavior? = null +) { TopAppBar( title = { Text( @@ -227,7 +247,9 @@ private fun TopBar(status: FlashingStatus, onBack: () -> Unit = {}, onSave: () - contentDescription = "Localized description" ) } - } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior ) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Home.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt similarity index 60% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Home.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt index 7f1d483f14bf..324005a92600 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Home.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Home.kt @@ -1,8 +1,10 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import android.content.Context import android.os.Build import android.os.PowerManager +import android.os.Handler +import android.os.Looper import android.system.Os import androidx.annotation.StringRes import androidx.compose.animation.* @@ -11,58 +13,68 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Archive -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material.icons.outlined.Block -import androidx.compose.material.icons.outlined.CheckCircle -import androidx.compose.material.icons.outlined.Warning +import androidx.compose.material.icons.automirrored.filled.* +import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.outlined.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.core.content.pm.PackageInfoCompat import com.ramcosta.composedestinations.annotation.Destination -import com.ramcosta.composedestinations.annotation.RootNavGraph +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import me.weishu.kernelsu.* -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.rememberConfirmDialog -import me.weishu.kernelsu.ui.screen.destinations.InstallScreenDestination -import me.weishu.kernelsu.ui.screen.destinations.SettingScreenDestination -import me.weishu.kernelsu.ui.util.* -import me.weishu.kernelsu.ui.util.module.LatestVersionInfo +import com.rifsxd.ksunext.* +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.rememberConfirmDialog +import com.rifsxd.ksunext.ui.util.* +import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo +import androidx.compose.ui.graphics.vector.ImageVector -@RootNavGraph(start = true) -@Destination +@OptIn(ExperimentalMaterial3Api::class) +@Destination(start = true) @Composable fun HomeScreen(navigator: DestinationsNavigator) { val kernelVersion = getKernelVersion() + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) - Scaffold(topBar = { - TopBar(kernelVersion, onSettingsClick = { - navigator.navigate(SettingScreenDestination) - }, onInstallClick = { - navigator.navigate(InstallScreenDestination) - }) - }) { innerPadding -> + Scaffold( + topBar = { + TopBar( + kernelVersion, + onInstallClick = { + navigator.navigate(InstallScreenDestination) + }, + scrollBehavior = scrollBehavior + ) + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) + ) { innerPadding -> Column( modifier = Modifier .padding(innerPadding) - .padding(horizontal = 16.dp) - .verticalScroll(rememberScrollState()), + .nestedScroll(scrollBehavior.nestedScrollConnection) + .verticalScroll(rememberScrollState()) + .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { val isManager = Natives.becomeManager(ksuApp.packageName) SideEffect { - if (isManager) install() + if (isManager) { + Handler(Looper.getMainLooper()).postDelayed({ + install() + }, 2000) + } } val ksuVersion = if (isManager) Natives.version else null val lkmMode = ksuVersion?.let { @@ -90,9 +102,9 @@ fun HomeScreen(navigator: DestinationsNavigator) { if (checkUpdate) { UpdateCard() } + NextCard() InfoCard() - DonateCard() - LearnMoreCard() + EXperimentalCard() Spacer(Modifier) } } @@ -103,12 +115,11 @@ fun UpdateCard() { val context = LocalContext.current val latestVersionInfo = LatestVersionInfo() val newVersion by produceState(initialValue = latestVersionInfo) { - value = withContext(Dispatchers.IO){ + value = withContext(Dispatchers.IO) { checkNewVersion() } } - val currentVersionCode = getManagerVersion(context).second val newVersionCode = newVersion.versionCode val newVersionUrl = newVersion.downloadUrl @@ -128,7 +139,9 @@ fun UpdateCard() { message = stringResource(id = R.string.new_version_available).format(newVersionCode), MaterialTheme.colorScheme.outlineVariant ) { - if (changelog.isNotEmpty()) { + if (changelog.isEmpty()) { + uriHandler.openUri(newVersionUrl) + } else { updateDialog.showConfirm( title = title, content = changelog, @@ -154,52 +167,50 @@ fun RebootDropdownItem(@StringRes id: Int, reason: String = "") { private fun TopBar( kernelVersion: KernelVersion, onInstallClick: () -> Unit, - onSettingsClick: () -> Unit + scrollBehavior: TopAppBarScrollBehavior? = null ) { - TopAppBar(title = { Text(stringResource(R.string.app_name)) }, actions = { - if (kernelVersion.isGKI()) { - IconButton(onClick = onInstallClick) { - Icon( - imageVector = Icons.Filled.Archive, - contentDescription = stringResource(id = R.string.install) - ) - } - } - - var showDropdown by remember { mutableStateOf(false) } - IconButton(onClick = { - showDropdown = true - }) { - Icon( - imageVector = Icons.Filled.Refresh, - contentDescription = stringResource(id = R.string.reboot) - ) - - DropdownMenu(expanded = showDropdown, onDismissRequest = { - showDropdown = false - }) { - - RebootDropdownItem(id = R.string.reboot) - - val pm = - LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager? - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) { - RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace") + TopAppBar( + title = { Text(stringResource(R.string.app_name)) }, + actions = { + if (kernelVersion.isGKI()) { + IconButton(onClick = onInstallClick) { + Icon( + imageVector = Icons.Filled.Archive, + contentDescription = stringResource(id = R.string.install) + ) } - RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery") - RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader") - RebootDropdownItem(id = R.string.reboot_download, reason = "download") - RebootDropdownItem(id = R.string.reboot_edl, reason = "edl") } - } - IconButton(onClick = onSettingsClick) { - Icon( - imageVector = Icons.Filled.Settings, - contentDescription = stringResource(id = R.string.settings) - ) - } - }) + var showDropdown by remember { mutableStateOf(false) } + IconButton(onClick = { + showDropdown = true + }) { + Icon( + imageVector = Icons.Filled.Refresh, + contentDescription = stringResource(id = R.string.reboot) + ) + + DropdownMenu(expanded = showDropdown, onDismissRequest = { + showDropdown = false + }) { + + RebootDropdownItem(id = R.string.reboot) + + val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager? + @Suppress("DEPRECATION") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) { + RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace") + } + RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery") + RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader") + RebootDropdownItem(id = R.string.reboot_download, reason = "download") + RebootDropdownItem(id = R.string.reboot_edl, reason = "edl") + } + } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior + ) } @Composable @@ -231,7 +242,7 @@ private fun StatusCard( } val workingMode = when (lkmMode) { - null -> "" + null -> " " true -> " " else -> " " } @@ -239,7 +250,7 @@ private fun StatusCard( val workingText = "${stringResource(id = R.string.home_working)}$workingMode$safeMode" - Icon(Icons.Outlined.CheckCircle, stringResource(R.string.home_working)) + Icon(Icons.Filled.LocalFireDepartment, stringResource(R.string.home_working)) Column(Modifier.padding(start = 20.dp)) { Text( text = workingText, @@ -265,7 +276,7 @@ private fun StatusCard( } kernelVersion.isGKI() -> { - Icon(Icons.Outlined.Warning, stringResource(R.string.home_not_installed)) + Icon(Icons.Filled.AutoFixHigh, stringResource(R.string.home_not_installed)) Column(Modifier.padding(start = 20.dp)) { Text( text = stringResource(R.string.home_not_installed), @@ -280,15 +291,15 @@ private fun StatusCard( } else -> { - Icon(Icons.Outlined.Block, stringResource(R.string.home_unsupported)) + Icon(Icons.Filled.Dangerous, stringResource(R.string.home_failure)) Column(Modifier.padding(start = 20.dp)) { Text( - text = stringResource(R.string.home_unsupported), + text = stringResource(R.string.home_failure), style = MaterialTheme.typography.titleMedium ) Spacer(Modifier.height(4.dp)) Text( - text = stringResource(R.string.home_unsupported_reason), + text = stringResource(R.string.home_failure_reason), style = MaterialTheme.typography.bodyMedium ) } @@ -320,61 +331,6 @@ fun WarningCard( } } -@Composable -fun LearnMoreCard() { - val uriHandler = LocalUriHandler.current - val url = stringResource(R.string.home_learn_kernelsu_url) - - ElevatedCard { - - Row(modifier = Modifier - .fillMaxWidth() - .clickable { - uriHandler.openUri(url) - } - .padding(24.dp), verticalAlignment = Alignment.CenterVertically) { - Column { - Text( - text = stringResource(R.string.home_learn_kernelsu), - style = MaterialTheme.typography.titleSmall - ) - Spacer(Modifier.height(4.dp)) - Text( - text = stringResource(R.string.home_click_to_learn_kernelsu), - style = MaterialTheme.typography.bodyMedium - ) - } - } - } -} - -@Composable -fun DonateCard() { - val uriHandler = LocalUriHandler.current - - ElevatedCard { - - Row(modifier = Modifier - .fillMaxWidth() - .clickable { - uriHandler.openUri("https://patreon.com/weishu") - } - .padding(24.dp), verticalAlignment = Alignment.CenterVertically) { - Column { - Text( - text = stringResource(R.string.home_support_title), - style = MaterialTheme.typography.titleSmall - ) - Spacer(Modifier.height(4.dp)) - Text( - text = stringResource(R.string.home_support_content), - style = MaterialTheme.typography.bodyMedium - ) - } - } - } -} - @Composable private fun InfoCard() { val context = LocalContext.current @@ -389,33 +345,140 @@ private fun InfoCard() { val uname = Os.uname() @Composable - fun InfoCardItem(label: String, content: String) { - contents.appendLine(label).appendLine(content).appendLine() - Text(text = label, style = MaterialTheme.typography.bodyLarge) - Text(text = content, style = MaterialTheme.typography.bodyMedium) + fun InfoCardItem(label: String, content: String, icon: ImageVector? = null) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (icon != null) { + Icon( + imageVector = icon, + contentDescription = null, + modifier = Modifier + .padding(end = 16.dp) + ) + } + Column { + Text( + text = label, + style = MaterialTheme.typography.bodyLarge + ) + Text( + text = content, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(top = 4.dp) + ) + } + } + } - InfoCardItem(stringResource(R.string.home_kernel), uname.release) + + InfoCardItem(stringResource(R.string.home_kernel), + uname.release, + icon = Icons.Filled.Memory, + ) + + Spacer(Modifier.height(16.dp)) + InfoCardItem( + stringResource(R.string.home_android), + "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})", + icon = Icons.Filled.Android, + + ) Spacer(Modifier.height(16.dp)) val managerVersion = getManagerVersion(context) InfoCardItem( stringResource(R.string.home_manager_version), - "${managerVersion.first} (${managerVersion.second})" + "${managerVersion.first}-next (${managerVersion.second})", + icon = Icons.AutoMirrored.Filled.Article, ) Spacer(Modifier.height(16.dp)) - InfoCardItem(stringResource(R.string.home_fingerprint), Build.FINGERPRINT) - - Spacer(Modifier.height(16.dp)) - InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus()) + InfoCardItem( + label = stringResource(R.string.home_selinux_status), + content = getSELinuxStatus(), + icon = Icons.Filled.Security, + ) } } } -fun getManagerVersion(context: Context): Pair { - val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) - return Pair(packageInfo.versionName, packageInfo.versionCode) +@Composable +fun NextCard() { + val uriHandler = LocalUriHandler.current + val url = stringResource(R.string.home_next_kernelsu_repo) + + ElevatedCard { + + Row(modifier = Modifier + .fillMaxWidth() + .clickable { + uriHandler.openUri(url) + } + .padding(24.dp), verticalAlignment = Alignment.CenterVertically) { + Column { + Text( + text = stringResource(R.string.home_next_kernelsu), + style = MaterialTheme.typography.titleSmall + ) + Spacer(Modifier.height(4.dp)) + Text( + text = stringResource(R.string.home_next_kernelsu_body), + style = MaterialTheme.typography.bodyMedium + ) + } + } + } +} + +@Composable +fun EXperimentalCard() { + /*val uriHandler = LocalUriHandler.current + val url = stringResource(R.string.home_experimental_kernelsu_repo) + */ + + ElevatedCard { + + Row(modifier = Modifier + .fillMaxWidth() + /*.clickable { + uriHandler.openUri(url) + } + */ + .padding(24.dp), verticalAlignment = Alignment.CenterVertically) { + Column { + Text( + text = stringResource(R.string.home_experimental_kernelsu), + style = MaterialTheme.typography.titleSmall + ) + Spacer(Modifier.height(4.dp)) + Text( + text = stringResource(R.string.home_experimental_kernelsu_body), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(Modifier.height(4.dp)) + Text( + text = stringResource(R.string.home_experimental_kernelsu_body_point_1), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(Modifier.height(2.dp)) + Text( + text = stringResource(R.string.home_experimental_kernelsu_body_point_2), + style = MaterialTheme.typography.bodyMedium + ) + Spacer(Modifier.height(2.dp)) + Text( + text = stringResource(R.string.home_experimental_kernelsu_body_point_3), + style = MaterialTheme.typography.bodyMedium + ) + } + } + } +} + +fun getManagerVersion(context: Context): Pair { + val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!! + val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo) + return Pair(packageInfo.versionName!!, versionCode) } @Preview @@ -439,4 +502,4 @@ private fun WarningCardPreview() { MaterialTheme.colorScheme.outlineVariant, onClick = {}) } -} \ No newline at end of file +} diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Install.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Install.kt similarity index 70% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Install.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Install.kt index 71b5c9756909..f19a6f659e6d 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Install.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Install.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import android.app.Activity import android.content.Intent @@ -6,11 +6,19 @@ import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.StringRes -import androidx.compose.foundation.clickable +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.interaction.MutableInteractionSource 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.fillMaxWidth +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.selection.toggleable +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.FileUpload @@ -23,6 +31,9 @@ import androidx.compose.material3.RadioButton import androidx.compose.material3.Scaffold 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 @@ -31,7 +42,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.maxkeppeker.sheets.core.models.base.Header @@ -40,25 +53,27 @@ import com.maxkeppeler.sheets.list.ListDialog import com.maxkeppeler.sheets.list.models.ListOption import com.maxkeppeler.sheets.list.models.ListSelection import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.DialogHandle -import me.weishu.kernelsu.ui.component.rememberConfirmDialog -import me.weishu.kernelsu.ui.component.rememberCustomDialog -import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination -import me.weishu.kernelsu.ui.util.LkmSelection -import me.weishu.kernelsu.ui.util.getCurrentKmi -import me.weishu.kernelsu.ui.util.getSupportedKmis -import me.weishu.kernelsu.ui.util.isAbDevice -import me.weishu.kernelsu.ui.util.isInitBoot -import me.weishu.kernelsu.ui.util.rootAvailable +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.DialogHandle +import com.rifsxd.ksunext.ui.component.rememberConfirmDialog +import com.rifsxd.ksunext.ui.component.rememberCustomDialog +import com.rifsxd.ksunext.ui.util.LkmSelection +import com.rifsxd.ksunext.ui.util.getCurrentKmi +import com.rifsxd.ksunext.ui.util.getSupportedKmis +import com.rifsxd.ksunext.ui.util.isAbDevice +import com.rifsxd.ksunext.ui.util.isInitBoot +import com.rifsxd.ksunext.ui.util.rootAvailable /** * @author weishu * @date 2024/3/12. */ -@Destination +@OptIn(ExperimentalMaterial3Api::class) +@Destination @Composable fun InstallScreen(navigator: DestinationsNavigator) { var installMethod by remember { @@ -113,12 +128,24 @@ fun InstallScreen(navigator: DestinationsNavigator) { }) } - Scaffold(topBar = { - TopBar( - onBack = { navigator.popBackStack() }, onLkmUpload = onLkmUpload - ) - }) { - Column(modifier = Modifier.padding(it)) { + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + + Scaffold( + topBar = { + TopBar( + onBack = { navigator.popBackStack() }, + onLkmUpload = onLkmUpload, + scrollBehavior = scrollBehavior + ) + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .nestedScroll(scrollBehavior.nestedScrollConnection) + .verticalScroll(rememberScrollState()) + ) { SelectInstallMethod { method -> installMethod = method } @@ -231,16 +258,31 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) { Column { radioOptions.forEach { option -> - Row(verticalAlignment = Alignment.CenterVertically, + val interactionSource = remember { MutableInteractionSource() } + Row( + verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .clickable { + .toggleable( + value = option.javaClass == selectedOption?.javaClass, + onValueChange = { + onClick(option) + }, + role = Role.RadioButton, + indication = LocalIndication.current, + interactionSource = interactionSource + ) + ) { + RadioButton( + selected = option.javaClass == selectedOption?.javaClass, + onClick = { onClick(option) - }) { - RadioButton(selected = option.javaClass == selectedOption?.javaClass, onClick = { - onClick(option) - }) - Column { + }, + interactionSource = interactionSource + ) + Column( + modifier = Modifier.padding(vertical = 12.dp) + ) { Text( text = stringResource(id = option.label), fontSize = MaterialTheme.typography.titleMedium.fontSize, @@ -292,20 +334,28 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle { @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) { - TopAppBar(title = { Text(stringResource(R.string.install)) }, navigationIcon = { - IconButton( - onClick = onBack - ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } - }, actions = { - IconButton(onClick = onLkmUpload) { - Icon(Icons.Filled.FileUpload, contentDescription = null) - } - }) +private fun TopBar( + onBack: () -> Unit = {}, + onLkmUpload: () -> Unit = {}, + scrollBehavior: TopAppBarScrollBehavior? = null +) { + TopAppBar( + title = { Text(stringResource(R.string.install)) }, navigationIcon = { + IconButton( + onClick = onBack + ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } + }, actions = { + IconButton(onClick = onLkmUpload) { + Icon(Icons.Filled.FileUpload, contentDescription = null) + } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior + ) } @Composable @Preview -fun SelectInstall_Preview() { +fun SelectInstallPreview() { InstallScreen(EmptyDestinationsNavigator) } \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt new file mode 100644 index 000000000000..b37e1b7a3f3d --- /dev/null +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt @@ -0,0 +1,754 @@ +package com.rifsxd.ksunext.ui.screen + +import android.app.Activity.RESULT_OK +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.util.Log +import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.selection.toggleable +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.Wysiwyg +import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.outlined.* +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +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.Alignment +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.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 +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination +import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.ConfirmResult +import com.rifsxd.ksunext.ui.component.rememberConfirmDialog +import com.rifsxd.ksunext.ui.component.rememberLoadingDialog +import com.rifsxd.ksunext.ui.util.DownloadListener +import com.rifsxd.ksunext.ui.util.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.download +import com.rifsxd.ksunext.ui.util.hasMagisk +import com.rifsxd.ksunext.ui.util.reboot +import com.rifsxd.ksunext.ui.util.toggleModule +import com.rifsxd.ksunext.ui.util.uninstallModule +import com.rifsxd.ksunext.ui.util.restoreModule +import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel +import com.rifsxd.ksunext.ui.webui.WebUIActivity +import okhttp3.OkHttpClient + +@OptIn(ExperimentalMaterial3Api::class) +@Destination +@Composable +fun ModuleScreen(navigator: DestinationsNavigator) { + val viewModel = viewModel() + val context = LocalContext.current + val snackBarHost = LocalSnackbarHost.current + + LaunchedEffect(Unit) { + if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) { + viewModel.fetchModuleList() + } + } + + val isSafeMode = Natives.isSafeMode + val hasMagisk = hasMagisk() + + val hideInstallButton = isSafeMode || hasMagisk + + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + + var zipUri by remember { mutableStateOf(null) } + var showConfirmDialog by remember { mutableStateOf(false) } + + Scaffold( + topBar = { + TopAppBar( + scrollBehavior = scrollBehavior, + title = { Text(stringResource(R.string.module)) }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) + ) + }, + floatingActionButton = { + if (!hideInstallButton) { + val moduleInstall = stringResource(id = R.string.module_install) + val selectZipLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode != RESULT_OK) { + return@rememberLauncherForActivityResult + } + val data = result.data ?: return@rememberLauncherForActivityResult + val uri = data.data ?: return@rememberLauncherForActivityResult + + // save the selected Uri and trigger confirmation dialog + zipUri = uri + showConfirmDialog = true + } + + ExtendedFloatingActionButton( + onClick = { + // select the zip file to install + val intent = Intent(Intent.ACTION_GET_CONTENT).apply { + type = "application/zip" + } + selectZipLauncher.launch(intent) + }, + icon = { Icon(Icons.Filled.Add, moduleInstall) }, + text = { Text(text = moduleInstall) }, + ) + } + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + snackbarHost = { SnackbarHost(hostState = snackBarHost) } + ) { innerPadding -> + // confirmation dialog + if (showConfirmDialog && zipUri != null) { + // extract the module name from the zipUri + val moduleName = zipUri?.lastPathSegment?.substringAfterLast('/') ?: "Unknown Module" + + AlertDialog( + onDismissRequest = { showConfirmDialog = false }, + confirmButton = { + TextButton(onClick = { + showConfirmDialog = false + navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(zipUri!!))) + + viewModel.markNeedRefresh() + + }) { + Text(stringResource(R.string.confirm)) + } + }, + dismissButton = { + TextButton(onClick = { showConfirmDialog = false }) { + Text(stringResource(android.R.string.cancel)) + } + }, + title = { Text(stringResource(R.string.confirm_module_installation)) }, + text = { + Text( + stringResource(R.string.module_install_prompt_with_name, moduleName) + ) + } + ) + } + + when { + hasMagisk -> { + Box( + modifier = Modifier + .fillMaxSize() + .padding(24.dp), + contentAlignment = Alignment.Center + ) { + Text( + stringResource(R.string.module_magisk_conflict), + textAlign = TextAlign.Center, + ) + } + } + else -> { + ModuleList( + navigator, + viewModel = viewModel, + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + boxModifier = Modifier.padding(innerPadding), + onInstallModule = { + navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it))) + }, + onClickModule = { id, name, hasWebUi -> + if (hasWebUi) { + context.startActivity( + Intent(context, WebUIActivity::class.java) + .setData(Uri.parse("kernelsu://webui/$id")) + .putExtra("id", id) + .putExtra("name", name) + ) + } + }, + context = context, + snackBarHost = snackBarHost + ) + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun ModuleList( + navigator: DestinationsNavigator, + viewModel: ModuleViewModel, + modifier: Modifier = Modifier, + boxModifier: Modifier = Modifier, + onInstallModule: (Uri) -> Unit, + onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit, + context: Context, + snackBarHost: SnackbarHostState +) { + val failedEnable = stringResource(R.string.module_failed_to_enable) + val failedDisable = stringResource(R.string.module_failed_to_disable) + val failedUninstall = stringResource(R.string.module_uninstall_failed) + val failedRestore = stringResource(R.string.module_restore_failed) + val successUninstall = stringResource(R.string.module_uninstall_success) + val successRestore = stringResource(R.string.module_restore_success) + val reboot = stringResource(R.string.reboot) + val rebootToApply = stringResource(R.string.reboot_to_apply) + val moduleStr = stringResource(R.string.module) + val uninstall = stringResource(R.string.uninstall) + val restore = stringResource(R.string.restore) + val cancel = stringResource(android.R.string.cancel) + val moduleUninstallConfirm = stringResource(R.string.module_uninstall_confirm) + val moduleRestoreConfirm = stringResource(R.string.module_restore_confirm) + val updateText = stringResource(R.string.module_update) + val changelogText = stringResource(R.string.module_changelog) + val downloadingText = stringResource(R.string.module_downloading) + val startDownloadingText = stringResource(R.string.module_start_downloading) + val fetchChangeLogFailed = stringResource(R.string.module_changelog_failed) + + val loadingDialog = rememberLoadingDialog() + val confirmDialog = rememberConfirmDialog() + + suspend fun onModuleUpdate( + module: ModuleViewModel.ModuleInfo, + changelogUrl: String, + downloadUrl: String, + fileName: String + ) { + val changelogResult = loadingDialog.withLoading { + withContext(Dispatchers.IO) { + runCatching { + OkHttpClient().newCall( + okhttp3.Request.Builder().url(changelogUrl).build() + ).execute().body!!.string() + } + } + } + + val showToast: suspend (String) -> Unit = { msg -> + withContext(Dispatchers.Main) { + Toast.makeText( + context, + msg, + Toast.LENGTH_SHORT + ).show() + } + } + + val changelog = changelogResult.getOrElse { + showToast(fetchChangeLogFailed.format(it.message)) + return + }.ifBlank { + showToast(fetchChangeLogFailed.format(module.name)) + return + } + + // changelog is not empty, show it and wait for confirm + val confirmResult = confirmDialog.awaitConfirm( + changelogText, + content = changelog, + markdown = true, + confirm = updateText, + ) + + if (confirmResult != ConfirmResult.Confirmed) { + return + } + + showToast(startDownloadingText.format(module.name)) + + val downloading = downloadingText.format(module.name) + withContext(Dispatchers.IO) { + download( + context, + downloadUrl, + fileName, + downloading, + onDownloaded = onInstallModule, + onDownloading = { + launch(Dispatchers.Main) { + Toast.makeText(context, downloading, Toast.LENGTH_SHORT).show() + } + } + ) + } + } + + suspend fun onModuleUninstall(module: ModuleViewModel.ModuleInfo) { + val confirmResult = confirmDialog.awaitConfirm( + moduleStr, + content = moduleUninstallConfirm.format(module.name), + confirm = uninstall, + dismiss = cancel + ) + if (confirmResult != ConfirmResult.Confirmed) { + return + } + + val success = loadingDialog.withLoading { + withContext(Dispatchers.IO) { + uninstallModule(module.id) + } + } + + if (success) { + viewModel.fetchModuleList() + } + val message = if (success) { + successUninstall.format(module.name) + } else { + failedUninstall.format(module.name) + } + val actionLabel = if (success) { + reboot + } else { + null + } + val result = snackBarHost.showSnackbar( + message = message, + actionLabel = actionLabel, + duration = SnackbarDuration.Long + ) + if (result == SnackbarResult.ActionPerformed) { + reboot() + } + } + + suspend fun onModuleRestore(module: ModuleViewModel.ModuleInfo) { + val confirmResult = confirmDialog.awaitConfirm( + moduleStr, + content = moduleRestoreConfirm.format(module.name), + confirm = restore, + dismiss = cancel + ) + if (confirmResult != ConfirmResult.Confirmed) { + return + } + + val success = loadingDialog.withLoading { + withContext(Dispatchers.IO) { + restoreModule(module.id) + } + } + + if (success) { + viewModel.fetchModuleList() + } + val message = if (success) { + successRestore.format(module.name) + } else { + failedRestore.format(module.name) + } + } + PullToRefreshBox( + modifier = boxModifier, + onRefresh = { + viewModel.fetchModuleList() + }, + isRefreshing = viewModel.isRefreshing + ) { + LazyColumn( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = remember { + PaddingValues( + start = 16.dp, + top = 16.dp, + end = 16.dp, + bottom = 16.dp + 56.dp + 16.dp + 48.dp + 6.dp /* Scaffold Fab Spacing + Fab container height + SnackBar height */ + ) + }, + ) { + when { + viewModel.moduleList.isEmpty() -> { + item { + Box( + modifier = Modifier.fillParentMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + stringResource(R.string.module_empty), + textAlign = TextAlign.Center + ) + } + } + } + + else -> { + items(viewModel.moduleList) { module -> + var isChecked by rememberSaveable(module) { mutableStateOf(module.enabled) } + val scope = rememberCoroutineScope() + val updatedModule by produceState(initialValue = Triple("", "", "")) { + scope.launch(Dispatchers.IO) { + value = viewModel.checkUpdate(module) + } + } + + ModuleItem( + navigator = navigator, + module = module, + isChecked = isChecked, + updateUrl = updatedModule.first, + onUninstall = { + scope.launch { onModuleUninstall(module) } + }, + onRestore = { + scope.launch { onModuleRestore(module) } + }, + onCheckChanged = { + scope.launch { + val success = loadingDialog.withLoading { + withContext(Dispatchers.IO) { + toggleModule(module.id, !isChecked) + } + } + if (success) { + isChecked = it + viewModel.fetchModuleList() + + val result = snackBarHost.showSnackbar( + message = rebootToApply, + actionLabel = reboot, + duration = SnackbarDuration.Long + ) + if (result == SnackbarResult.ActionPerformed) { + reboot() + } + } else { + val message = if (isChecked) failedDisable else failedEnable + snackBarHost.showSnackbar(message.format(module.name)) + } + } + }, + onUpdate = { + scope.launch { + onModuleUpdate( + module, + updatedModule.third, + updatedModule.first, + "${module.name}-${updatedModule.second}.zip" + ) + } + }, + onClick = { + onClickModule(it.id, it.name, it.hasWebUi) + } + ) + + // fix last item shadow incomplete in LazyColumn + Spacer(Modifier.height(1.dp)) + } + } + } + } + + DownloadListener(context, onInstallModule) + + } +} + +@Composable +fun ModuleItem( + navigator: DestinationsNavigator, + module: ModuleViewModel.ModuleInfo, + isChecked: Boolean, + updateUrl: String, + onUninstall: (ModuleViewModel.ModuleInfo) -> Unit, + onRestore: (ModuleViewModel.ModuleInfo) -> Unit, + onCheckChanged: (Boolean) -> Unit, + onUpdate: (ModuleViewModel.ModuleInfo) -> Unit, + onClick: (ModuleViewModel.ModuleInfo) -> Unit +) { + ElevatedCard( + modifier = Modifier.fillMaxWidth() + ) { + val textDecoration = if (!module.remove) null else TextDecoration.LineThrough + val interactionSource = remember { MutableInteractionSource() } + val indication = LocalIndication.current + val viewModel = viewModel() + + 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) + + Column( + modifier = Modifier.fillMaxWidth(0.8f) + ) { + 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 + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + ) { + Switch( + enabled = !module.update, + checked = isChecked, + onCheckedChange = onCheckChanged, + interactionSource = if (!module.hasWebUi) interactionSource else null + ) + } + } + + 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(16.dp)) + + HorizontalDivider(thickness = Dp.Hairline) + + Spacer(modifier = Modifier.height(4.dp)) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + if (module.hasActionScript) { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + onClick = { + navigator.navigate(ExecuteModuleActionScreenDestination(module.id)) + viewModel.markNeedRefresh() + }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.PlayArrow, + contentDescription = null + ) + if (!module.hasWebUi && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + text = stringResource(R.string.action), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize + ) + } + } + + Spacer(modifier = Modifier.weight(0.1f, true)) + } + + if (module.hasWebUi) { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + onClick = { onClick(module) }, + interactionSource = interactionSource, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.AutoMirrored.Outlined.Wysiwyg, + contentDescription = null + ) + if (!module.hasActionScript && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.open) + ) + } + } + } + + Spacer(modifier = Modifier.weight(1f, true)) + + if (updateUrl.isNotEmpty()) { + Button( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + onClick = { onUpdate(module) }, + shape = ButtonDefaults.textShape, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Download, + contentDescription = null + ) + if (!module.hasActionScript || !module.hasWebUi) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.module_update) + ) + } + } + + Spacer(modifier = Modifier.weight(0.1f, true)) + } + + if (module.remove) { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + onClick = { onRestore(module) }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Restore, + contentDescription = null + ) + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.restore) + ) + } + } else { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + enabled = true, + onClick = { onUninstall(module) }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Delete, + contentDescription = null + ) + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.uninstall) + ) + } + } + } + } + } +} + +@Preview +@Composable +fun ModuleItemPreview() { + val module = ModuleViewModel.ModuleInfo( + id = "id", + name = "name", + version = "version", + versionCode = 1, + author = "author", + description = "I am a test module and i do nothing but show a very long description", + enabled = true, + update = true, + remove = false, + updateJson = "", + hasWebUi = false, + hasActionScript = false + ) + ModuleItem(EmptyDestinationsNavigator, module, true, "", {}, {}, {}, {}, {}) +} \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt similarity index 74% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt index 4f970f7ee331..735e5758b555 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Settings.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Settings.kt @@ -1,22 +1,23 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen -import android.content.ContentResolver import android.content.Context import android.content.Intent -import android.database.Cursor import android.net.Uri -import android.provider.OpenableColumns -import android.util.Log import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box 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.ArrowBack import androidx.compose.material.icons.automirrored.filled.Undo import androidx.compose.material.icons.filled.BugReport import androidx.compose.material.icons.filled.Compress @@ -29,15 +30,18 @@ import androidx.compose.material.icons.filled.RemoveModerator import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.filled.Update -import androidx.compose.material3.BottomSheetScaffold import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.ModalBottomSheet 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 @@ -48,6 +52,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.LineHeightStyle @@ -62,26 +67,26 @@ import com.maxkeppeler.sheets.list.ListDialog import com.maxkeppeler.sheets.list.models.ListOption import com.maxkeppeler.sheets.list.models.ListSelection import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination +import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import me.weishu.kernelsu.BuildConfig -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.AboutDialog -import me.weishu.kernelsu.ui.component.ConfirmResult -import me.weishu.kernelsu.ui.component.DialogHandle -import me.weishu.kernelsu.ui.component.SwitchItem -import me.weishu.kernelsu.ui.component.rememberConfirmDialog -import me.weishu.kernelsu.ui.component.rememberCustomDialog -import me.weishu.kernelsu.ui.component.rememberLoadingDialog -import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination -import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination -import me.weishu.kernelsu.ui.util.getBugreportFile -import me.weishu.kernelsu.ui.util.getFileNameFromUri -import me.weishu.kernelsu.ui.util.shrinkModules +import com.rifsxd.ksunext.BuildConfig +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.AboutDialog +import com.rifsxd.ksunext.ui.component.ConfirmResult +import com.rifsxd.ksunext.ui.component.DialogHandle +import com.rifsxd.ksunext.ui.component.SwitchItem +import com.rifsxd.ksunext.ui.component.rememberConfirmDialog +import com.rifsxd.ksunext.ui.component.rememberCustomDialog +import com.rifsxd.ksunext.ui.component.rememberLoadingDialog +import com.rifsxd.ksunext.ui.util.LocalSnackbarHost +import com.rifsxd.ksunext.ui.util.getBugreportFile import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -90,31 +95,52 @@ import java.time.format.DateTimeFormatter * @date 2023/1/1. */ @OptIn(ExperimentalMaterial3Api::class) -@Destination +@Destination @Composable fun SettingScreen(navigator: DestinationsNavigator) { + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + val snackBarHost = LocalSnackbarHost.current + Scaffold( topBar = { - TopBar(onBack = { - navigator.popBackStack() - }) - } + TopBar( + scrollBehavior = scrollBehavior + ) + }, + snackbarHost = { SnackbarHost(snackBarHost) }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { paddingValues -> val aboutDialog = rememberCustomDialog { AboutDialog(it) } val loadingDialog = rememberLoadingDialog() - val shrinkDialog = rememberConfirmDialog() Column( modifier = Modifier .padding(paddingValues) + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(rememberScrollState()) ) { val context = LocalContext.current val scope = rememberCoroutineScope() + val exportBugreportLauncher = rememberLauncherForActivityResult( + ActivityResultContracts.CreateDocument("application/gzip") + ) { uri: Uri? -> + if (uri == null) return@rememberLauncherForActivityResult + scope.launch(Dispatchers.IO) { + loadingDialog.show() + context.contentResolver.openOutputStream(uri)?.use { output -> + getBugreportFile(context).inputStream().use { + it.copyTo(output) + } + } + loadingDialog.hide() + snackBarHost.showSnackbar(context.getString(R.string.log_saved)) + } + } + val profileTemplate = stringResource(id = R.string.settings_profile_template) ListItem( leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) }, @@ -184,46 +210,25 @@ fun SettingScreen(navigator: DestinationsNavigator) { showBottomsheet = true } ) - if (showBottomsheet){ + if (showBottomsheet) { ModalBottomSheet( onDismissRequest = { showBottomsheet = false }, content = { - Row(modifier = Modifier.padding(10.dp) - .align(Alignment.CenterHorizontally) + Row( + modifier = Modifier + .padding(10.dp) + .align(Alignment.CenterHorizontally) ) { - Box{ + Box { Column( - modifier = Modifier.padding(16.dp) + modifier = Modifier + .padding(16.dp) .clickable { - scope.launch { - val bugreport = loadingDialog.withLoading { - withContext(Dispatchers.IO) { - getBugreportFile(context) - } - } - - val uri: Uri = - FileProvider.getUriForFile( - context, - "${BuildConfig.APPLICATION_ID}.fileprovider", - bugreport - ) - val filename = getFileNameFromUri(context , uri) - val savefile = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "application/zip" - putExtra(Intent.EXTRA_STREAM, uri) - putExtra(Intent.EXTRA_TITLE, filename) - flags = Intent.FLAG_GRANT_READ_URI_PERMISSION - } - context.startActivity( - Intent.createChooser( - savefile, - context.getString(R.string.save_log) - ) - ) - } + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm") + val current = LocalDateTime.now().format(formatter) + exportBugreportLauncher.launch("KernelSU_bugreport_${current}.tar.gz") + showBottomsheet = false } ) { Icon( @@ -243,11 +248,11 @@ fun SettingScreen(navigator: DestinationsNavigator) { ) } - } - Box{ + Box { Column( - modifier = Modifier.padding(16.dp) + modifier = Modifier + .padding(16.dp) .clickable { scope.launch { val bugreport = loadingDialog.withLoading { @@ -263,10 +268,11 @@ fun SettingScreen(navigator: DestinationsNavigator) { bugreport ) - val shareIntent = Intent(Intent.ACTION_SEND) - shareIntent.putExtra(Intent.EXTRA_STREAM, uri) - shareIntent.setDataAndType(uri, "application/zip") - shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + val shareIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_STREAM, uri) + setDataAndType(uri, "application/gzip") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } context.startActivity( Intent.createChooser( @@ -291,43 +297,15 @@ fun SettingScreen(navigator: DestinationsNavigator) { trim = LineHeightStyle.Trim.None ) } - ) } - } } } ) - - } - val shrink = stringResource(id = R.string.shrink_sparse_image) - val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message) - ListItem( - leadingContent = { - Icon( - Icons.Filled.Compress, - shrink - ) - }, - headlineContent = { Text(shrink) }, - modifier = Modifier.clickable { - scope.launch { - val result = - shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage) - if (result == ConfirmResult.Confirmed) { - loadingDialog.withLoading { - shrinkModules() - } - } - } - } - ) - - val lkmMode = - Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode + val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode if (lkmMode) { UninstallItem(navigator) { loadingDialog.withLoading(it) @@ -339,7 +317,7 @@ fun SettingScreen(navigator: DestinationsNavigator) { leadingContent = { Icon( Icons.Filled.ContactPage, - stringResource(id = R.string.about) + about ) }, headlineContent = { Text(about) }, @@ -350,6 +328,7 @@ fun SettingScreen(navigator: DestinationsNavigator) { } } } + @Composable fun UninstallItem( navigator: DestinationsNavigator, @@ -374,11 +353,9 @@ fun UninstallItem( UninstallType.PERMANENT -> navigator.navigate( FlashScreenDestination(FlashIt.FlashUninstall) ) - UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate( FlashScreenDestination(FlashIt.FlashRestore) ) - UninstallType.NONE -> Unit } } @@ -456,14 +433,13 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle { @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun TopBar(onBack: () -> Unit = {}) { +private fun TopBar( + scrollBehavior: TopAppBarScrollBehavior? = null +) { TopAppBar( title = { Text(stringResource(R.string.settings)) }, - navigationIcon = { - IconButton( - onClick = onBack - ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } - }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior ) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/SuperUser.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt similarity index 77% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/SuperUser.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt index 2eb2e770bb9d..736e3993a191 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/SuperUser.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/SuperUser.kt @@ -1,22 +1,21 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.pullrefresh.PullRefreshIndicator -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.* +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.* -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle @@ -26,27 +25,37 @@ import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage import coil.request.ImageRequest import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import kotlinx.coroutines.launch -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.SearchAppBar -import me.weishu.kernelsu.ui.screen.destinations.AppProfileScreenDestination -import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.SearchAppBar +import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel -@OptIn(ExperimentalMaterialApi::class) -@Destination +@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) +@Destination @Composable fun SuperUserScreen(navigator: DestinationsNavigator) { val viewModel = viewModel() val scope = rememberCoroutineScope() + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + val listState = rememberLazyListState() - LaunchedEffect(Unit) { + LaunchedEffect(key1 = navigator) { + viewModel.search = "" if (viewModel.appList.isEmpty()) { viewModel.fetchAppList() } } + LaunchedEffect(viewModel.search) { + if (viewModel.search.isEmpty()) { + listState.scrollToItem(0) + } + } + Scaffold( topBar = { SearchAppBar( @@ -91,32 +100,30 @@ fun SuperUserScreen(navigator: DestinationsNavigator) { } } }, + scrollBehavior = scrollBehavior ) - } + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { innerPadding -> - val refreshState = rememberPullRefreshState( - refreshing = viewModel.isRefreshing, - onRefresh = { scope.launch { viewModel.fetchAppList() } }, - ) - Box( - modifier = Modifier - .padding(innerPadding) - .pullRefresh(refreshState) + PullToRefreshBox( + modifier = Modifier.padding(innerPadding), + onRefresh = { + scope.launch { viewModel.fetchAppList() } + }, + isRefreshing = viewModel.isRefreshing ) { - LazyColumn(Modifier.fillMaxSize()) { + LazyColumn( + state = listState, + modifier = Modifier + .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection) + ) { items(viewModel.appList, key = { it.packageName + it.uid }) { app -> AppItem(app) { navigator.navigate(AppProfileScreenDestination(app)) } - } } - - PullRefreshIndicator( - refreshing = viewModel.isRefreshing, - state = refreshState, - modifier = Modifier.align(Alignment.TopCenter) - ) } } } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Template.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Template.kt similarity index 80% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Template.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Template.kt index bf353b0afa84..9c54f92310e2 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Template.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Template.kt @@ -1,14 +1,17 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import android.widget.Toast import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.ExperimentalMaterialApi @@ -17,9 +20,6 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.ImportExport import androidx.compose.material.icons.filled.Sync -import androidx.compose.material.pullrefresh.PullRefreshIndicator -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api @@ -31,6 +31,10 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -38,8 +42,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -47,22 +51,23 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.result.ResultRecipient import com.ramcosta.composedestinations.result.getOr import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination -import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.viewmodel.TemplateViewModel /** * @author weishu * @date 2023/10/20. */ -@OptIn(ExperimentalMaterialApi::class) -@Destination +@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) +@Destination @Composable fun AppProfileTemplateScreen( navigator: DestinationsNavigator, @@ -70,6 +75,7 @@ fun AppProfileTemplateScreen( ) { val viewModel = viewModel() val scope = rememberCoroutineScope() + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) LaunchedEffect(Unit) { if (viewModel.templateList.isEmpty()) { @@ -93,7 +99,8 @@ fun AppProfileTemplateScreen( Toast.makeText(context, msg, Toast.LENGTH_SHORT).show() } } - TopBar(onBack = { navigator.popBackStack() }, + TopBar( + onBack = { navigator.popBackStack() }, onSync = { scope.launch { viewModel.fetchTemplates(true) } }, @@ -124,7 +131,8 @@ fun AppProfileTemplateScreen( clipboardManager.setText(AnnotatedString(it)) } } - } + }, + scrollBehavior = scrollBehavior ) }, floatingActionButton = { @@ -141,29 +149,27 @@ fun AppProfileTemplateScreen( text = { Text(stringResource(id = R.string.app_profile_template_create)) }, ) }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { innerPadding -> - val refreshState = rememberPullRefreshState( - refreshing = viewModel.isRefreshing, - onRefresh = { scope.launch { viewModel.fetchTemplates() } }, - ) - Box( - modifier = Modifier - .padding(innerPadding) - .pullRefresh(refreshState) + PullToRefreshBox( + modifier = Modifier.padding(innerPadding), + isRefreshing = viewModel.isRefreshing, + onRefresh = { + scope.launch { viewModel.fetchTemplates() } + } ) { - LazyColumn(Modifier.fillMaxSize(), contentPadding = remember { - PaddingValues(bottom = 16.dp + 16.dp + 56.dp /* Scaffold Fab Spacing + Fab container height */) - }) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection), + contentPadding = remember { + PaddingValues(bottom = 16.dp + 56.dp + 16.dp /* Scaffold Fab Spacing + Fab container height */) + } + ) { items(viewModel.templateList, key = { it.id }) { app -> TemplateItem(navigator, app) } } - - PullRefreshIndicator( - refreshing = viewModel.isRefreshing, - state = refreshState, - modifier = Modifier.align(Alignment.TopCenter) - ) } } } @@ -209,7 +215,8 @@ private fun TopBar( onBack: () -> Unit, onSync: () -> Unit = {}, onImport: () -> Unit = {}, - onExport: () -> Unit = {} + onExport: () -> Unit = {}, + scrollBehavior: TopAppBarScrollBehavior? = null ) { TopAppBar( title = { @@ -254,6 +261,8 @@ private fun TopBar( }) } } - } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior ) } \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/TemplateEditor.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/TemplateEditor.kt similarity index 77% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/TemplateEditor.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/TemplateEditor.kt index b6b7cc8028ec..4850927b92c3 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/TemplateEditor.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/TemplateEditor.kt @@ -1,10 +1,14 @@ -package me.weishu.kernelsu.ui.screen +package com.rifsxd.ksunext.ui.screen import android.widget.Toast import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxWidth +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.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -22,6 +26,9 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold 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 @@ -30,6 +37,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.pointerInteropFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController @@ -37,22 +45,23 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.result.ResultBackNavigator -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.profile.RootProfileConfig -import me.weishu.kernelsu.ui.util.deleteAppProfileTemplate -import me.weishu.kernelsu.ui.util.getAppProfileTemplate -import me.weishu.kernelsu.ui.util.setAppProfileTemplate -import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel -import me.weishu.kernelsu.ui.viewmodel.toJSON +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.R +import com.rifsxd.ksunext.ui.component.profile.RootProfileConfig +import com.rifsxd.ksunext.ui.util.deleteAppProfileTemplate +import com.rifsxd.ksunext.ui.util.getAppProfileTemplate +import com.rifsxd.ksunext.ui.util.setAppProfileTemplate +import com.rifsxd.ksunext.ui.viewmodel.TemplateViewModel +import com.rifsxd.ksunext.ui.viewmodel.toJSON /** * @author weishu * @date 2023/10/20. */ -@OptIn(ExperimentalComposeUiApi::class) -@Destination +@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class) +@Destination @Composable fun TemplateEditorScreen( navigator: ResultBackNavigator, @@ -67,6 +76,8 @@ fun TemplateEditorScreen( mutableStateOf(initialTemplate) } + val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) + BackHandler { navigator.navigateBack(result = !readOnly) } @@ -106,12 +117,16 @@ fun TemplateEditorScreen( } else { Toast.makeText(context, saveTemplateFailed, Toast.LENGTH_SHORT).show() } - }) + }, + scrollBehavior = scrollBehavior + ) }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) ) { innerPadding -> Column( modifier = Modifier .padding(innerPadding) + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(rememberScrollState()) .pointerInteropFilter { // disable click and ripple if readOnly @@ -240,39 +255,44 @@ private fun TopBar( summary: String = "", onBack: () -> Unit, onDelete: () -> Unit = {}, - onSave: () -> Unit = {} + onSave: () -> Unit = {}, + scrollBehavior: TopAppBarScrollBehavior? = null ) { - TopAppBar(title = { - Column { - Text(title) - if (summary.isNotBlank()) { - Text( - text = summary, - style = MaterialTheme.typography.bodyMedium, + TopAppBar( + title = { + Column { + Text(title) + if (summary.isNotBlank()) { + Text( + text = summary, + style = MaterialTheme.typography.bodyMedium, + ) + } + } + }, navigationIcon = { + IconButton( + onClick = onBack + ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } + }, actions = { + if (readOnly) { + return@TopAppBar + } + IconButton(onClick = onDelete) { + Icon( + Icons.Filled.DeleteForever, + contentDescription = stringResource(id = R.string.app_profile_template_delete) ) } - } - }, navigationIcon = { - IconButton( - onClick = onBack - ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } - }, actions = { - if (readOnly) { - return@TopAppBar - } - IconButton(onClick = onDelete) { - Icon( - Icons.Filled.DeleteForever, - contentDescription = stringResource(id = R.string.app_profile_template_delete) - ) - } - IconButton(onClick = onSave) { - Icon( - imageVector = Icons.Filled.Save, - contentDescription = stringResource(id = R.string.app_profile_template_save) - ) - } - }) + IconButton(onClick = onSave) { + Icon( + imageVector = Icons.Filled.Save, + contentDescription = stringResource(id = R.string.app_profile_template_save) + ) + } + }, + windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), + scrollBehavior = scrollBehavior + ) } @Composable @@ -289,17 +309,14 @@ private fun TextEdit( value = text, modifier = Modifier.fillMaxWidth(), label = { Text(label) }, - suffix = - if (errorHint.isNotBlank()) { - { + suffix = { + if (errorHint.isNotBlank()) { Text( text = if (isError) errorHint else "", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error ) } - } else { - null }, isError = isError, keyboardOptions = KeyboardOptions( @@ -314,7 +331,7 @@ private fun TextEdit( } private fun isValidTemplateId(id: String): Boolean { - return Regex("""^([A-Za-z]{1}[A-Za-z\d_]*\.)*[A-Za-z][A-Za-z\d_]*$""").matches(id) + return Regex("""^([A-Za-z][A-Za-z\d_]*\.)*[A-Za-z][A-Za-z\d_]*$""").matches(id) } private fun isTemplateExist(id: String): Boolean { diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Color.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Color.kt similarity index 71% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Color.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Color.kt index 155cf4e248bc..675f4aefc688 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Color.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.theme +package com.rifsxd.ksunext.ui.theme import androidx.compose.ui.graphics.Color diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Theme.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Theme.kt similarity index 67% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Theme.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Theme.kt index 3b3945d0cdc5..896aa0eb0858 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Theme.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Theme.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.theme +package com.rifsxd.ksunext.ui.theme import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme @@ -7,12 +7,8 @@ import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme -import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import com.google.accompanist.systemuicontroller.rememberSystemUiController private val DarkColorScheme = darkColorScheme( primary = YELLOW, @@ -42,20 +38,6 @@ fun KernelSUTheme( else -> LightColorScheme } - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor( - color = colorScheme.surface, - darkIcons = !darkTheme - ) - - // To match the App Navbar color - systemUiController.setNavigationBarColor( - color = colorScheme.surfaceColorAtElevation(8.dp), - darkIcons = !darkTheme, - ) - } - MaterialTheme( colorScheme = colorScheme, typography = Typography, diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Type.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Type.kt similarity index 96% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Type.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Type.kt index e8d73313a330..27794e7076dc 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/theme/Type.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.theme +package com.rifsxd.ksunext.ui.theme import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/CompositionProvider.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/CompositionProvider.kt similarity index 86% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/CompositionProvider.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/CompositionProvider.kt index c1b57483a02f..d0da793cfa66 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/CompositionProvider.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/CompositionProvider.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.compositionLocalOf diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/Downloader.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/Downloader.kt similarity index 87% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/Downloader.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/Downloader.kt index 954cac50da30..64ac60ac2433 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/Downloader.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/Downloader.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util import android.annotation.SuppressLint import android.app.DownloadManager @@ -7,11 +7,11 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.Uri -import android.os.Build import android.os.Environment import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect -import me.weishu.kernelsu.ui.util.module.LatestVersionInfo +import androidx.core.content.ContextCompat +import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo /** * @author weishu @@ -26,8 +26,7 @@ fun download( onDownloaded: (Uri) -> Unit = {}, onDownloading: () -> Unit = {} ) { - val downloadManager = - context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val query = DownloadManager.Query() query.setFilterByStatus(DownloadManager.STATUS_RUNNING or DownloadManager.STATUS_PAUSED or DownloadManager.STATUS_PENDING) @@ -63,7 +62,8 @@ fun download( } fun checkNewVersion(): LatestVersionInfo { - val url = "https://api.github.com/repos/tiann/KernelSU/releases/latest" + // Next version updates + val url = "https://api.github.com/repos/rifsxd/KernelSU-Next/releases/latest" // default null value if failed val defaultValue = LatestVersionInfo() runCatching { @@ -130,18 +130,12 @@ fun DownloadListener(context: Context, onDownloaded: (Uri) -> Unit) { } } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - context.registerReceiver( - receiver, - IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), - Context.RECEIVER_EXPORTED - ) - } else { - context.registerReceiver( - receiver, - IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) - ) - } + ContextCompat.registerReceiver( + context, + receiver, + IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), + ContextCompat.RECEIVER_EXPORTED + ) onDispose { context.unregisterReceiver(receiver) } diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HanziToPinyin.java b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HanziToPinyin.java similarity index 99% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HanziToPinyin.java rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HanziToPinyin.java index d3d57cefe2ea..0f6247080b0c 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HanziToPinyin.java +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HanziToPinyin.java @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.util; +package com.rifsxd.ksunext.ui.util; /* * Copyright (C) 2009 The Android Open Source Project * diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HyperlinkText.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HyperlinkText.kt similarity index 98% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HyperlinkText.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HyperlinkText.kt index 4473b828aa1a..0c1cf43b8828 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/HyperlinkText.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/HyperlinkText.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.material3.MaterialTheme diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt similarity index 90% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt index 108e08f2a139..b717efa8be63 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/KsuCli.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/KsuCli.kt @@ -1,25 +1,24 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util import android.content.ContentResolver import android.content.Context import android.database.Cursor import android.net.Uri -import android.os.Build import android.os.Environment import android.os.Parcelable import android.os.SystemClock import android.provider.OpenableColumns +import android.system.Os import android.util.Log import com.topjohnwu.superuser.CallbackList import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.ShellUtils -import com.topjohnwu.superuser.io.SuFile import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize -import me.weishu.kernelsu.BuildConfig -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.ksuApp +import com.rifsxd.ksunext.BuildConfig +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.ksuApp import org.json.JSONArray import java.io.File @@ -52,10 +51,10 @@ inline fun withNewRootShell( return createRootShell(globalMnt).use(block) } -fun getFileNameFromUri(context: Context, uri: Uri): String? { +fun Uri.getFileName(context: Context): String? { var fileName: String? = null val contentResolver: ContentResolver = context.contentResolver - val cursor: Cursor? = contentResolver.query(uri, null, null, null, null) + val cursor: Cursor? = contentResolver.query(this, null, null, null, null) cursor?.use { if (it.moveToFirst()) { fileName = it.getString(it.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)) @@ -143,6 +142,13 @@ fun uninstallModule(id: String): Boolean { return result } +fun restoreModule(id: String): Boolean { + val cmd = "module restore $id" + val result = execKsud(cmd, true) + Log.i(TAG, "restore module $id result: $result") + return result +} + private fun flashWithIO( cmd: String, onStdout: (String) -> Unit, @@ -189,6 +195,30 @@ fun flashModule( } } +fun runModuleAction( + moduleId: String, onStdout: (String) -> Unit, onStderr: (String) -> Unit +): Boolean { + val shell = getRootShell() + + val stdoutCallback: CallbackList = object : CallbackList() { + override fun onAddElement(s: String?) { + onStdout(s ?: "") + } + } + + val stderrCallback: CallbackList = object : CallbackList() { + override fun onAddElement(s: String?) { + onStderr(s ?: "") + } + } + + val result = shell.newJob().add("${getKsuDaemonPath()} module action $moduleId") + .to(stdoutCallback, stderrCallback).exec() + Log.i("KernelSU", "Module runAction result: $result") + + return result.isSuccess +} + fun restoreBoot( onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit ): Boolean { @@ -207,10 +237,6 @@ fun uninstallPermanently( return result.isSuccess } -suspend fun shrinkModules(): Boolean = withContext(Dispatchers.IO) { - execKsud("module shrink", true) -} - @Parcelize sealed class LkmSelection : Parcelable { data class LkmUri(val uri: Uri) : LkmSelection() @@ -312,18 +338,7 @@ fun isAbDevice(): Boolean { } fun isInitBoot(): Boolean { - val shell = getRootShell() - if (shell.isRoot) { - // if we have root, use /dev/block/by-name/init_boot to check - val abDevice = isAbDevice() - val initBootBlock = "/dev/block/by-name/init_boot${if (abDevice) "_a" else ""}" - val file = SuFile(initBootBlock) - file.shell = shell - return file.exists() - } - // https://source.android.com/docs/core/architecture/partitions/generic-boot - return ShellUtils.fastCmd(shell, "getprop ro.product.first_api_level").trim() - .toInt() >= Build.VERSION_CODES.TIRAMISU + return !Os.uname().release.contains("android12-") } suspend fun getCurrentKmi(): String = withContext(Dispatchers.IO) { @@ -339,12 +354,6 @@ suspend fun getSupportedKmis(): List = withContext(Dispatchers.IO) { out.filter { it.isNotBlank() }.map { it.trim() } } -fun overlayFsAvailable(): Boolean { - val shell = getRootShell() - // check /proc/filesystems - return ShellUtils.fastCmdResult(shell, "cat /proc/filesystems | grep overlay") -} - fun hasMagisk(): Boolean { val shell = getRootShell(true) val result = shell.newJob().add("which magisk").exec() diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/LogEvent.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/LogEvent.kt similarity index 95% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/LogEvent.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/LogEvent.kt index 19eb1df18991..79063807b215 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/LogEvent.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/LogEvent.kt @@ -1,16 +1,12 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util -import android.content.ContentResolver import android.content.Context -import android.net.Uri import android.os.Build -import android.os.ParcelFileDescriptor import android.system.Os import com.topjohnwu.superuser.ShellUtils -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.ui.screen.getManagerVersion +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.ui.screen.getManagerVersion import java.io.File -import java.io.FileOutputStream import java.io.FileWriter import java.io.PrintWriter import java.time.LocalDateTime @@ -75,6 +71,7 @@ fun getBugreportFile(context: Context): File { pw.println("MODEL: " + Build.MODEL) pw.println("PRODUCT: " + Build.PRODUCT) pw.println("MANUFACTURER: " + Build.MANUFACTURER) + pw.println("ANDROID: " + Build.VERSION.RELEASE) pw.println("SDK: " + Build.VERSION.SDK_INT) pw.println("PREVIEW_SDK: " + Build.VERSION.PREVIEW_SDK_INT) pw.println("FINGERPRINT: " + Build.FINGERPRINT) diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/SELinuxChecker.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/SELinuxChecker.kt similarity index 94% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/SELinuxChecker.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/SELinuxChecker.kt index 78346dd9412c..7b5c3c362fd6 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/SELinuxChecker.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/SELinuxChecker.kt @@ -1,9 +1,9 @@ -package me.weishu.kernelsu.ui.util +package com.rifsxd.ksunext.ui.util -import androidx.compose.ui.res.stringResource import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource import com.topjohnwu.superuser.Shell -import me.weishu.kernelsu.R +import com.rifsxd.ksunext.R @Composable fun getSELinuxStatus(): String { diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/module/LatestVersionInfo.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/module/LatestVersionInfo.kt similarity index 75% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/module/LatestVersionInfo.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/module/LatestVersionInfo.kt index 374b3853ab1a..1fc4031421df 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/util/module/LatestVersionInfo.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/util/module/LatestVersionInfo.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.util.module +package com.rifsxd.ksunext.ui.util.module data class LatestVersionInfo( val versionCode : Int = 0, diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/ModuleViewModel.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt similarity index 93% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/ModuleViewModel.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt index 013453fbfeed..4312fa2eaf3b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/ModuleViewModel.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.viewmodel +package com.rifsxd.ksunext.ui.viewmodel import android.os.SystemClock import android.util.Log @@ -10,8 +10,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import me.weishu.kernelsu.ui.util.listModules -import me.weishu.kernelsu.ui.util.overlayFsAvailable +import com.rifsxd.ksunext.ui.util.listModules import org.json.JSONArray import org.json.JSONObject import java.text.Collator @@ -36,6 +35,7 @@ class ModuleViewModel : ViewModel() { val remove: Boolean, val updateJson: String, val hasWebUi: Boolean, + val hasActionScript: Boolean, ) data class ModuleUpdateInfo( @@ -48,9 +48,6 @@ class ModuleViewModel : ViewModel() { var isRefreshing by mutableStateOf(false) private set - var isOverlayAvailable by mutableStateOf(overlayFsAvailable()) - private set - val moduleList by derivedStateOf { val comparator = compareBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id) modules.sortedWith(comparator).also { @@ -74,8 +71,6 @@ class ModuleViewModel : ViewModel() { val start = SystemClock.elapsedRealtime() kotlin.runCatching { - isOverlayAvailable = overlayFsAvailable() - val result = listModules() Log.i(TAG, "result: $result") @@ -87,7 +82,6 @@ class ModuleViewModel : ViewModel() { .map { obj -> ModuleInfo( obj.getString("id"), - obj.optString("name"), obj.optString("author", "Unknown"), obj.optString("version", "Unknown"), @@ -97,7 +91,8 @@ class ModuleViewModel : ViewModel() { obj.getBoolean("update"), obj.getBoolean("remove"), obj.optString("updateJson"), - obj.optBoolean("web") + obj.optBoolean("web"), + obj.optBoolean("action") ) }.toList() isNeedRefresh = false diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/SuperUserViewModel.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt similarity index 91% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/SuperUserViewModel.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt index 37e05aa82aff..76a630e625d3 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/SuperUserViewModel.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/SuperUserViewModel.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.viewmodel +package com.rifsxd.ksunext.ui.viewmodel import android.content.ComponentName import android.content.Intent @@ -18,12 +18,12 @@ import com.topjohnwu.superuser.Shell import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize -import me.weishu.kernelsu.IKsuInterface -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.ksuApp -import me.weishu.kernelsu.ui.KsuService -import me.weishu.kernelsu.ui.util.HanziToPinyin -import me.weishu.kernelsu.ui.util.KsuCli +import com.rifsxd.ksunext.IKsuInterface +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.ksuApp +import com.rifsxd.ksunext.ui.KsuService +import com.rifsxd.ksunext.ui.util.HanziToPinyin +import com.rifsxd.ksunext.ui.util.KsuCli import java.text.Collator import java.util.* import kotlin.coroutines.resume @@ -45,7 +45,7 @@ class SuperUserViewModel : ViewModel() { val packageName: String get() = packageInfo.packageName val uid: Int - get() = packageInfo.applicationInfo.uid + get() = packageInfo.applicationInfo!!.uid val allowSu: Boolean get() = profile != null && profile.allowSu @@ -90,7 +90,7 @@ class SuperUserViewModel : ViewModel() { .toPinyinString(it.label).contains(search, true) }.filter { it.uid == 2000 // Always show shell - || showSystemApps || it.packageInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) == 0 + || showSystemApps || it.packageInfo.applicationInfo!!.flags.and(ApplicationInfo.FLAG_SYSTEM) == 0 } } @@ -146,7 +146,7 @@ class SuperUserViewModel : ViewModel() { apps = packages.map { val appInfo = it.applicationInfo - val uid = appInfo.uid + val uid = appInfo!!.uid val profile = Natives.getAppProfile(it.packageName, uid) AppInfo( label = appInfo.loadLabel(pm).toString(), diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/TemplateViewModel.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/TemplateViewModel.kt similarity index 97% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/TemplateViewModel.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/TemplateViewModel.kt index cbed82f21c05..9c5d3041c69b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/viewmodel/TemplateViewModel.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/TemplateViewModel.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.viewmodel +package com.rifsxd.ksunext.ui.viewmodel import android.os.Parcelable import android.util.Log @@ -10,12 +10,12 @@ import androidx.lifecycle.ViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.profile.Capabilities -import me.weishu.kernelsu.profile.Groups -import me.weishu.kernelsu.ui.util.getAppProfileTemplate -import me.weishu.kernelsu.ui.util.listAppProfileTemplates -import me.weishu.kernelsu.ui.util.setAppProfileTemplate +import com.rifsxd.ksunext.Natives +import com.rifsxd.ksunext.profile.Capabilities +import com.rifsxd.ksunext.profile.Groups +import com.rifsxd.ksunext.ui.util.getAppProfileTemplate +import com.rifsxd.ksunext.ui.util.listAppProfileTemplates +import com.rifsxd.ksunext.ui.util.setAppProfileTemplate import okhttp3.OkHttpClient import okhttp3.Request import org.json.JSONArray diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/MimeUtil.java b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/MimeUtil.java similarity index 98% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/MimeUtil.java rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/MimeUtil.java index 1fc2f4a4ceab..e02ac462c470 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/MimeUtil.java +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/MimeUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package me.weishu.kernelsu.ui.webui; +package com.rifsxd.ksunext.ui.webui; import java.net.URLConnection; diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/SuFilePathHandler.java b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuFilePathHandler.java similarity index 99% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/SuFilePathHandler.java rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuFilePathHandler.java index ff450e8e9cfe..22fd75bed8fb 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/SuFilePathHandler.java +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/SuFilePathHandler.java @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.webui; +package com.rifsxd.ksunext.ui.webui; import android.content.Context; import android.util.Log; diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebUIActivity.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt similarity index 53% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebUIActivity.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt index eccb002a1688..ba547117fdef 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebUIActivity.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebUIActivity.kt @@ -1,17 +1,22 @@ -package me.weishu.kernelsu.ui.webui +package com.rifsxd.ksunext.ui.webui import android.annotation.SuppressLint import android.app.ActivityManager -import android.content.Context +import android.os.Build import android.os.Bundle +import android.view.ViewGroup.MarginLayoutParams import android.webkit.WebResourceRequest import android.webkit.WebResourceResponse import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.ComponentActivity +import androidx.activity.enableEdgeToEdge +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updateLayoutParams import androidx.webkit.WebViewAssetLoader import com.topjohnwu.superuser.Shell -import me.weishu.kernelsu.ui.util.createRootShell +import com.rifsxd.ksunext.ui.util.createRootShell import java.io.File @SuppressLint("SetJavaScriptEnabled") @@ -21,18 +26,33 @@ class WebUIActivity : ComponentActivity() { private var rootShell: Shell? = null override fun onCreate(savedInstanceState: Bundle?) { + + // Enable edge to edge + enableEdgeToEdge() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + window.isNavigationBarContrastEnforced = false + } + super.onCreate(savedInstanceState) + val moduleId = intent.getStringExtra("id")!! val name = intent.getStringExtra("name")!! - setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name")) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + @Suppress("DEPRECATION") + setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name")) + } else { + val taskDescription = ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build() + setTaskDescription(taskDescription) + } - val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE) + val prefs = getSharedPreferences("settings", MODE_PRIVATE) WebView.setWebContentsDebuggingEnabled(prefs.getBoolean("enable_web_debugging", false)) - val webRoot = File("/data/adb/modules/${moduleId}/webroot") + val moduleDir = "/data/adb/modules/${moduleId}" + val webRoot = File("${moduleDir}/webroot") val rootShell = createRootShell(true).also { this.rootShell = it } val webViewAssetLoader = WebViewAssetLoader.Builder() - .setDomain("mui.kernelsu.org") + .setDomain("mui.kernelsu-next.org") .addPathHandler( "/", SuFilePathHandler(this, webRoot, rootShell) @@ -49,13 +69,23 @@ class WebUIActivity : ComponentActivity() { } val webView = WebView(this).apply { + ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets -> + val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + view.updateLayoutParams { + leftMargin = inset.left + rightMargin = inset.right + topMargin = inset.top + bottomMargin = inset.bottom + } + return@setOnApplyWindowInsetsListener insets + } settings.javaScriptEnabled = true settings.domStorageEnabled = true settings.allowFileAccess = false - webviewInterface = WebViewInterface(this@WebUIActivity, this) + webviewInterface = WebViewInterface(this@WebUIActivity, this, moduleDir) addJavascriptInterface(webviewInterface, "ksu") setWebViewClient(webViewClient) - loadUrl("https://mui.kernelsu.org/index.html") + loadUrl("https://mui.kernelsu-next.org/index.html") } setContentView(webView) diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebViewInterface.kt b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt similarity index 77% rename from drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebViewInterface.kt rename to drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt index 4b6a3c8f755d..649c71c6b619 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/webui/WebViewInterface.kt +++ b/drivers/staging/kernelsu/manager/app/src/main/java/com/rifsxd/ksunext/ui/webui/WebViewInterface.kt @@ -1,4 +1,4 @@ -package me.weishu.kernelsu.ui.webui +package com.rifsxd.ksunext.ui.webui import android.app.Activity import android.content.Context @@ -9,18 +9,24 @@ import android.view.Window import android.webkit.JavascriptInterface import android.webkit.WebView import android.widget.Toast -import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import com.topjohnwu.superuser.CallbackList import com.topjohnwu.superuser.ShellUtils -import me.weishu.kernelsu.ui.util.createRootShell -import me.weishu.kernelsu.ui.util.withNewRootShell +import com.topjohnwu.superuser.internal.UiThreadHandler +import com.rifsxd.ksunext.ui.util.createRootShell +import com.rifsxd.ksunext.ui.util.listModules +import com.rifsxd.ksunext.ui.util.withNewRootShell import org.json.JSONArray import org.json.JSONObject +import java.io.File import java.util.concurrent.CompletableFuture -class WebViewInterface(val context: Context, private val webView: WebView) { +class WebViewInterface( + val context: Context, + private val webView: WebView, + private val modDir: String +) { @JavascriptInterface fun exec(cmd: String): String { @@ -108,13 +114,13 @@ class WebViewInterface(val context: Context, private val webView: WebView) { } } - val stdout = object : CallbackList() { + val stdout = object : CallbackList(UiThreadHandler::runAndWait) { override fun onAddElement(s: String) { emitData("stdout", s) } } - val stderr = object : CallbackList() { + val stderr = object : CallbackList(UiThreadHandler::runAndWait) { override fun onAddElement(s: String) { emitData("stderr", s) } @@ -170,21 +176,34 @@ class WebViewInterface(val context: Context, private val webView: WebView) { } } -} + @JavascriptInterface + fun moduleInfo(): String { + val moduleInfos = JSONArray(listModules()) + var currentModuleInfo = JSONObject() + currentModuleInfo.put("moduleDir", modDir) + val moduleId = File(modDir).getName() + for (i in 0 until moduleInfos.length()) { + val currentInfo = moduleInfos.getJSONObject(i) -fun hideSystemUI(window: Window) { - WindowCompat.setDecorFitsSystemWindows(window, false) - WindowInsetsControllerCompat(window, window.decorView).let { controller -> - controller.hide(WindowInsetsCompat.Type.systemBars()) - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + if (currentInfo.getString("id") != moduleId) { + continue + } + + var keys = currentInfo.keys() + for (key in keys) { + currentModuleInfo.put(key, currentInfo.get(key)) + } + break + } + return currentModuleInfo.toString() } } -fun showSystemUI(window: Window) { - WindowCompat.setDecorFitsSystemWindows(window, true) - WindowInsetsControllerCompat( - window, - window.decorView - ).show(WindowInsetsCompat.Type.systemBars()) -} \ No newline at end of file +fun hideSystemUI(window: Window) = + WindowInsetsControllerCompat(window, window.decorView).let { controller -> + controller.hide(WindowInsetsCompat.Type.systemBars()) + controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + +fun showSystemUI(window: Window) = + WindowInsetsControllerCompat(window, window.decorView).show(WindowInsetsCompat.Type.systemBars()) diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/AboutCard.kt b/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/AboutCard.kt deleted file mode 100644 index 0807d0521dfe..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/component/AboutCard.kt +++ /dev/null @@ -1,123 +0,0 @@ -package me.weishu.kernelsu.ui.component - -import android.text.method.LinkMovementMethod -import android.widget.TextView -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb -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 androidx.compose.ui.unit.sp -import androidx.compose.ui.viewinterop.AndroidView -import androidx.compose.ui.window.Dialog -import androidx.core.content.res.ResourcesCompat -import androidx.core.text.HtmlCompat -import com.google.accompanist.drawablepainter.rememberDrawablePainter -import me.weishu.kernelsu.BuildConfig -import me.weishu.kernelsu.R - -@Preview -@Composable -fun AboutCard() { - ElevatedCard( - modifier = Modifier - .fillMaxWidth(), - shape = RoundedCornerShape(8.dp), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(24.dp) - ) { - AboutCardContent() - } - } -} - -@Composable -fun AboutDialog(dismiss: () -> Unit) { - Dialog(onDismissRequest = { dismiss() }) { - AboutCard() - } -} - -@Composable -private fun AboutCardContent() { - Column( - modifier = Modifier - .fillMaxWidth() - ) { - val drawable = ResourcesCompat.getDrawable( - LocalContext.current.resources, - R.mipmap.ic_launcher, - LocalContext.current.theme - ) - - Row { - Image( - painter = rememberDrawablePainter(drawable), - contentDescription = "icon", - modifier = Modifier.size(40.dp) - ) - - Spacer(modifier = Modifier.width(12.dp)) - - Column { - - Text( - stringResource(id = R.string.app_name), - style = MaterialTheme.typography.titleSmall, - fontSize = 18.sp - ) - Text( - BuildConfig.VERSION_NAME, - style = MaterialTheme.typography.bodySmall, - fontSize = 14.sp - ) - - Spacer(modifier = Modifier.height(8.dp)) - - HtmlText( - html = stringResource( - id = R.string.about_source_code, - "GitHub", - "Telegram" - ) - ) - } - } - } -} - -@Composable -fun HtmlText(html: String, modifier: Modifier = Modifier) { - val contentColor = LocalContentColor.current - AndroidView( - modifier = modifier, - factory = { context -> - TextView(context).also { - it.movementMethod = LinkMovementMethod.getInstance() - } - }, - update = { - it.text = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT) - it.setTextColor(contentColor.toArgb()) - } - ) -} \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt b/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt deleted file mode 100644 index 9812e87ebba6..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/java/me/weishu/kernelsu/ui/screen/Module.kt +++ /dev/null @@ -1,576 +0,0 @@ -package me.weishu.kernelsu.ui.screen - -import android.app.Activity.RESULT_OK -import android.content.Intent -import android.net.Uri -import android.util.Log -import android.widget.Toast -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.pullrefresh.PullRefreshIndicator -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState -import androidx.compose.material3.Button -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ElevatedCard -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExtendedFloatingActionButton -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarResult -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.produceState -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.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -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 -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.ramcosta.composedestinations.annotation.Destination -import com.ramcosta.composedestinations.navigation.DestinationsNavigator -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import me.weishu.kernelsu.Natives -import me.weishu.kernelsu.R -import me.weishu.kernelsu.ui.component.ConfirmResult -import me.weishu.kernelsu.ui.component.rememberConfirmDialog -import me.weishu.kernelsu.ui.component.rememberLoadingDialog -import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination -import me.weishu.kernelsu.ui.util.DownloadListener -import me.weishu.kernelsu.ui.util.LocalSnackbarHost -import me.weishu.kernelsu.ui.util.download -import me.weishu.kernelsu.ui.util.hasMagisk -import me.weishu.kernelsu.ui.util.reboot -import me.weishu.kernelsu.ui.util.toggleModule -import me.weishu.kernelsu.ui.util.uninstallModule -import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel -import me.weishu.kernelsu.ui.webui.WebUIActivity -import okhttp3.OkHttpClient - -@Destination -@Composable -fun ModuleScreen(navigator: DestinationsNavigator) { - val viewModel = viewModel() - val context = LocalContext.current - - LaunchedEffect(Unit) { - if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) { - viewModel.fetchModuleList() - } - } - - val isSafeMode = Natives.isSafeMode - val hasMagisk = hasMagisk() - - val hideInstallButton = isSafeMode || hasMagisk - - Scaffold(topBar = { - TopBar() - }, floatingActionButton = if (hideInstallButton) { - { /* Empty */ } - } else { - { - val moduleInstall = stringResource(id = R.string.module_install) - val selectZipLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.StartActivityForResult() - ) { - if (it.resultCode != RESULT_OK) { - return@rememberLauncherForActivityResult - } - val data = it.data ?: return@rememberLauncherForActivityResult - val uri = data.data ?: return@rememberLauncherForActivityResult - - navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri))) - - viewModel.markNeedRefresh() - - Log.i("ModuleScreen", "select zip result: ${it.data}") - } - - ExtendedFloatingActionButton( - onClick = { - // select the zip file to install - val intent = Intent(Intent.ACTION_GET_CONTENT) - intent.type = "application/zip" - selectZipLauncher.launch(intent) - }, - icon = { Icon(Icons.Filled.Add, moduleInstall) }, - text = { Text(text = moduleInstall) }, - ) - } - }) { innerPadding -> - - when { - hasMagisk -> { - Box( - modifier = Modifier - .fillMaxSize() - .padding(24.dp), - contentAlignment = Alignment.Center - ) { - Text( - stringResource(R.string.module_magisk_conflict), - textAlign = TextAlign.Center, - ) - } - } - - else -> { - ModuleList( - viewModel = viewModel, modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), - onInstallModule = - { - navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it))) - }, onClickModule = { id, name, hasWebUi -> - if (hasWebUi) { - context.startActivity(Intent(context, WebUIActivity::class.java) - .setData(Uri.parse("kernelsu://webui/$id")) - .putExtra("id", id) - .putExtra("name", name) - ) - } - }) - } - } - } -} - -@OptIn(ExperimentalMaterialApi::class) -@Composable -private fun ModuleList( - viewModel: ModuleViewModel, - modifier: Modifier = Modifier, - onInstallModule: (Uri) -> Unit, - onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit -) { - val failedEnable = stringResource(R.string.module_failed_to_enable) - val failedDisable = stringResource(R.string.module_failed_to_disable) - val failedUninstall = stringResource(R.string.module_uninstall_failed) - val successUninstall = stringResource(R.string.module_uninstall_success) - val reboot = stringResource(id = R.string.reboot) - val rebootToApply = stringResource(id = R.string.reboot_to_apply) - val moduleStr = stringResource(id = R.string.module) - val uninstall = stringResource(id = R.string.uninstall) - val cancel = stringResource(id = android.R.string.cancel) - val moduleUninstallConfirm = stringResource(id = R.string.module_uninstall_confirm) - val updateText = stringResource(R.string.module_update) - val changelogText = stringResource(R.string.module_changelog) - val downloadingText = stringResource(R.string.module_downloading) - val startDownloadingText = stringResource(R.string.module_start_downloading) - val fetchChangeLogFailed = stringResource(R.string.module_changelog_failed) - - val snackBarHost = LocalSnackbarHost.current - val context = LocalContext.current - - val loadingDialog = rememberLoadingDialog() - val confirmDialog = rememberConfirmDialog() - - suspend fun onModuleUpdate( - module: ModuleViewModel.ModuleInfo, - changelogUrl: String, - downloadUrl: String, - fileName: String - ) { - val changelogResult = loadingDialog.withLoading { - withContext(Dispatchers.IO) { - runCatching { - OkHttpClient().newCall( - okhttp3.Request.Builder().url(changelogUrl).build() - ).execute().body!!.string() - } - } - } - - val showToast: suspend (String) -> Unit = { msg -> - withContext(Dispatchers.Main) { - Toast.makeText( - context, - msg, - Toast.LENGTH_SHORT - ).show() - } - } - - val changelog = changelogResult.getOrElse { - showToast(fetchChangeLogFailed.format(it.message)) - return - }.ifBlank { - showToast(fetchChangeLogFailed.format(module.name)) - return - } - - // changelog is not empty, show it and wait for confirm - val confirmResult = confirmDialog.awaitConfirm( - changelogText, - content = changelog, - markdown = true, - confirm = updateText, - ) - - if (confirmResult != ConfirmResult.Confirmed) { - return - } - - showToast(startDownloadingText.format(module.name)) - - val downloading = downloadingText.format(module.name) - withContext(Dispatchers.IO) { - download( - context, - downloadUrl, - fileName, - downloading, - onDownloaded = onInstallModule, - onDownloading = { - launch(Dispatchers.Main) { - Toast.makeText(context, downloading, Toast.LENGTH_SHORT).show() - } - } - ) - } - } - - suspend fun onModuleUninstall(module: ModuleViewModel.ModuleInfo) { - val confirmResult = confirmDialog.awaitConfirm( - moduleStr, - content = moduleUninstallConfirm.format(module.name), - confirm = uninstall, - dismiss = cancel - ) - if (confirmResult != ConfirmResult.Confirmed) { - return - } - - val success = loadingDialog.withLoading { - withContext(Dispatchers.IO) { - uninstallModule(module.id) - } - } - - if (success) { - viewModel.fetchModuleList() - } - val message = if (success) { - successUninstall.format(module.name) - } else { - failedUninstall.format(module.name) - } - val actionLabel = if (success) { - reboot - } else { - null - } - val result = snackBarHost.showSnackbar(message, actionLabel = actionLabel) - if (result == SnackbarResult.ActionPerformed) { - reboot() - } - } - - val refreshState = rememberPullRefreshState(refreshing = viewModel.isRefreshing, - onRefresh = { viewModel.fetchModuleList() }) - Box(modifier.pullRefresh(refreshState)) { - val context = LocalContext.current - - LazyColumn( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = remember { - PaddingValues( - start = 16.dp, - top = 16.dp, - end = 16.dp, - bottom = 16.dp + 16.dp + 56.dp /* Scaffold Fab Spacing + Fab container height */ - ) - }, - ) { - when { - !viewModel.isOverlayAvailable -> { - item { - Box( - modifier = Modifier.fillParentMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - stringResource(R.string.module_overlay_fs_not_available), - textAlign = TextAlign.Center - ) - } - } - } - - viewModel.moduleList.isEmpty() -> { - item { - Box( - modifier = Modifier.fillParentMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - stringResource(R.string.module_empty), - textAlign = TextAlign.Center - ) - } - } - } - - else -> { - items(viewModel.moduleList) { module -> - var isChecked by rememberSaveable(module) { mutableStateOf(module.enabled) } - val scope = rememberCoroutineScope() - val updatedModule by produceState(initialValue = Triple("", "", "")) { - scope.launch(Dispatchers.IO) { - value = viewModel.checkUpdate(module) - } - } - - ModuleItem(module, isChecked, updatedModule.first, onUninstall = { - scope.launch { onModuleUninstall(module) } - }, onCheckChanged = { - scope.launch { - val success = loadingDialog.withLoading { - withContext(Dispatchers.IO) { - toggleModule(module.id, !isChecked) - } - } - if (success) { - isChecked = it - viewModel.fetchModuleList() - - val result = snackBarHost.showSnackbar( - rebootToApply, actionLabel = reboot - ) - if (result == SnackbarResult.ActionPerformed) { - reboot() - } - } else { - val message = if (isChecked) failedDisable else failedEnable - snackBarHost.showSnackbar(message.format(module.name)) - } - } - }, onUpdate = { - scope.launch { - onModuleUpdate( - module, - updatedModule.third, - updatedModule.first, - "${module.name}-${updatedModule.second}.zip" - ) - } - }, onClick = { - onClickModule(it.id, it.name, it.hasWebUi) - }) - - // fix last item shadow incomplete in LazyColumn - Spacer(Modifier.height(1.dp)) - } - } - } - } - - DownloadListener(context, onInstallModule) - - PullRefreshIndicator( - refreshing = viewModel.isRefreshing, state = refreshState, modifier = Modifier.align( - Alignment.TopCenter - ) - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun TopBar() { - TopAppBar(title = { Text(stringResource(R.string.module)) }) -} - -@Composable -private fun ModuleItem( - module: ModuleViewModel.ModuleInfo, - isChecked: Boolean, - updateUrl: String, - onUninstall: (ModuleViewModel.ModuleInfo) -> Unit, - onCheckChanged: (Boolean) -> Unit, - onUpdate: (ModuleViewModel.ModuleInfo) -> Unit, - onClick: (ModuleViewModel.ModuleInfo) -> Unit -) { - ElevatedCard( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface) - ) { - - val textDecoration = if (!module.remove) null else TextDecoration.LineThrough - - Column(modifier = Modifier.clickable { onClick(module) }.padding(24.dp, 16.dp, 24.dp, 0.dp)) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - val moduleVersion = stringResource(id = R.string.module_version) - val moduleAuthor = stringResource(id = R.string.module_author) - - Column(modifier = Modifier.fillMaxWidth(0.8f)) { - 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 - ) - } - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End, - ) { - Switch( - enabled = !module.update, - checked = isChecked, - onCheckedChange = onCheckChanged - ) - } - } - - 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(16.dp)) - - HorizontalDivider(thickness = Dp.Hairline) - - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Spacer(modifier = Modifier.weight(1f, true)) - - if (updateUrl.isNotEmpty()) { - Button( - modifier = Modifier - .padding(0.dp) - .defaultMinSize(52.dp, 32.dp), - onClick = { onUpdate(module) }, - shape = RoundedCornerShape(6.dp), - contentPadding = PaddingValues(0.dp) - ) { - Text( - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.module_update), - ) - } - } - - TextButton( - enabled = !module.remove, - onClick = { onUninstall(module) }, - ) { - Text( - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.uninstall), - ) - } - - if (module.hasWebUi) { - TextButton( - onClick = { onClick(module) }, - ) { - Text( - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.open), - ) - } - } - } - } - } -} - -@Preview -@Composable -fun ModuleItemPreview() { - val module = ModuleViewModel.ModuleInfo( - id = "id", - name = "name", - version = "version", - versionCode = 1, - author = "author", - description = "I am a test module and i do nothing but show a very long description", - enabled = true, - update = true, - remove = true, - updateJson = "", - hasWebUi = false, - ) - ModuleItem(module, true, "", {}, {}, {}, {}) -} \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_background.xml b/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 900e2d8c829e..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_foreground.xml b/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_foreground.xml index c9ad0ad4ddfe..3157323385f7 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -5,18 +5,22 @@ android:viewportWidth="108" android:viewportHeight="108"> - - - - - + + + + + \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_monochrome.xml b/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_monochrome.xml index e4dc522eeab8..3157323385f7 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_monochrome.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/drawable/ic_launcher_monochrome.xml @@ -5,18 +5,22 @@ android:viewportWidth="108" android:viewportHeight="108"> - - - - - + + + + + \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-anydpi/ic_launcher.xml old mode 100644 new mode 100755 index b070c763da32..345888d26e66 --- a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-anydpi/ic_launcher.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -1,6 +1,6 @@ - - - + + + \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher.png old mode 100644 new mode 100755 index 485b815dfee9..d7ffcdca577c Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_background.png new file mode 100755 index 000000000000..19669488f1b2 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100755 index 000000000000..92885122bfac Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png new file mode 100755 index 000000000000..92885122bfac Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-ldpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-ldpi/ic_launcher.png deleted file mode 100644 index 5c18cc7926c4..000000000000 Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-ldpi/ic_launcher.png and /dev/null differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher.png old mode 100644 new mode 100755 index 9df352536389..ede24bad2b1d Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_background.png new file mode 100755 index 000000000000..75025cfd5ccc Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100755 index 000000000000..c99d272c48a1 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png new file mode 100755 index 000000000000..c99d272c48a1 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher.png old mode 100644 new mode 100755 index f8dc01c5de52..57d2c2d43cd9 Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png new file mode 100755 index 000000000000..9784f16c8826 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100755 index 000000000000..c9d273ca09e8 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png new file mode 100755 index 000000000000..c9d273ca09e8 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher.png old mode 100644 new mode 100755 index ba22bf82fd6b..783e08eb2edc Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png new file mode 100755 index 000000000000..04ef206c8607 Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100755 index 000000000000..acd784af2a0a Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png new file mode 100755 index 000000000000..acd784af2a0a Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png old mode 100644 new mode 100755 index cddff920f64f..d27020a106ec Binary files a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100755 index 000000000000..66a5487a223c Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100755 index 000000000000..e1adc36f83cc Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png new file mode 100755 index 000000000000..e1adc36f83cc Binary files /dev/null and b/drivers/staging/kernelsu/manager/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png differ diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/resources.properties b/drivers/staging/kernelsu/manager/app/src/main/res/resources.properties new file mode 100644 index 000000000000..d5a3ddc92a9b --- /dev/null +++ b/drivers/staging/kernelsu/manager/app/src/main/res/resources.properties @@ -0,0 +1 @@ +unqualifiedResLocale=en-US \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-ar/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-ar/strings.xml deleted file mode 100644 index c38c4fc89464..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-ar/strings.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - الرئيسية - غير مثبت - إضغط للتثبيت - يعمل - الإصدار: %d - مستخدمين الجذر: %d - الإضافات: %d - غير مدعوم - KernelSU يدعم GKI kernels فقط - إصدار النواة - إصدار المدير - البصمة - وضع SELinux - معطل - مفروض - متساهل - مجهول - مستخدم خارق - فشل في تمكين الإضافة: %s - فشل تعطيل الإضافة : %s - لا توجد إضافات مثبتة - الإضافات - إلغاء التثبيت - تثبيت الوحدة - تثبيت - إعادة تشغيل - الإعدادات - إعادة تشغيل سريعة - إعادة تشغيل إلى وضع Recovery - إعادة تشغيل إلى وضع Bootloader - إعادة تشغيل إلى وضع Download - إعادة تشغيل إلى وضع EDL - من نحن - هل أنت متأكد أنك تريد إلغاء تثبيت الإضافة %s ? - تم إلغاء تثبيتها %s - فشل إلغاء التثبيت: %s - الإصدار - المطور - التراكبات غير متوفرة ، لا يمكن للإضافة أن تعمل! - إنعاش - إظهار تطبيقات النظام - إخفاء تطبيقات النظام - إرسال السجلات - الوضع الآمن - إعادة التشغيل لتطبيق التغييرات - تم تعطيل الإضافات لأنها تتعارض مع Magisk! - تعلم KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - تعرف على كيفية تثبيت KernelSU واستخدام الإضافات - إدعمنا - KernelSU سيظل دائماً مجانياً ومفتوح المصدر. مع ذلك، يمكنك أن تظهر لنا أنك تهتم بالتبرع. - إنضم إلى قناتنا في %2$s ]]> - القدرات - تحديث - تحميل الإضافة: %s - ابدأ التنزيل: %s - الإصدار الجديد: %s متاح ، انقر للتحديث - تشغيل - الإفتراضي - نموذج - موروث - عالمي - فردي - مجموعات - مُخصّص - تركيب مساحة الاسم - الغاء تحميل الإضافات - فشل تحديث ملف تعريف التطبيق لـ %s - سياق SELinux - ايقاف إجباري - الغاء تحميل الإضافات بشكل افتراضي - القيمة الافتراضية العامة لـ\"إلغاء تحميل الإضافات\" في ملفات تعريف التطبيقات. إذا تم تمكينه، إزالة جميع تعديلات الإضافات على النظام للتطبيقات التي لا تحتوي على مجموعة ملف تعريف. - سيسمح تمكين هذا الخيار لـKernelSU باستعادة أي ملفات معدلة بواسطة الإضافات لهذا التطبيق. - المجال - القواعد - إعادة تشغيل التطبيق - فشل تحديث قواعد SELinux لما يلي: %s - اسم الملف الشخصي - إصدار KernelSU الحالي %d منخفض جدًا بحيث لا يعمل المدير بشكل صحيح. الرجاء الترقية إلى الإصدار %d أو أعلى! - سجل التغييرات - تم الاستيراد بنجاح - تصدير إلى الحافظة - لا يمكن العثور على القالب المحلي للتصدير! - معرف القالب موجود بالفعل! - استيراد من الحافظة - فشل في جلب سجل التغيير: %s - الاسم - معرف القالب غير صالح - مزامنة القوالب عبر الإنترنت - إنشاء قالب - للقراءة فقط - استيراد / تصدير - فشل في حفظ القالب - تحرير القالب - المعرف - قالب ملف تعريف التطبيق - الوصف - حفظ - إدارة القالب المحلي وعبر الإنترنت لملف تعريف التطبيق - حذف - الحافظة فارغة! - عرض القالب - فشل في منح صلاحية الجذر! - فتح - التحقق تلقائيًا من وجود تحديثات عند فتح التطبيق - التحقق من التحديث - تمكين تصحيح أخطاء WebView - يمكن استخدامه لتصحيح أخطاء WebUI، يرجى تمكينه فقط عند الحاجة. - التالي - اختيار ملف - تثبيت مباشر (موصى به) - التثبيت على فتحة غير نشطة (بعد OTA) - سيتم **إجبار** جهازك على التمهيد إلى الفتحة غير النشطة الحالية بعد إعادة التشغيل! -\nاستخدم هذا الخيار فقط بعد انتهاء التحديث. -\nأستمرار؟ - اختر KMI - يوصى باستخدام صورة القسم %1$s - تصغير الصورة المتفرقة - قم بتغيير حجم الصورة المتفرقة حيث توجد الإضافة إلى حجمها الفعلي. لاحظ أن هذا قد يتسبب في عمل الإضافة بشكل غير طبيعي، لذا يرجى استخدامها فقط عند الضرورة (مثل النسخ الاحتياطي) - إلغاء التثبيت - إلغاء التثبيت مؤقتًا - إلغاء التثبيت بشكل دائم - استعادة الصورة الاصلية - ‬إلغاء تثبيت KernelSU (الجذر وجميع الوحدات) بشكل كامل ودائم. - تركيب - نجح التركيب - فشل التركيب - صورة lkm المحددة: %s - استعادة صورة المصنع المخزنة (في حالة وجود نسخة احتياطية)، والتي تُستخدم عادة قبل OTA؛ إذا كنت بحاجة إلى إلغاء تثبيت KernelSU، فيرجى استخدام \"إلغاء التثبيت الدائم\". - قم بإلغاء تثبيت KernelSU مؤقتًا، واستعد إلى حالته الأصلية بعد إعادة التشغيل التالية. - حفظ السجلات - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-az/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-az/strings.xml deleted file mode 100644 index 21ec189f55c4..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-az/strings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - Ana səhifə - Super istifadəçilər: %d - Nüvə - Yüklənmədi - Yükləmək üçün toxunun - İşləyir - Versiya: %d - Modullar: %d - Hal-hazırda KernelSU yalnız GKI nüvələrini dəstəkləyir - Dəstəklənmir - Yüklə - Yüklə - Naməlum - Barmaq izi - Menecer versiyası - Qeyri-aktiv - SELinux vəziyyəti - Sərbəst - Məcburi - Super istifadəçi - Sil - Modulu aktiv etmək mümkün olmadı: %s - Modulu deaktiv etmək mümkün olmadı: %s - Heç bir modul quraşdırılmayıb - Modul - Yenidən başlat - Parametrlər - Bərpa rejimində yenidən başlat - Yüngül vəziyyətdə yenodən başlat - Bootloader rejimində yenidən başlat - Yükləmə rejimində yenidən başlat - Versiya - Sahib - Modulu silmək istədiyinizdən əminsiniz %s\? - Sistem proqramlarını göstər - Haqqında - EDL rejimində yenidən başlat - Silmək mümkün olmadı: %s - %s silindi - Sistem proqramlarını gizlət - overlayfs mövcud deyil,modul işləyə bilməyəcək! - Log-u göndər - Yenilə - Təhlükəsiz rejimi - Qüvvəyə minməsi üçün yenidən başlat - Modular deaktiv edilir,çünki o Magisk-in modulları ilə toqquşur! - KernelSU-yu öyrən - https://kernelsu.org/guide/what-is-kernelsu.html - Bizi dəstəkləyin - KernelSU-yu necə quraşdırılacağını və modulların necə istifadə ediləcəyini öyrən - Şablon - Defolt - Özəl - KernelSU pulsuz və açıq mənbəlidir,həmişə belə olacaqdır. Bununla belə, ianə etməklə bizə qayğı göstərdiyinizi göstərə bilərsiniz. - Mənbə kodlarımıza baxın %1$s
Kanalımıza %2$s qoşulun
- Profil adı - Bacarıqlar - Modulları umount et - Miras qalmış - Qlobal - Bölmənin ad sahəsi - Fərdi - Qruplar - Defolt olaraq modulları umount et - SELinux konteksi - %s görə tətbiq profillərini güncəlləmək mümkün olmadı - Tətbiq Profillərində \"Umount modulları\" üçün qlobal standart dəyər. Aktivləşdirilərsə, o, Profil dəsti olmayan proqramlar üçün sistemdəki bütün modul dəyişikliklərini siləcək. - Domen - Qaydalar - Güncəllə - Endirməni başlat: %s - Yeni versiya: %s əlçatandır, endirmək üçün toxunun - Modul yüklənir: %s - Bu seçimi aktivləşdirmək KernelSU-ya bu proqram üçün modullar tərəfindən hər hansı dəyişdirilmiş faylları bərpa etməyə imkan verəcək. - - Məcburi dayandır - Yenidən başlat - %s görə SELinux qaydalarını güncəlləmək mümkün olmadı - Girişləri Saxla -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-bn-rBD/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-bn-rBD/strings.xml deleted file mode 100644 index 078d88fee7ca..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-bn-rBD/strings.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - কর্নেল এস ইউ কেবল মাত্র জিকআই কর্নেল সাপোর্ট করে - এসইলিনাক্স স্টেটাস - আননোন - মোডিউল ইনেবল করা যায়নি: %s - ইন্সটল করটে চাপুন - কাজ করছে - মোডিউল: %d - অমূলক - কর্নেল - ম্যানেজার ভারসন - ফিঙ্গারপ্রিন্ট - ডিসেবল - এনফোর্সিং - সুপার ইউজার - মোডিউল - আনইন্সটল - ইন্সটল - ইন্সটল - রিবুট - সেটিংস - সফট রিবুট - গ্লোবাল - গ্রুপস - এসইলিনাক্স কন্টেক্সট - %s এর জন্য অ্যাপ প্রফাইল আপডেট করা যায়নি - বাইডিফল্ট মোডিউল আনমাউন্ট - হোম - ইন্সটল হয়নী - পারমিসিভ - মোডিউল ডিসেবল করা যায়নি: %s - কোনো মোডিউল ইন্সটল করা নেই - সংস্করণ: %d - সুপার ইউজার: %d - নেইম স্পেস মাউন্ট - ইনহেরিটেড - ইন্ডিভিজুয়াল - ক্যাপাবিলিটিস - আনমাউন্ট মোডিউলস - রিকভারিতে বুট - বুটলোডারে বুট - ডাউনলোড মডে বুট - ইমারজেন্সি ডাউনলোড মডে বুট - অ্যাবাউট - %s মোডিউল আনইনস্টলের বেপারে নিশ্চিৎ\? - %s আনইনস্টলড - %s আনইনস্টল করা যায়নি - ভার্সন - অথার - লগ সংরক্ষণ করুন - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-bn/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-bn/strings.xml deleted file mode 100644 index 312672c8715a..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-bn/strings.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - হোম - ইনস্টল করা হয়নি - ইনস্টল করার জন্য ক্লিক করুন - ওয়ার্কিং - ওয়ার্কিং সংস্করণ: %d - সুপার ইউজার: %d - মডিউল: %d - অসমর্থিত - KernelSU শুধুমাত্র GKI কার্নেল সমর্থন করে - কার্নেল - ম্যানেজার সংস্করণ - ফিঙ্গারপ্রিন্ট - SELinux স্টেটাস - ডিজেবল - কার্যকর - অনুমতিমূলক - অজানা - সুপার ইউজার - মডিউল সক্ষম করতে ব্যর্থ হয়েছে: %s - মডিউল নিষ্ক্রিয় করতে ব্যর্থ হয়েছে: %s - কোন মডিউল ইনস্টল করা নেই - মডিউল - আনইন্সটল - মডিউল ইনস্টল - ইনস্টল - রিবুট - সেটিংস - সফট রিবুট - রিবুট রিকোভারি - রিবুট বুটলোডার - রিবুট ডাউনলোড - রিবুট ইডিএল - এবাউট - মডিউল আনইনস্টল নিশ্চিত করুন %s? - %s আনইনস্টল সফল - আনইন্সটল ব্যর্থ: %s - ভার্সন - লেখক - ওভারলেএফএস উপলব্ধ নয়, মডিউল কাজ করতে পারে না! - রিফ্রেশ - শো সিস্টেম অ্যাপস - হাইড সিস্টেম অ্যাপস - সেন্ড লগ - সেইফ মোড - রিবুট এপ্লাই - মডিউলগুলি অক্ষম কারণ তারা ম্যাজিস্কের সাথে বিরোধিতা করে! - লার্ন কার্নেলএসইউ - https://kernelsu.org/guide/what-is-kernelsu.html - কিভাবে কার্নেলএসইউ ইনস্টল করতে হয় এবং মডিউল ব্যবহার করতে হয় তা শিখুন - সাপোর্ট টাইটেল - কার্নেলএসইউ বিনামূল্যে এবং ওপেন সোর্স, এবং সবসময় থাকবে। আপনি সবসময় একটি অনুদান দিয়ে আপনার কৃতজ্ঞতা প্রদর্শন করতে পারেন. - আমাদের %2$s চ্যানেল মার্জ করুন]]> - প্রফাইলের নাম - নেমস্পেস মাউন্ট - গ্রুপস - যোগ্যতা - এসই লিনাক্স কনটেক্সট - ডিফল্ট - টেমপ্লেট - কাস্টম - গ্লোবাল - আলাদাভাবে - আনমাউন্ট মোডিউল - ম্যানেজার সঠিকভাবে কাজ করার জন্য বর্তমান KernelSU সংস্করণ %d খুবই কম। অনুগ্রহ করে %d বা উচ্চতর সংস্করণে আপগ্রেড করুন! - লগ সংরক্ষণ করুন - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-bs/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-bs/strings.xml deleted file mode 100644 index da07863193fe..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-bs/strings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - Imenski prostor nosača - Naslijeđen - Globalan - Pojedinačan - Grupe - Sposobnosti - SELinux kontekst - Umount module - Ažuriranje Profila Aplikacije za %s nije uspjelo - Trenutna KernelSU verzija %d je preniska da bi upravitelj ispravno radio. Molimo vas da nadogradite na verziju %d ili noviju! - Umount module po zadanom - Globalna zadana vrijednost za \"Umount module\" u Profilima Aplikacije. Ako je omogućeno, uklonit će sve izmjene modula na sistemu za aplikacije koje nemaju postavljen Profil. - Uključivanjem ove opcije omogućit će KernelSU-u da vrati sve izmjenute datoteke od strane modula za ovu aplikaciju. - Ažuriranje - Skidanje module: %s - Započnite sa skidanjem: %s - Nova verzija: %s je dostupna, kliknite da skinete - Pokrenite - Prisilno Zaustavite - Resetujte - U Provođenju - Početna - Nije instalirano - Kliknite da instalirate - Superkorisnici: %d - Module: %d - Nepodržano - KernelSU samo podržava GKI kernele sad - Verzija Upravitelja - Otisak prsta - SELinux stanje - Instalirajte - Instalirajte - Ponovo pokrenite - Podešavanja - Verzija - Autor - Osvježi - Prikažite sistemske aplikacije - Sakrijte sistemske aplikacije - Sigurnosni mod - Ponovo pokrenite da bi proradilo - Module su isključene jer je u sukobu sa Magisk-om! - https://kernelsu.org/guide/what-is-kernelsu.html - Naučite kako da instalirate KernelSU i da koristite module - Podržite Nas - Pošaljite Izvještaj - Naučite KernelSU - Pogledajte izvornu kodu na %1$s
Pridružite nam se na %2$s kanalu
- Domena - Pravila - Neuspješno ažuriranje SELinux pravila za: %s - Radi - Verzija: %d - Kernel - Permisivno - Deinstalirajte - Nepoznato - Nema instaliranih modula - Superkorisnik - Modula - Ponovo pokrenite u Pogonski Učitavatelj - Ponovo pokrenite u Oporavu - %s deinstalirana - Lagano Ponovo pokretanje - Neuspješno uključivanje module: %s - Ponovo pokrenite u Preuzimanje - Neuspješno isključivanje module: %s - Ponovo pokrenite u EDL - Neuspješna deinstalacija: %s - Isključeno - O - Jeste li sigurni da želite deinstalirati modulu %s\? - overlayfs nije dostupan, modula ne može raditi! - KernelSU je, i uvijek če biti, besplatan, i otvorenog izvora. Možete nam međutim pokazati da vas je briga s time da napravite donaciju. - Zadano - Šablon - Prilagođeno - Naziv profila - Sačuvaj Dnevnike -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-da/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-da/strings.xml deleted file mode 100644 index 6ab022567f4c..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-da/strings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - Arbejder - Moduler: %d - Ikke understøttet - Kernel - KernelSU understøtter kun GKI kernels - Manager Version - SELinux-status - Deaktiveret - Tilladende - Superbruger - Håndhævende - Deaktivering af modul fejlede: %s - Intet modul installeret - Afinstaller - Installer - Installer - Genstart - Indstillinger - Blød Genstart - Genstart til Download - Genstart til EDL - Om - Er du sikker på, at du vil afinstallere modulet %s\? - %s afinstalleret - Afinstallation af: %s fejlede - overlayfs er ikke tilgængeligt, modulet kan ikke fungere! - Opdater - Send Log - Sikker tilstand - Genstart for at tage effekt - Lær KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Lær hvordan man installerer KernelSU og moduler - Se source koden ved %1$s
Deltage i vores %2$s kanal
- Standard - Skabelon - Monter navnerum - Arvet - Global - Grupper - Evner - SELinux-kontext - Afmonteret moduler - Afmontere moduler som standard - Aktivering af denne indstilling vil tillade KernelSU at gendanne hvilken som helst modificeret filer af modulet for denne applikation. - Opdatering - Downloader modulet: %s - Ny version: %s er tilgængelig, kilk for at downloade - Start - Tving Stop - Opdatering af SELinux-regler for: %s fejlede - Start download: %s - Klik for at installere - Version: %d - Hjem - Ikke installeret - Superbrugere: %d - Fingeraftryk - Ukendt - Aktivering af modul fejlede: %s - Genstart til Recovery - Modul - Forfatter - Genstart til Bootloader - Version - Gem system-apps - Vis system-apps - Moduler er deaktiveret, fordi der er konflikt med Magiskes! - Støt Os - KernelSU er, og vil altid være gratis og open source. Du kan stadig vise os din støtte ved at donere. - Brugerdefineret - Profilnavn - Individuel - Opdatering af App Profil for %s fejlede - Den globale standard værdi for \"Afmonter moduler\" i App Profiler. Hvis aktiveret vil den fjerne alle modulers modifikationer til system applikationerne der ikke har en sat Profil. - Domæne - Regler - Genstart - Den nuværende KernelSU version %d er for lav til manageren for at fungere ordentligt. Opgrader til version %d eller højere! - Gem Logfiler -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-de/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-de/strings.xml deleted file mode 100644 index 047123467301..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-de/strings.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - Startseite - Nicht installiert - Permissiv - Funktioniert - Version: %d - SuperUser - Tippen zum Installieren - Superuser: %d - Unbekannt - Erzwingen - Neustart in Bootloader - Neustart in Download-Modus - Neustart mit EDL-Modus - Autor - overlayfs nicht verfügbar, Modul kann nicht funktionieren! - Über - Module sind deaktiviert, weil es einen Konflikt mit Magisk gibt! - https://kernelsu.org/guide/what-is-kernelsu.html - Erfahren, wie KernelSU installiert und Module verwendet werden - Unterstütze uns - KernelSU ist und wird immer frei und quelloffen sein. Du kannst uns jedoch deine Unterstützung zeigen, indem du eine Spende tätigst. - SELinux-Kontext - Module standardmäßig aushängen - Globaler Standardwert für \'Module aushängen\' in App-Profilen. Falls aktiviert, werden alle Moduländerungen im System für alle Apps entfernt, für die kein Profil festgelegt ist. - Standard - Vorlage - Benutzerdefiniert - App-Profilaktualisierung für %s fehlgeschlagen - Vererbt - Global - Individuell - Domäne - Aktualisieren - Wenn du diese Option aktivierst, kann KernelSU alle von den Modulen für diese App geänderten Dateien wiederherstellen. - Regeln - Herunterladen startet: %s - Fehler beim Aktualisieren der SELinux-Regeln für: %s - Starten - Neue Version: %s verfügbar, tippen zum Aktualisieren - Stopp erzwingen - Neustart - Module: %d - Manager-Version - SELinux-Status - Deaktiviert - Modulaktivierung fehlgeschlagen: %s - Moduldeaktivierung fehlgeschlagen: %s - Keine Module installiert - Modul - Deinstallieren - Installieren - Neustarten - Einstellungen - Neustart in Recovery - %s deinstalliert - Version - Neu laden - System-Apps anzeigen - System-Apps ausblenden - Protokoll senden - KernelSU verstehen - Sicherer Modus - Neustarten, damit Änderungen wirksam werden - Quellcode unter %1$s ansehen
Unserem %2$s-Kanal beitreten
- Profilname - Namespace einhängen - Gruppen - Fähigkeiten - Module aushängen - Modul herunterladen: %s - Nicht unterstützt - KernelSU unterstützt derzeit nur GKI-Kernel - Kernel - Fingerabdruck - Installieren - Soft-Reboot - Sicher, dass du das Modul %s deinstallieren möchtest\? - Deinstallation fehlgeschlagen: %s - Die aktuelle Kernel-Version %d ist zu alt für diese Manager-Version. Bitte auf Version %d oder höher upgraden! - Änderungsprotokoll - Erfolgreich importiert - In Zwischenablage exportieren - Kann lokale Vorlage nicht finden! - Vorlagen-ID existiert bereits! - Aus Zwischenablage importieren - Konnte Changelog nicht laden: %s - Name - Ungültige Vorlagen-ID - Online-Vorlagen synchronisieren - Vorlage erstellen - Schreibgeschützt - Import/Export - Fehler beim Speichern - Vorlage bearbeiten - ID - App-Profil-Template - Beschreibung - Speichern - verwalte lokale und online Profil Vorlagen - Löschen - Zwischenablage ist leer! - Vorlage ansehen - WebView-Debugging aktivieren - Kann verwendet werden zum Debugging von WebUI, bitte nur falls nötig aktivieren. - %1$s Partitionsabbild empfohlen - KMI auswählen - Weiter - Direkte Installation (empfohlen) - Datei auswählen - In inaktiven Slot installieren (nach OTA) - Nach einem Neustart wird dein Gerät **GEZWUNGEN** in den derzeit inaktiven Slot zu booten. -\nBenutze dies nur nach Fertigstellung des OTA. -\nFortfahren? - Root-Zugriff konnte nicht gewährt werden! - Öffnen - Updates suchen - Automatisch nach Updates suchen beim Öffnen der App - Protokolle Speichern -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-es/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-es/strings.xml deleted file mode 100644 index 5623b47a2943..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-es/strings.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - Inicio - No instalado - Toca para instalar - Funcionando - Versión: %d - Superusuarios: %d - Módulos: %d - No soportado - Por el momento, KernelSU solo es compatible con kernels genéricos (GKIs) - Versión del kernel - Versión del gestor - Huella del dispositivo - Estado de SELinux - - Desactivado - Enforcing de SELinux - Permisivo - Desconocido - Superusuario - No se pudo habilitar el módulo \"%s\" - No se pudo deshabilitar el módulo \"%s\" - No hay ningún módulo instalado - Módulo - Desinstalar - Instalar módulo - Instalar - Reiniciar - Ajustes - Reinicio minimo - Reiniciar en modo de recuperación - Reiniciar en modo de arranque - Reiniciar en modo Download - Reiniciar en modo EDL - Acerca de - ¿Estás seguro de que quieres desinstalar el módulo \"%s\"? - \"%s\" esta desinstalado - No se pudo desinstalar \"%s\" - Versión - Autor - El módulo no puede funcionar ya que OverlayFS no está disponible! - Recargar - Mostrar applicaciones del sistema - Ocultar applicaciones del sistema - Enviar registro de informe - Modo seguro - Reinicia para aplicar cambios - Se deshabilitaron los módulos ya que entran en conflicto con los de Magisk! - Aprende KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Descubre cómo instalar KernelSU y utilizar módulos - Apóyanos - KernelSU es y siempre será, libre y de código abierto. De todas formas, puedes mostrarnos tu apoyo mediante una donación. - Mirar el código en %1$s
Únete a nuestro canal de %2$s
- Predeterminado - Plantilla - Personalizado - Nombre de perfil - Montaje del espacio de nombres - Heredado - Global - Individual - Grupos - Capacidades - Contexto de SELinux - Desmontar módulos - No se pudo actualizar el perfil de la applicación para %s - Desmontar módulos por defecto - El valor global predeterminado para \"Desmontar módulos\" en los perfiles de las aplicaciones. Si la habilitas, se desharán todas las modificaciones al sistema hechas por el módulo para las applicaciones que no tengan un perfil establecido. - Si habilitas esta opción, KernelSU podrá restaurar cualquier archivo modificado por los módulos para esta app. - Dominio - Reglas - Actualizar - Descargando módulo: \"%s\" - Iniciar descarga: %s - Nueva versión: %s está disponible, toque para actualizar - Abrir Aplicacion - Forzar cierre de la aplicacion - Reiniciar aplicacion - Falló al actualizar reglas de SEpolicy por: %s - La versión actual de KernelSU %d es demasiado baja para que el gestor funcione correctamente. ¡Por favor actualiza a la versión %d o superior! - Registro de cambios - Importado con exíto - Exportar a portapapeles - No se puede encontrar plantilla local para exportar! - Ya existe un ID de la plantilla! - Importar desde portapapeles - Error en obtener los registros de cambios: %s - Nombre - ID de la plantilla es invalido - Sincronizar plantillas en linea - Crear plantilla - sololectura - Importar/Exportar - Fallo en guardar plantilla - Editar plantilla - id - Plantilla del perfil de la aplicacion - Descripción - Guardar - Administrar las plantillas locales y de en linea del perfil de la aplicacion - Eliminar - El portapapeles esta vacio! - Ver plantilla - Guardar Registros -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-et/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-et/strings.xml deleted file mode 100644 index d514fc6aea79..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-et/strings.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - Töötamine - Versioon: %d - Mooduleid: %d - Tuum - Manageri versioon - Sõrmejälg - Lubav - Mooduli lubamine ebaõnnestus: %s - Mooduleid pole paigaldatud - Taaskäivita - Taaskäivita taastusesse - Kas soovid kindlasti eemaldada mooduli %s? - %s on eemaldatud - Raporteeri logi - Turvarežiim - Muudatuste rakendamiseks taaskäivita - Õpi KernelSUd - https://kernelsu.org/guide/what-is-kernelsu.html - Vaikimisi - Haagi nimeruum - Lahtihaagitud moodulid - Rakenduseprofiili uuendamine %s jaoks ebaõnnestus - Haagi moodulid vaikimisi lahti - Allalaadimise alustamine: %s - SELinux reeglite uuendamine ebaõnnestus: %s - Muuda malli - Rakenduseprofiili mall - ID - vaid lugemiseks - malli ID juba eksisteerib! - Ekspordi lõikelauale - Sünkrooni võrgumallid - Muudatuste logi hankimine ebaõnnestus: %s - Kodu - Klõpsa paigaldamiseks - Pole paigaldatud - Mittetoetatud - Superkasutajaid: %d - KernelSU toetab hetkel vaid GSI tuumasid - SELinuxi olek - Keelatud - Jõustav - Teadmata - Superkasutaja - Mooduli keelamine ebaõnnestus: %s - Moodul - Taaskäivita käivituslaadurisse - Eemalda - Paigalda - Teave - Paigalda - Seaded - Pehme taaskäivitus - Taaskäivita allalaadimisrežiimi - Taaskäivita EDL-i - Värskenda - Autor - Eemaldamine ebaõnnestus: %s - Versioon - overlayfs pole saadaval, moodul ei saa töötada! - Kuva süsteemirakendused - Peida süsteemirakendused - Moodulid on keelatud, kuna need lähevad konflikti Magiski omadega! - Õpi KernelSUd paigaldama ja mooduleid kasutama - Toeta meid - Grupid - KernelSU on, ja alati jääb, tasuta ning avatud lähtekoodiga kättesaadavaks. Sellegipoolest võid sa näidata, et hoolid, ning teha annetuse. - Mall - Vaata lähtekoodi %1$sis
Liitu meie %2$si kanaliga
- Profiili nimi - Kohandatud - Päritud - Globaalne - Individuaalne - Võimekused - Sobimatu malli ID - SELinux kontekst - Praegune KernelSU versioon %d on liiga madal, haldur ei saa konkreetselt toimida. Palun täienda versioonile %d või kõrgem! - Domeen - Käivita - Sundpeata - Reeglid - Uuenda - Mooduli allalaadimine: %s - Uus versioon: %s on saadaval, klõpsa täiendamiseks - Taaskäivita - Muudatuste logi - Nimi - Kirjeldus - Edukalt imporditud - Salvesta - Lõikelaud on tühi! - Kustuta - Vaata malli - Impordi/ekspordi - Impordi lõikelaualt - Malli salvestamine ebaõnnestus - Loo mall - Halda kohalikke ja võrgusolevaid rakenduseprofiili malle - Selle valiku lubamine lubab KernelSU-l taastada selle rakenduse moodulite poolt mistahes muudetud faile. - Eksportimiseks kohalikku malli ei leitud! - Globaalne vaikeväärtus \"Lahtihaagitud moodulitele\" rakenduseprofiilides. Lubamisel eemaldab see kõik moodulite süsteemimuudatused rakendustele, millel ei ole profiili määratud. - Saab kasutada WebUI silumiseks, palun luba ainult vajadusel. - Juurkasutaja andmine ebaõnnestus! - Kontrolli uuendusi - Rakenduse avamisel kontrolli automaatselt uuendusi - Ava - Luba WebView silumine - Salvesta Logid -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-fa/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-fa/strings.xml deleted file mode 100644 index a5cdb2f7ff58..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-fa/strings.xml +++ /dev/null @@ -1,67 +0,0 @@ - -خانه -نصب نشده است -برای نصب ضربه بزنید -به درستی کار می‌کند -نسخه: %d -برنامه های با دسترسی روت: %d -ماژول‌ها: %d -پشتیبانی نشده -کرنل اس یو فقط هسته های gki را پشتیبانی میکند - هسته - نسخه برنامه - اثرانگشت - وضعیت SELinux -غیرفعال -قانونمند -آزاد -ناشناخته -دسترسی روت - فعال کردن ماژول ناموفق بود: %s -غیرفعال کردن ماژول ناموفق بود: %s -هیچ ماژولی نصب نشده است -ماژول -لغو نصب -نصب -نصب -راه اندازی دوباره -تنظیمات -راه اندازی نرم -راه اندازی به ریکاوری -راه اندازی به بوتلودر -راه اندازی به حالت دانلود -راه اندازی به EDL -درباره - آیا مطمئنید که میخواهید ماژول %s را پاک کنید؟ -%s پاک شد -پاک کردن ناموفق بود: %s -نسخه -سازنده -overlayfs موجود نیست. مازول کار نمیکند!! -تازه‌سازی -نمایش برنامه های سیستمی -مخفی کردن برنامه های سیستمی -ارسال وقایع -حالت امن -راه‌اندازی مجدد برای تاثیرگذاری -مازول به دلیل تعارض با مجیسک غیرفعال شده اند\'s! -یادگیری کرنل اس یو -https://kernelsu.org/guide/what-is-kernelsu.html -یاد بگیرید چگونه از کرنل اس یو و ماژول ها استفاده کنید -از ما حمایت کنید -KernelSU رایگان است و همیشه خواهد بود و منبع باز است. با این حال، می توانید با اهدای کمک مالی به ما نشان دهید که برایتان مهم است. - -Join our %2$s channel ]]> - -پروفایل برنامه -پیش‌فرض -قالب -شخصی سازی شده -اسم پروفایل -Mount namespace -اثر گرفته -گلوبال -تکی -جداکردن ماژول ها - ذخیره گزارش‌ها - diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-fil/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-fil/strings.xml deleted file mode 100644 index fc527bf30627..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-fil/strings.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - Katayuan ng SELinux - Hindi pinagana - Enforcing - Permissive - Hindi naka-install - Home - Pindutin para mag-install - Gumagana - Bersyon: %d - Hindi matukoy - Mga Modyul: %d - Hindi Suportado - Sinusuportahan lang ng KernelSU ang mga kernel ng GKI ngayon - Nabigong paganahin ang modyul: %s - Nabigong i-disable ang modyul: %s - Walang naka-install na modyul - Modyul - I-install - I-install - I-reboot - I-soft Reboot - I-reboot sa Download - I-reboot sa EDL - Tungkol - Sigurado ka bang gusto mong i-uninstall ang modyul %s\? - Na-uninstall ang %s - Nabigong i-uninstall: %s - May-akda - Ang overlayfs ay hindi magagamit, ang modyul ay hindi gagana! - I-refresh - Ipakita ang mga application ng system - Magpadala ng Log - I-reboot para umepekto - Hindi pinagana ang mga modyul dahil salungat ito sa Magisk! - Alamin ang KernelSU - Matutunan kung paano mag-install ng KernelSU at gumamit ng mga modyul - Suportahan Kami - Ang KernelSU ay, at palaging magiging, libre, at open source. Gayunpaman, maaari mong ipakita sa amin na nagmamalasakit ka sa pamamagitan ng pagbibigay ng donasyon. - Tingnan ang source code sa %1$s
Sumali sa aming %2$s channel
- I-mount ang namespace - Indibidwal - Mga Grupo - Mga Kakayanan - Konteksto ng SELinux - I-unmount ang mga modyul - Nabigong i-update ang App Profile para sa %s - Ang kasalukuyang bersyon ng KernelSU %d ay masyadong mababa para gumana nang maayos ang manager. Mangyaring mag-upgrade sa bersyon %d o mas mataas! - Ang pagpapagana sa opsyong ito ay magbibigay-daan sa KernelSU na ibalik ang anumang binagong file ng mga modyul para sa aplikasyon na ito. - Mga Tuntunin - Nagda-download ng modyul: %s - Simulan ang pag-download: %s - Bagong bersyon: Available ang %s, i-click upang i-download - Ilunsad - Pilit na I-hinto - I-restart - Nabigong i-update ang mga panuntunan ng SELinux para sa: %s - Bersyon ng Manager - Mga setting - I-reboot sa Recovery - I-reboot sa Bootloader - Bersyon - I-uninstall - Itago ang mga application ng system - Pangalan ng profile - Minana - Ang pangkalahatang default na halaga para sa \"Umount modules\" sa Mga Profile ng App. Kung pinagana, aalisin nito ang lahat ng mga pagbabago sa modyul sa system para sa mga aplikasyon na walang hanay ng Profile. - I-save ang mga Log -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-fr/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-fr/strings.xml deleted file mode 100644 index 01c0672b87a6..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-fr/strings.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - Non installé - Fonctionnel - Version : %d - Super-utilisateurs : %d - Modules : %d - Actuellement, KernelSU ne supporte que les noyaux GKI - Noyau - Empreinte digitale - Mode SELinux - Désactivé - Permissive - Inconnu - Super-utilisateur - Aucun module installé - Accueil - Appuyez ici pour installer - Non supporté - Échec de la désinstallation : %s - Version - Version du gestionnaire - Enforcing - Échec de l\'activation du module : %s - Modules - Désinstaller - Installer - Échec de la désactivation du module : %s - Redémarrer - Installer - Paramètres - Redémarrer en mode bootloader - Redémarrage progressif - Redémarrer en mode de récupération - Redémarrer en mode EDL - À propos - %s a été désinstallé - Redémarrer en mode de téléchargement - Auteur - Êtes-vous sûr(e) de vouloir désinstaller le module %s \? - Découvrir KernelSU - OverlayFS est indisponible, impossible de faire fonctionner les modules ! - Rafraîchir - Afficher les applications système - Masquer les applications système - Mode sans échec - Rapport de journal - Redémarrez pour appliquer les modifications - Les modules sont désactivés car ils sont en conflit avec ceux de Magisk ! - https://kernelsu.org/guide/what-is-kernelsu.html - Soutenez-nous - Découvrez comment installer KernelSU et utiliser les modules - KernelSU est, et restera toujours, gratuit et open source. Vous pouvez cependant nous témoigner de votre soutien en nous faisant un don. - Voir le code source sur %1$s
-\nRejoindre notre canal %2$s
- Modèle - Par défaut - Personnalisé - Nom du profil - Espace de noms de montage - Hérité - Individuel - Contexte SELinux - Global - Groupes - Capacités - Démonter les modules - Échec de la modification du profil d\'application de %s - L\'activation de cette option permettra à KernelSU de restaurer tous les fichiers modifiés par les modules de cette application. - Démonter les modules par défaut - Valeur globale par défaut pour l\'option « Démonter les modules » dans les profils d\'application. Lorsqu\'elle est activée, les modifications apportées au système par les modules seront supprimées pour les applications qui n\'ont pas de profil défini. - Domaine - Règles - Mettre à jour - Téléchargement du module : %s - Lancer - La version %s est disponible, appuyez ici pour mettre à jour - Début du téléchargement de : %s - Forcer l\'arrêt - Relancer l\'application - Échec de la mise à jour des règles SELinux pour : %s - La version actuelle de KernelSU (%d) est trop ancienne pour que le gestionnaire fonctionne correctement. Veuillez passer à la version %d ou à une version supérieure ! - Importation réussie - Exporter vers le presse-papiers - Impossible de trouver un modèle local à exporter ! - L\'id du modèle existe déjà ! - Journal des modifications - Importer à partir du presse-papiers - Échec de récupération du journal des modifications : %s - Nom - id de modèle invalide - Synchroniser les modèles en ligne - Créer un modèle - lecture seule - Importer/exporter - Échec de l\'enregistrement du modèle - Modifier le modèle - id - Modèles de profils d\'application - Description - Enregistrer - Gérer les modèles de profils d\'application locaux et en ligne - Supprimer - Le presse-papiers est vide ! - Voir le modèle - Vérifier automatiquement les mises à jour à l\'ouverture de l\'application - Vérifier les mises à jour - Activer le débogage de WebView - Peut être utilisé pour déboguer WebUI, n\'activez cette option que si nécessaire. - Échec de l\'octroi des privilèges root ! - Ouvrir - Installation directe (recommandé) - Sélectionner un fichier - Installer dans l\'emplacement inactif (après OTA) - Votre appareil sera **FORCÉ** à démarrer sur l\'emplacement inactif actuel après un redémarrage ! -\nN\'utilisez cette option qu\'une fois la mise à jour OTA terminée. -\nContinuer ? - Suivant - L\'image de la partition %1$s est recommandée - Sélectionner une KMI - Minimiser l\'image clairsemée - Redimensionne l\'image clairsemée où se trouve le module à sa taille réelle. Notez que cela peut entraîner un dysfonctionnement du module, alors utilisez cette fonctionnalité uniquement lorsque nécessaire (pour la sauvegarde, par exemple) - Désinstaller - Désinstaller temporairement - Désinstaller définitivement - Restaurer l\'image stock - Restaurer l\'image stock d\'usine (s\'il en existe une sauvegarde), option généralement utilisée avant une mise à jour OTA ; si vous avez besoin de désinstaller KernelSU, utilisez plutôt l\'option « Désinstaller définitivement ». - Flash en cours - Flash réussi - Échec du flash - lkm sélectionné : %s - Désinstallation complète et permanente de KernelSU (root et tous les modules). - Désinstaller KernelSU temporairement et rétablir l\'état original au redémarrage suivant. - Enregistrer les Journaux -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-hi/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-hi/strings.xml deleted file mode 100644 index f930446936f3..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-hi/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - प्रभाव में होने के लिए रीबूट करें - जानें कि KernelSU कैसे स्थापित करें और मॉड्यूल का उपयोग कैसे करें - अज्ञात - सिस्टम एप्प दिखाए - %s अनइंस्टॉल सफल हुआ - मॉड्यूल्स अनमाउंट करें - लॉग भेजे - डिसेबल्ड (बंद) - हमें प्रोत्साहन दें - Inherited - मॉड्यूल बंद कर दिए गए हैं क्योंकि यह मैजिक के साथ टकरा रहे है! - क्या बदलाव हुए है - पर्मिसिव - डाउनलोड में रिबूट करें - डिफ़ॉल्ट रूप से मॉड्यूल अनमाउन्ट करें - इस विकल्प को चालू करने से KernelSU को इस एप्लिकेशन के लिए मॉड्यूल द्वारा किसी भी मोडिफाइड फ़ाइल को रिस्टोर करें। - Individual - %s मॉड्यूल चालू करने में विफल - जबर्दस्ती बंद करें - EDL मोड में रिबूट करें - फिर से चालू करें - क्षमताएं - सुपरयूजर : %d - %s की डाउनलोडिंग स्टार्ट करें - Global - ऐप प्रोफाइल में \"अनमाउंट मॉड्यूल\" के लिए ग्लोबल डिफ़ॉल्ट वैल्यू। यदि चालू किया गया है, तो यह एप्लीकेशंस के लिऐ सिस्टम के सभी मॉड्यूल मोडिफिकेशन को हटा देगा जिनकी प्रोफ़ाइल सेट नहीं है। - मॉड्यूल्स : %d - एनफोर्सिंग - SELinux context - फिंगरप्रिंट - डिफॉल्ट - लॉन्च करें - सेफ मोड - मैनेजर के ठीक से काम करने के लिए वर्तमान KernelSU वर्जन %d बहुत कम है। कृपया वर्जन %d या उच्चतर में अपग्रेड करें! - रिकवरी में रिबूट करें - सॉफ्ट रिबूट - प्रोफाइल का नाम - KernelSU मुफ़्त और ओपन सोर्स और हमेशा रहेगा। हालाँकि आप दान देकर हमें दिखा सकते हैं कि आप संरक्षण करते हैं। - अनइंस्टॉल करें - Namspace माउंट करें - इंस्टाल करें - इंस्टाल करने के लिए क्लिक करें - नियम - समूह - Overlayfs उपलब्ध नहीं है, मॉड्यूल काम नहीं कर सकता ! - मॉड्यूल - निर्माता - हमारे बारे में - वर्जन: %d - रीबूट करें - KernelSU अभी केवल GKI कर्नल्स को सपोर्ट करता है - SELinux स्थिति - सिस्टम एप्प छिपाए - वर्जन - सपोर्ट नहीं करता है - डोमेन - होम - कस्टम - टेम्पलेट - रिफ्रेश - %s मॉड्यूल डाउनलोड हो रहा है - अपडेट - KernelSU सीखें - क्या आप सच में मॉड्यूल %s को अनइंस्टॉल करना चाहते हैं\? - %s अनइंस्टल करने में असफल - सुपरयूजर - सेटिंग - काम कर रहा है - %s मॉड्यूल बंद करने में विफल - कोई मॉड्यूल इंस्टाल नहीं हुआ - इंस्टाल करें - कर्नल - इंस्टाल नहीं हुआ - %s के लिए ऐप प्रोफ़ाइल अपडेट करने में विफल - https://kernelsu.org/guide/what-is-kernelsu.html - %s के लिए SELinux नियमों को अपटेड करने में विफल - बुटलोडर में रिबूट करें - %1$s पर स्रोत कोड देखें
हमारे %2$s चैनल से जुड़ें
- मैनेजर वर्जन - नया वर्जन: %s उपलब्ध है,अपग्रेड के लिए क्लिक करें - लॉग सहेजें -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-hr/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-hr/strings.xml deleted file mode 100644 index 9fb1e4c67460..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-hr/strings.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - Prikažite sistemske aplikacije - Sakrijte sistemske aplikacije - Pošaljite Izvještaj - Sigurnosni mod - Ponovno pokrenite da bi proradilo - Neuspješno ažuriranje SELinux pravila za: %s - Početna - Nije instalirano - Verzija: %d - Kliknite da instalirate - Radi - Superkorisnici: %d - Module: %d - Nepodržano - KernelSU samo podržava GKI kernele sad - Kernel - Verzija Voditelja - Otisak prsta - Isključeno - U Provođenju - Permisivno - SELinux stanje - Nepoznato - Superkorisnik - Neuspješno uključivanje module: %s - Neuspješno isključivanje module: %s - Nema instaliranih modula - Modula - Deinstalirajte - Instalirajte - Instalirajte - Ponovno pokrenite - Postavke - Lagano Ponovno pokretanje - Ponovno pokrenite u Oporavu - Ponovno pokrenite u Pogonski Učitavalac - Ponovno pokrenite u Preuzimanje - Ponovo pokrenite u EDL - O - Jeste li sigurni da želite deinstalirati modulu %s\? - %s deinstalirana - Neuspješna deinstalacija: %s - Verzija - Autor - Osvježi - overlayfs nije dostupan, modula ne može raditi! - Module su isključene jer je u sukobu sa Magisk-om! - Naučite KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Naučite kako da instalirate KernelSU i da koristite module - Podržite Nas - KernelSU je, i uvijek če biti, besplatan, i otvorenog izvora. Možete nam međutim pokazati da vas je briga s time da napravite donaciju. - Pogledajte izvornu kodu na %1$s
Pridružite nam se na %2$s kanalu
- Zadano - Šablon - Prilagođeno - Naziv profila - Naslijeđen - Imenski prostor nosača - Ažuriranje Profila Aplikacije za %s nije uspjelo - Globalan - Pojedinačan - Umount module - Grupe - Sposobnosti - SELinux kontekst - Trenutna KernelSU verzija %d je preniska da bi voditelj ispravno radio. Molimo vas da nadogradite na verziju %d ili noviju! - Umount module po zadanom - Globalna zadana vrijednost za \"Umount module\" u Profilima Aplikacije. Ako je omogućeno, uklonit će sve izmjene modula na sistemu za aplikacije koje nemaju postavljen Profil. - Domena - Uključivanjem ove opcije omogućit će KernelSU-u da vrati sve izmjenute datoteke od strane modula za ovu aplikaciju. - Pravila - Ažuriranje - Preuzimanje module: %s - Započnite sa preuzimanjem: %s - Nova verzija: %s je dostupna, kliknite da preuzmete - Pokrenite - Prisilno Zaustavite - Resetujte - Spremi Zapise -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-hu/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-hu/strings.xml deleted file mode 100644 index 2b52317c1b79..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-hu/strings.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - Működik - Verzió: %d - Modulok: %d - KernelSU csak GKI kerneleket támogat jelenleg - Kernel - App verziója - Build Fingerprint - Kikapcsolt - Újraindítás letöltő módba - Újraindítás EDL-be - Névjegy - Biztos vagy benne hogy eltávolítod a következő modult: %s\? - Nem sikerült eltávolítani: %s - Készítő - Overlayfs nem elérhető, a modul nem tud enélkül működni! - Újratöltés - Mutasd a rendszer alkalmazásokat - Rejtsd el a rendszer alkalmazásokat - Biztonságos mód - A modul letiltva mert ütközik a Magisk verziójával! - Tudj meg többet a KernelSU-ról - Tudd meg hogyan telepítsd a KernelSU-t és használd moduljait - Támogass minket - Tekintsd meg a forráskódot a %1$s-n
Csatlakozz a %2$s csatornánkhoz
- Alapértelmezett - Sablon - Egyedi - Profil neve - Mountold a névteret - Örökölt - https://kernelsu.org/guide/what-is-kernelsu.html - Különálló - Csoportok - Jogosultságok - SElinux kontextus - Umountold a modulokat alpértelmezés szerint - Ennek az opciónak az engedélyezése lehetővé teszi, hogy a KernelSU visszaállítsa az alkalmazás moduljai által módosított fájlokat. - Tartomány - Szabályok - Frissítés - A %s modul letöltése folyamatban - Indítsd el a letöltést: %s - Indítás - Kényszerített leállítás - újraindítás - Kezdőlap - Nincs telepítve - Kattints a telepítéshez - Engedélyezett alkalmazások: %d - Nem támogatott - SELinux státusz - Érvényesítés - Megengedő - Ismeretlen - Super user - Nem sikerült engedélyezni a következő modult: %s - Nem sikerült letiltani a következő modulokat: %s - Nincs modul telepítve - Modulok - Eltávolítás - Telepítés - Telepítés - Újraindítás - Beállítások - Android felület újraindítása - Újraindítás recovery-módba - Újraindítás bootloader-módba - %s törölve - Verzió - Napló küldése - Indítsd újra a készüléket hogy érvényesítsd a változást - A KernelSU ingyenes és nyílt forráskódú és mindig is az lesz. Te viszont meg tudod mutatni azt, hogy törődsz ennek a projektnek a sorsával egy adomány formájában. - Globális - Unmountold a modulokat - Nem sikerült frissíteni az App Profilt ehhez %s - A „Modulok csatlakoztatása” globális alapértelmezett értéke az alkalmazásprofilokban. Ha engedélyezve van, eltávolítja a rendszer összes modul-módosítását azoknál az alkalmazásoknál, amelyeknek nincs beállított profilja. - Új verzió: %s elérhető, kattints a frissítéshez - Nem sikerült frissíteni a SELinux szabályait a következőhöz: %s - A jelenlegi KernelSU verzió %d túlságosan elavult. Kérlek frissíts a %d verzióra vagy újabbra! - Sikeresen importálva - Exportálás a vágólapból - A helyi sablon nem található az exportáláshoz! - A sablon ID már létezik! - Változások - Importálás a vágólapból - A változásnapló lekérése nem sikerült: %s - Név - Hibás sablon ID - Online sablonok szinkronizálása - Sablon készítése - csak olvasható - Import/Export - A sablon mentése sikertelen - Sablon szerkesztése - id - Alkalmazásprofil sablon - Leírás - Mentés - Az alkalmazásprofil helyi és online sablon kezelése - Törlés - A vágólap üres! - Sablon megnézése - Naplók Mentése -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-in/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-in/strings.xml deleted file mode 100644 index 98698f529aa9..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-in/strings.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - Beranda - Tidak terinstal - Klik untuk menginstal - Berfungsi - Versi: %d - SuperUser: %d - Modul: %d - Tidak didukung - KernelSU saat ini hanya mendukung kernel GKI - Kernel - Versi Manager - Identitas - Status SELinux - Nonaktif - Enforcing - Permissive - Unknown - SuperUser - Gagal mengaktifkan modul: %s - Gagal menonaktifkan modul: %s - Tidak ada modul - Modul - Hapus - Instal - Instal - Reboot - Pengaturan - SoftReboot - But ke Recovery - But ke Bootloader - But ke Download - But ke EDL - Tentang - Yakin menghapus modul %s? - %s berhasil dihapus - Gagal menghapus: %s - Versi - Oleh - OverlayFS tidak tersedia, modul tidak berfungsi! - Muat ulang - Tampilkan aplikasi sistem - Sembunyikan aplikasi sistem - Laporkan Log - Mode aman - Reboot agar berfungsi - Konflik dengan Magisk, fungsi modul ditiadakan! - Pelajari KernelSU - https://kernelsu.org/id_ID/guide/what-is-kernelsu.html - Pelajari cara instal KernelSU dan menggunakan modul - Dukung Kami - KernelSU akan selalu menjadi aplikasi gratis dan terbuka. Anda dapat memberikan donasi sebagai bentuk dukungan. - Lihat kode sumber di %1$s
Gabung kanal %2$s kami
- Profil Apl - Bawaan - Templat - Khusus - Nama profil - Mount Namespace - Diwariskan - Universal - Individual - Kelompok - Kemampuan - Konteks SELinux - Umount Modul - Gagal membarui Profil pada %s - Melepas Modul secara bawaan - Menggunakan \"Umount Modul\" secara universal pada Profil aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set Profil. - Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini. - Domain - Aturan - Membarui - Mengunduh modul: %s - Mulai mengunduh: %s - Tersedia versi terbaru: %s, Klik untuk membarui - Jalankan - Paksa Berhenti - Mulai ulang - Gagal membarui aturan SELinux pada: %s - Versi KernelSU %d terlalu rendah agar manajer berfungsi normal. Harap membarui ke versi %d atau di atasnya! - Catatan Perubahan - Berhasil diimpor - Ekspor ke papan klip - Tidak ditemukan templat lokal untuk diekspor! - Id templat sudah ada! - Impor dari papan klip - Gagal mengambil Changelog: %s - Nama - Id templat tidak valid - Sinkronkan templat daring - Buat Templat - Impor/Ekspor - Gagal menyimpan templat - Edit Templat - id - Templat Profil Aplikasi - Deskripsi - Simpan - Atur templat Profil yang lokal dan daring - Hapus - Papan klip kosong! - Lihat Templat - ReadOnly - Pengawakutuan WebView - Dapat mengawakutu WebView, hanya aktifkan jika butuh. - %1$s image partisi terekomendasi - Pilih KMI - Selanjutnya - Gawai akan **DIPAKSA** untuk but ke slot nonaktif! -\nHANYA gunakan setelah proses OTA selesai. -\nLanjutkan? - Instal Langsung (rekomendasi) - Pilih berkas - Instal ke slot nonaktif (setelah OTA) - Gagal memberikan akses root! - Buka - Cek terbaru - Cek terbaru setiap membuka aplikasi - Meminimalkan sparse image - Mengembalikan sparse image, lokasi modul disimpan, ke ukuran sebenarnya. Dapat menyebabkan modul bekerja abnormal, maka gunakan saat dibutuhkan saja (mis. untuk pencadangan) - Hapus permanen KernelSU (root dan modul). - Hapus Temporer - Pulihkan Image Asal - Hapus - Hapus Temporer KernelSU, pulihkan ke kondisi asali setelah but berikutnya. - Hapus Permanen - Pulihkan image bawaan ROM (jika cadangan tersedia), umumnya dilakukan sebelum OTA; jika ingin menghapus KernelSU, gunakan fungsi \"Hapus Permanen\". - Pemasangan Berhasil - LKM dipilih: %s - Pasang - Pemasangan Gagal - Simpan Log -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-it/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-it/strings.xml deleted file mode 100644 index 7bd3f9247356..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-it/strings.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - Home - Non installato - Clicca per installare - In esecuzione - Versione: %d - Applicazioni con accesso root: %d - Moduli installati: %d - Non supportato - KernelSU ora supporta solo i kernel GKI - Kernel - Versione del manager - Impronta della build di Android - Stato di SELinux - Disabilitato - Enforcing - Permissive - Sconosciuto - Accesso root - Impossibile abilitare il modulo: %s - Impossibile disabilitare il modulo: %s - Nessun modulo installato - Modulo - Disinstalla - Installa - Installa - Riavvia - Impostazioni - Riavvio rapido - Riavvia in modalità Recovery - Riavvia in modalità Bootloader - Riavvia in modalità Download - Riavvia in modalità EDL - Informazioni - Sei sicuro di voler disinstallare il modulo %s? - %s disinstallato - Impossibile disinstallare: %s - Versione - Autore - overlayfs non è disponibile, i moduli non possono funzionare! - Ricarica - Mostra app di sistema - Nascondi app di sistema - Invia log - Modalità provvisoria - Riavvia per applicare la modifica - I moduli sono disabilitati perché in conflitto con quelli di Magisk! - Scopri KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Scopri come installare KernelSU e utilizzare i moduli - Supportaci - KernelSU è, e sempre sarà, gratuito e open source. Puoi comunque mostrarci il tuo apprezzamento facendo una donazione. - Unisciti al nostro canale %2$s]]> - Nome profilo - Spazio dei nomi del mount - Globale - Gruppi - Ereditato - Individuale - Predefinito - Personalizzato - Modello - Scollega moduli - Contesto SELinux - Aggiornamento App Profile per %s fallito - Aggiorna - Apri - Capacità - Scollega moduli da default - Regole - Sto scaricando il modulo: %s - Inizia a scaricare:%s - Nuova versione: %s disponibile, tocca per aggiornare - Arresto forzato - Riavvia - Aggiornamento regole SELinux per %s fallito - Attivando questa opzione permetterai a KernelSU di ripristinare ogni file modificato dai moduli per questa app. - Dominio - Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato. - La versione attualmente installata di KernelSU (%d) è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %d o successiva! - Registro aggiornamenti - Crea modello - Modifica modello - identificativo - Identificativo modello non valido - Nome - Visualizza modello - Sola lettura - L\'identificativo del modello esiste già! - Importa/Esporta - Importa dagli appunti - Esporta negli appunti - Impossibile trovare modello locale da esportare! - Importato con successo - Sincronizza i modelli remoti - Gli appunti sono vuoti! - Impossibile ottenere l\'accesso root! - Modelli App Profile - Gestisci i modelli locali e remoti di App Profile - Elimina - Descrizione - Salva - Impossibile salvare il modello - Apri - Impossibile reperire il changelog: %s - Controlla aggiornamenti - Controlla automaticamente la disponibilità di aggiornamenti all\'apertura dell\'applicazione - Abilita il Debug di WebView - Può essere usato per svolgere il debug di WebUI, è consigliato attivarlo solo quando necessario. - È consigliato usare immagine della partizione %1$s - Scegli il KMI - Avanti - Installazione diretta (Raccomandata) - Scegli un File - Installa nello Slot Inattivo (Dopo OTA) - Il tuo dispositivo sarà **FORZATO** ad avviarsi nello slot inattivo dopo il riavvio! -\nUsa questa opzione solo quando l\'applicazione dell\'aggiornamento OTA è terminata. -\nProcedere? - Riduci la dimensione dell\'immagine moduli sparse al minimo - Riduci la dimensione dell\'immagine sparse dei moduli alla sua reale dimenzione. Nota che questo potrebbe causare malfunzionamenti dei moduli quindi utilizzala solo quando necessario (ad esempio in caso di backup) - Disinstalla - Disinstalla Temporaneamente - Disinstalla Permanentemente - Ripristina immagine originale del produttore - Disinstalla temporaneamente KernelSU, ripristina lo stato originale dopo il prossimo riavvio. - Disinstalla KernelSU (Root e tutti i moduli) completamente e permanentemente. - Installazione - Installazione completata - Installazione fallita - LKM selezionato: %s - Ripristina l\'immagine di fabbrica del produttore (se il backup è presente), solitamente usato prima di applicare l\'OTA; se devi disinstallare KernelSU, utilizza invece \"Disinstalla Permanentemente\". - Salva Registri - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-iw/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-iw/strings.xml deleted file mode 100644 index 18cfc638eb9d..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-iw/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - הפעל מחדש כדי להכניס לתוקף - למד כיצד להתקין את KernelSU ולהשתמש במודולים - לא ידוע - הצג אפליקציות מערכת - %s הוסר - הסרת טעינת מודולים - שלח לוג - מושבת - תמכו בנו - ירושה - מודולים מושבתים מכיוון שהם מתנגשים עם זה של Magisk! - יומן שינויים - התרים - הפעלה מחדש למצב הורדה - טעינת מודולים כברירת מחדל - הפעלת אפשרות זו תאפשר ל-KernelSU לשחזר קבצים שהשתנו על ידי המודולים עבור יישום זה. - אישי - הפעלת המודל נכשלה: %s - עצירה בכח - הפעלה מחדש למצב EDL - איתחול - יכולת - משתמשי על: %d - מפעיל מודל: %s - גלובלי - ערך ברירת המחדל הגלובלי עבור \"טעינת מודולים\" בפרופילי אפליקציה. אם מופעל, זה יסיר את כל שינויי המודול למערכת עבור יישומים שאין להם ערכת פרופיל. - מודלים:%d - אכיפה - הקשר SELinux - טביעת אצבע - ברירת מחדל - להשיק - מצב בטוח - גרסת KernelSU הנוכחית %d נמוכה מדי כדי שהמנהל יפעל כראוי. אנא שדרג לגרסה %d ומעלה! - הפעלה מחדש לריקברי - רך Reboot - שם פרופיל - KernelSU הוא, ותמיד יהיה, חינמי וקוד פתוח. עם זאת, תוכל להראות לנו שאכפת לך על ידי תרומה. - הסרה - טעינת מרחב שמות - התקנה - לחץ להתקנה - כללים - קבוצה - שכבות-על לא זמינות, המודול לא יכול לעבוד! - מודולים - יוצר - אודות - גרסה: %d - הפעלה מחדש - KernelSU תומך רק בליבת GKI כעת - סטטוס SELinux - הסתר אפליקציות מערכת - גרסה - אינו נתמך - תחום - בית - מותאם אישית - תבנית - רענון - מוריד מודל: %s - עדכון - למד אודות KernelSU - האם אתה בטוח שברצונך להסיר את התקנת המודל %s\? - הסרת התקנת %s נכשלה: - משתמש על - הגדרות - עובד - השבתת מודל %s נכשלה: - אין מודלים מותקנים - להתקין - Kernel - לא מותקן - נכשל עדכון פרופיל האפליקציה עבור %s - https://kernelsu.org/guide/what-is-kernelsu.html - נכשל עדכון כללי SELinux עבור: %s - הפעלה מחדש לבוטלאודר - ראה את קוד המקור ב%1$s
הצטרף אלינו %2$s בערוץ
- גרסת מנהל - גרסה חדשה עבור: %s זמינה, לחץ כדי לשדרג - שמור יומנים -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-ja/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-ja/strings.xml deleted file mode 100644 index 4ecf7420447a..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-ja/strings.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - ホーム - 未インストール - タップでインストール - 動作中 - バージョン: %d - スーパーユーザー: %d - モジュール: %d - 非対応 - 現在、 KernelSU は GKI カーネルにのみ対応しています - カーネル - アプリのバージョン - Fingerprint - SELinux の状態 - Disabled - Enforcing - Permissive - 不明 - スーパーユーザー - モジュールの有効化に失敗: %s - モジュールの無効化に失敗: %s - モジュールをインストールしていません - モジュール - アンインストール - インストール - インストール - 再起動 - 設定 - 通常の再起動 - リカバリーへ再起動 - ブートローダー へ再起動 - ダウンロードモードへ再起動 - EDL へ再起動 - アプリについて - モジュール %s をアンインストールしますか? - %s はアンインストールされました - アンインストールに失敗: %s - バージョン - 制作者 - OverlayFS が有効でないためモジュールは動作しません! - 更新 - システムアプリを表示 - システムアプリを非表示 - ログを送信 - セーフモード - 再起動すると有効化されます - Magisk と競合しているためモジュールは無効になっています! - KernelSU について - https://kernelsu.org/ja_JP/guide/what-is-kernelsu.html - KernelSU のインストール方法やモジュールの使い方はこちら - 支援する - KernelSU はこれからもずっとフリーでオープンソースです。寄付をすることで私たちを気にかけていることを示せます。 - %2$s チャンネルに参加]]> - アプリのプロファイル - 既定 - テンプレート - カスタム - プロファイル名 - 名前空間のマウント - 継承 - 共通 - 分離 - モジュールのアンマウント - グループ - SELinux コンテキスト - %s のアプリのプロファイルの更新をできませでした - ドメイン - ルール - 新しいバージョン: %s が利用可能です。タップしてダウンロード - アップデート - ダウンロードを開始: %s - 起動 - 強制停止 - 再起動 - SELinux ルールの更新に失敗しました: %s - ケーパビリティ - モジュールをダウンロード中: %s - このオプションを有効にすると、KernelSU はこのアプリのモジュールによって変更されたファイルを復元できるようになります。 - 既定でモジュールのマウントを解除 - アプリプロファイルの「モジュールのアンマウント」の共通のデフォルト値です。 有効にすると、プロファイルセットを持たないアプリのシステムに対するすべてのモジュールの変更が削除されます。 - 現在の KernelSU バージョン %d はマネージャーが適切に機能するには低すぎます。 バージョン %d 以降にアップグレードしてください! - 変更履歴 - インポート成功 - クリップボードからエクスポート - エクスポートするローカル テンプレートが見つかりません! - テンプレート id はすでに存在します! - クリップボードからインポート - 変更ログの取得に失敗しました: %s - 名前 - 無効なテンプレート id - オンラインテンプレートの同期 - テンプレートの作成 - 読み取り専用 - インポート/エクスポート - テンプレートの保存に失敗しました - テンプレートの編集 - id - アプリプロファイルのテンプレート - 説明 - 保存 - アプリプロファイルのローカルおよびオンラインテンプレートを管理する - 消去 - クリップボードが空です! - テンプレートを表示 - アップデートを確認 - アプリを開いたときにアップデートを自動的に確認する - root の付与に失敗しました! - 開く - WebView デバッグを有効にする - WebUI のデバッグに使用できます。必要な場合にのみ有効にしてください。 - %1$s パーティション イメージが推奨されます - KMI を選択してください - 次に - 非アクティブなスロットにインストール (OTA 後) - 再起動後、デバイスは**強制的に**、現在非アクティブなスロットから起動します。 -\nこのオプションは、OTA が完了した後にのみ使用してください。 -\n続く? - 直接インストール (推奨) - ファイルを選択してください - スパースイメージを最小化 - モジュールが配置されているスパースイメージのサイズを実際のサイズに変更します。 モジュールが正常に動作しなくなる可能性がありますので、必要な場合にのみご使用ください - 完全にアンインストールする - ストックイメージを復元 - 一時的にアンインストールする - アンインストール - KernelSU を一時的にアンインストールし、次回の再起動後に元の状態に戻します。 - KernelSU (ルートおよびすべてのモジュール) を完全かつ永久にアンインストールします。 - バックアップが存在する場合、工場出荷時のイメージを復元できます (OTA の前に使用してください)。KernelSU をアンインストールする必要がある場合は、「完全にアンインストールする」を使用してください。 - フラッシュ - フラッシュ成功 - フラッシュ失敗 - 選択された lkm: %s - ログを保存 - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-kn/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-kn/strings.xml deleted file mode 100644 index 3c4e79fe639f..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-kn/strings.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - ಪರಿಣಾಮ ಬೀರಲು ರೀಬೂಟ್ ಮಾಡಿ - KernelSU ಅನ್ನು ಹೇಗೆ ಸ್ಥಾಪಿಸಬೇಕು ಮತ್ತು ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ಬಳಸುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಿರಿ - ತಿಳಿಯದ - ಸಿಸ್ಟಮ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ತೋರಿಸಿ - %s ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿದೆ - Umount ಮಾಡ್ಯೂಲ್‌ಗಳು - ಲಾಗ್ ಕಳುಹಿಸಿ - ನಮ್ಮನ್ನು ಬೆಂಬಲಿಸಿ - ಪಿತ್ರಾರ್ಜಿತ - ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಏಕೆಂದರೆ ಇದು ಮ್ಯಾಜಿಸ್ಕ್‌ನೊಂದಿಗೆ ಸಂಘರ್ಷವಾಗಿದೆ! - ಚೇಂಜ್ಲಾಗ್ - Permissive - ಡೀಫಾಲ್ಟ್ ಆಗಿ Umount ಮಾಡ್ಯೂಲ್ - ಈ ಆಯ್ಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ ಈ ಅಪ್ಲಿಕೇಶನ್‌ಗಾಗಿ ಮಾಡ್ಯೂಲ್‌ಗಳ ಮೂಲಕ ಯಾವುದೇ ಮಾರ್ಪಡಿಸಿದ ಫೈಲ್‌ಗಳನ್ನು ಮರುಸ್ಥಾಪಿಸಲು KernelSU ಗೆ ಅನುಮತಿಸುತ್ತದೆ. - ವೈಯಕ್ತಿಕ - ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ: %s - ಫೋರ್ಸ್ ಸ್ಟಾಪ್ - EDL ಗೆ ರೀಬೂಟ್ - ಸಾಮರ್ಥ್ಯಗಳು - ಸೂಪರ್‌ಯೂಸರ್‌ಗಳು: %d - ಡೌನ್‌ಲೋಡ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಿ: %s - ಜಾಗತಿಕ - ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್‌ಗಳಲ್ಲಿ \"Umount ಮಾಡ್ಯೂಲ್\" ಗಾಗಿ ಜಾಗತಿಕ ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯ. ಸಕ್ರಿಯಗೊಳಿಸಿದರೆ, ಪ್ರೊಫೈಲ್ ಸೆಟ್ ಅನ್ನು ಹೊಂದಿರದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಸಿಸ್ಟಮ್‌ಗೆ ಎಲ್ಲಾ ಮಾಡ್ಯೂಲ್ ಮಾರ್ಪಾಡುಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ. - ಮಾಡ್ಯೂಲ್‌ಗಳು: %d - SELinux ಸಂದರ್ಭ - ಡೀಫಾಲ್ಟ್ - ಲಾಂಚ್ - ಸುರಕ್ಷಿತ ಮೋಡ್ - ಪ್ರಸ್ತುತ KernelSU ಆವೃತ್ತಿ %d ಮ್ಯಾನೇಜರ್ ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ತುಂಬಾ ಕಡಿಮೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಆವೃತ್ತಿ %d ಅಥವಾ ಹೆಚ್ಚಿನದಕ್ಕೆ ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಿ! - ಸಾಫ್ಟ್ ರೀಬೂಟ್ - ಪ್ರೊಫೈಲ್ ಹೆಸರು - KernelSU ಉಚಿತ ಮತ್ತು ಮುಕ್ತ ಮೂಲವಾಗಿದೆ ಮತ್ತು ಯಾವಾಗಲೂ ಇರುತ್ತದೆ. ಆದಾಗ್ಯೂ ನೀವು ದೇಣಿಗೆ ನೀಡುವ ಮೂಲಕ ನೀವು ಕಾಳಜಿ ವಹಿಸುತ್ತೀರಿ ಎಂದು ನಮಗೆ ತೋರಿಸಬಹುದು. - ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ - ಮೌಂಟ್ ನೇಮ್‌ಸ್ಪೇಸ್ - ನಿಯಮಗಳು - ಗುಂಪುಗಳು - ಓವರ್‌ಲೇಫ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ, ಮಾಡ್ಯೂಲ್ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ! - ಮಾಡ್ಯೂಲ್ - ಲೇಖಕ - ಬಗ್ಗೆ - ವರ್ಷನ್: %d - ರೀಬೂಟ್ - KernelSU ಈಗ GKI ಕರ್ನಲ್‌ಗಳನ್ನು ಮಾತ್ರ ಬೆಂಬಲಿಸುತ್ತದೆ - SELinux ಸ್ಥಿತಿ - ಸಿಸ್ಟಮ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಮರೆಮಾಡಿ - ವರ್ಷನ್ - ಬೆಂಬಲಿತವಾಗಿಲ್ಲ - ಡೊಮೇನ್ - ಮನೆ - ಕಸ್ಟಮ್ - ಟೆಂಪ್ಲೇಟ್ - ರಿಫ್ರೆಶ್ - ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ: %s - KernelSU ಕಲಿಯಿರಿ - %s ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಅಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ\? - ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ: %s - ಸೂಪರ್ಯೂಸರ್ - ಕೆಲಸ ಮಾಡುತ್ತಿದೆ - ಮಾಡ್ಯೂಲ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ವಿಫಲವಾಗಿದೆ: %s - ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ - ಕರ್ನಲ್ - %s ಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ - https://kernelsu.org/guide/what-is-kernelsu.html - %1$s ನಲ್ಲಿ ಮೂಲ ಕೋಡ್ ಅನ್ನು ವೀಕ್ಷಿಸಿ
ನಮ್ಮ %2$s ಚಾನಲ್‌ಗೆ ಸೇರಿ
- ಮ್ಯಾನೇಜರ್ ವರ್ಷನ್ - ಹೊಸ ಆವೃತ್ತಿ: %s ಲಭ್ಯವಿದೆ, ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಲು ಕ್ಲಿಕ್ ಮಾಡಿ - ಲಾಗ್ಗಳನ್ನು ಉಳಿಸಿ -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-ko/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-ko/strings.xml deleted file mode 100644 index 7c29cc02f324..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-ko/strings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - 설치되지 않음 - 이 곳을 눌러 설치하기 - 정상 작동 중 - 버전: %d - 루트 권한: %d개 - 설치된 모듈: %d개 - 지원되지 않음 - KernelSU는 현재 GKI 커널만 지원합니다 - 커널 - 매니저 버전 - 빌드 정보 - SELinux 상태 - 비활성화됨 - 적용 - 허용 - 알 수 없음 - 슈퍼유저 - 모듈 활성화 실패: %s - 모듈 비활성화 실패: %s - 설치된 모듈 없음 - 모듈 - 삭제 - 설치 - 설치 - 다시 시작 - 설정 - 빠른 다시 시작 - 복구 모드로 다시 시작 - 부트로더로 다시 시작 - 다운로드 모드로 다시 시작 - EDL 모드로 다시 시작 - 정보 - %s 모듈을 삭제할까요? - %s 모듈 삭제됨 - 모듈 삭제 실패: %s - 버전 - 제작자 - overlayfs 사용 불가, 모듈을 사용할 수 없습니다! - 새로고침 - 시스템 앱 보이기 - 시스템 앱 숨기기 - 로그 보내기 - 안전 모드 - 다시 시작하여 변경 사항 적용 - Magisk와의 충돌로 인해 모듈을 사용할 수 없습니다! - KernelSU 알아보기 - KernelSU 설치 방법과 모듈 사용 방법을 확인합니다 - 지원이 필요합니다 - KernelSU는 지금도, 앞으로도 항상 무료이며 오픈 소스로 유지됩니다. 기부를 통해 여러분의 관심을 보여주세요. - %2$s 채널 참가하기]]> - https://kernelsu.org/guide/what-is-kernelsu.html - 앱 프로필 메뉴의 \"모듈 사용 해제\" 설정에 대한 전역 기본값을 설정합니다. 활성화 시, 개별 프로필이 설정되지 않은 앱은 시스템에 대한 모듈의 모든 수정사항이 적용되지 않습니다. - 다시 시작 - 규칙 - 새 버전: %s 사용 가능, 여기를 눌러서 받기 - 다운로드 시작: %s - 강제 중지 - 기본값 - 사용자 지정 - 템플릿 - 프로필 이름 - 이름 공간 마운트 - 상속 - 전역 - 개별 - 사용자 그룹 - 모듈 사용 해제 - SELinux 컨텍스트 - 권한 - %s에 대한 앱 프로필 업데이트 실패 - 기본값으로 모듈 사용 해제 - 이 옵션이 활성화되면, KernelSU는 이 애플리케이션에 대한 모듈의 모든 수정사항을 복구합니다. - 업데이트 - 모듈 받는 중: %s - 도메인 - 실행 - 다음 앱에 대한 SELinux 규칙 업데이트 실패: %s - 로그 저장 - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-lt/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-lt/strings.xml deleted file mode 100644 index cba5f5b18c25..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-lt/strings.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - Pirštų atspaudas - Išjungta - Priverstinas - Nežinomas - Supernaudotojai - Nepavyko įjungti modulio: %s - Nepavyko išjungti modulio: %s - Leistinas - Nėra įdiegtų modulių - Moduliai - Perkrovimas neišjungus - Perkrauti į atkūrimo rėžimą - Perkrauti į įkrovos tvarkyklę - Perkrauti į atsisiuntimo rėžimą - Apie - Nepavyko išdiegti: %s - %s išdiegtas - Versija - Autorius - overlayfs nepasiekiamas, modulis negali veikti! - Rodyti sistemos programas - Slėpti sistemos programas - Siųsti žurnalą - Paleisti iš naujo - Atšviežinti - Saugus rėžimas - Paleiskite iš naujo, kad įsigaliotų - Moduliai yra išjungti, nes jie konfliktuoja su Magisk\'s! - https://kernelsu.org/guide/what-is-kernelsu.html - Sužinokite apie KernelSU - Sužinokite, kaip įdiegti KernelSU ir naudoti modulius - Peržiūrėkite šaltinio kodą %1$s
Prisijunkite prie mūsų %2$s kanalo
- Numatytas - Šablonas - Pasirinktinis - Profilio pavadinimas - Prijungti vardų erdvę - Paveldėtas - Globalus - Individualus - Grupės - Galimybės - SELinux kontekstas - Atjungti modulius - Atjungti modulius pagal numatytuosius parametrus - Įjungus šią parinktį, KernelSU galės atkurti visus modulių modifikuotus failus šiai programai. - Domenas - Taisyklės - Atnaujinti - Atsisiunčiamas modulis: %s - Pradedamas atsisiuntimas: %s - Nauja versija: %s pasiekiama, spustelėkite norėdami atsinaujinti - Paleisti - Priversti sustoti - Perkrauti - Nepavyko atnaujinti SELinux taisyklių: %s - Namai - Neįdiegta - KernelSU dabar palaiko tik GKI branduolius - Spustelėkite norėdami įdiegti - Veikia - Supernaudotojai: %d - Versija: %d - Nepalaikoma - Moduliai: %d - Tvarkyklės versija - Branduolys - SELinux statusas - Išdiegti - Įdiegti - Įdiegti - Parametrai - Perkrauti į EDL - Ar tikrai norite išdiegti modulį %s\? - Paremkite mus - KernelSU yra ir visada bus nemokamas ir atvirojo kodo. Tačiau galite parodyti, kad jums rūpi, paaukodami mums. - Nepavyko atnaujinti programos profilio %s - Visuotinė numatytoji „Modulių atjungimo“ reikšmė programų profiliuose. Jei įjungta, ji pašalins visus sistemos modulio pakeitimus programoms, kurios neturi profilio. - Keitimų žurnalas - Ši KernelSU versija %d yra per žema, kad šis vadybininkas galėtų tinkamai funkcionuoti. Prašome atsinaujinti į versiją %d ar aukščiau! - Saglabāt Žurnālus -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-lv/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-lv/strings.xml deleted file mode 100644 index c264b76a650d..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-lv/strings.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - Iespējojot šo opciju, KernelSU varēs atjaunot visus moduļos šīs lietojumprogrammas modificētos failus. - Neizdevās atjaunināt SELinux noteikumus: %s - Pārvaldiet vietējo un tiešsaistes lietotņu profila veidni - Nederīgs veidnes id - veidnes id jau pastāv! - Eksportēt starpliktuvē - Importēt no starpliktuves - Importēts veiksmīgi - Sinhronizēt tiešsaistes veidnes - Sākums - Nav ieinstalēts - Noklikšķiniet, lai instalētu - Darbojas - Versija: %d - Superlietotāji: %d - Moduļi: %d - Neatbalstīts - KernelSU atbalsta tikai GKI kodolus - Kodols - Pārvaldnieka versija - Pirkstu nospiedums - SELinux statuss - Izpildīšana - Atspējots - Nezināms - SuperLietotājs - Neizdevās atspējot moduli: %s - Nav instalētu moduļu - Moduļi - Atinstalēt - Instalēt - Restartēt - Iestatījumi - Ātri restartēt - Restartēt uz Bootloaderu - Restartēt uz Recovery - Restartēt uz Download - Restartēt uz EDL - Par - %s ir atinstalēts - Neizdevās atinstalēt: %s - Autors - Atjaunot - Rādīt sistēmas lietotnes - Slēpt sistēmas lietotnes - Ziņot žurnālu - Restartējiet, lai stātos spēkā - Uzzināt par KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Uzzināt, kā instalēt KernelSU un izmantot moduļus - Atbalsti mūs - Skatiet avota kodu vietnē %1$s
Pievienojies mūsu %2$s kanālam
- Noklusējums - Veidne - Pielāgots - Profila vārds - Mount nosaukumvieta - Individuāls - Iespējas - SELinux konteksts - Atvienot moduļus - Neizdevās atjaunināt lietotnes profilu %s - Pēc noklusējuma atvienot moduļus - Globālā noklusējuma vērtība vienumam “Atvienot moduļus” lietotņu profilos. Ja tas ir iespējots, lietojumprogrammām, kurām nav iestatīts profils, tiks noņemtas visas sistēmas moduļu modifikācijas. - Domēns - Noteikumi - Atjaunināt - Lejupielādē moduli: %s - Sākt lejupielādi: %s - Jaunā versija: %s ir pieejama, noklikšķiniet, lai atjauninātu - Palaist - Piespiedu apstāšana - Restartēt aplikāciju - Izmaiņu žurnāls - Lietotnes profila veidne - Izveidot veidni - Rediģēt veidni - id - Vārds - Apraksts - Saglabāt - Dzēst - Skatīt veidni - tikai lasīt - Importēt/Eksportēt - Nevar atrast vietējo eksportējamo veidni! - Neizdevās saglabāt veidni - Starpliktuve ir tukša! - Izmaiņu žurnāla iegūšana neizdevās: %s - Visatļautība - Neizdevās iespējot moduli: %s - Instalēt - Vai tiešām vēlaties atinstalēt moduli %s? - Versija - overlayfs nav pieejams, modulis nevar darboties! - Drošais režīms - Moduļi ir atspējoti, jo tie konfliktē ar Magisk! - KernelSU ir un vienmēr būs bezmaksas un atvērtā koda. Tomēr jūs varat parādīt mums, ka jums rūp, veicot ziedojumu. - Grupas - Globāli - Pašreizējā KernelSU versija %d ir pārāk zema, lai pārvaldnieks darbotos pareizi. Lūdzu, atjauniniet uz versiju %d vai jaunāku! - Iespējot WebView atkļūdošanu - Ieteicams %1$s nodalījuma attēls - Nākamais - Mantots - Izvēlieties failu - Instalēt neaktīvajā slotā (pēc OTA) - Pēc restartēšanas jūsu ierīce tiks **PIESPIESTI** palaista pašreizējā neaktīvajā slotā! -\nIzmantojiet šo opciju tikai pēc OTA pabeigšanas -\nTurpināt? - Tiešā instalēšana (Ieteicams) - Atinstalēt - Pagaidu atinstalēšana - Atjaunot oriģinālo attēlu - Īslaicīgi atinstalēt KernelSU, pēc nākamās restartēšanas atjaunot sākotnējo stāvokli. - KernelSU (saknes un visu moduļu) pilnīga atinstalēšana. - Atjaunojot rūpnīcas attēlu (ja ir dublējums), ko parasti izmanto pirms OTA; ja nepieciešams atinstalēt KernelSU, lūdzu, izmantojiet \"Neatgriezeniski atinstalēt\". - Izvēlētais lkm: %s - Neizdevās piešķirt sakni! - Atvērt - Pārbaudīt atjauninājumus - Automātiski pārbaudīt atjauninājumus atverot aplikāciju - Var izmantot WebUI atkļūdošanai, lūdzu, izmantot tikai tad, kad tas ir nepieciešams. - Izvēlieties KMI - Neatgriezeniski atinstalēt - Instalē - Instalēts veiksmīgi - Instalēšana neizdevās - Samazināt reto attēlu - Mainīt retā attēla izmēru, kurā atrodas modulis, līdz tā faktiskajam izmēram. Ņemiet vērā, ka tas var izraisīt moduļa neparastu darbību, tāpēc, lūdzu, izmantojiet tikai nepieciešamības gadījumā (piemēram, dublēšanai) - Išsaugoti Žurnalus -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-mr/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-mr/strings.xml deleted file mode 100644 index eaaf2a255b44..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-mr/strings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - इंस्टॉल केले नाही - होम - इंस्टॉल साठी क्लिक करा - कार्यरत - आवृत्ती: %d - मॉड्यूल्स: %d - सुपरयूझर: %d - असमर्थित - KernelSU आता फक्त GKI कर्नलचे समर्थन करते - कर्नल - फिंगरप्रिंट - व्यवस्थापक आवृत्ती - SELinux स्थिती - अक्षम - एनफोर्सिंग - परमिसिव - अज्ञात - स्थापित करा - कोणतेही मॉड्यूल स्थापित केलेले नाही - रीबूट करा - सुपरयुझर - मॉड्यूल सक्षम करण्यात अयशस्वी: %s - विस्थापित करा - मॉड्यूल अक्षम करण्यात अयशस्वी: %s - मॉड्यूल - स्थापित करा - सेटिंग्ज - सॉफ्ट रीबूट - बद्दल - EDL वर रीबूट करा - तुमची खात्री आहे की तुम्ही मॉड्यूल %s विस्थापित करू इच्छिता\? - विस्थापित करण्यात अयशस्वी: %s - overlayfs उपलब्ध नाही, मॉड्यूल काम करू शकत नाही! - सिस्टम अॅप्स दाखवा - बूटलोडरवर रीबूट करा - %s विस्थापित - आवृत्ती - लेखक - रिफ्रेश करा - रिकवरी मध्ये रिबुट करा - डाउनलोड करण्यासाठी रीबूट करा - लॉग पाठवा - सुरक्षित मोड - सिस्टम अॅप्स लपवा - प्रभावी होण्यासाठी रीबूट करा - KernelSU शिका - https://kernelsu.org/guide/what-is-kernelsu.html - मॉड्यूल अक्षम केले आहेत कारण ते Magisk च्या विरोधाभास आहे! - KernelSU कसे स्थापित करायचे आणि मॉड्यूल कसे वापरायचे ते शिका - KernelSU विनामूल्य आणि मुक्त स्रोत आहे, आणि नेहमीच असेल. तथापि, देणगी देऊन तुम्ही आम्हाला दाखवू शकता की तुमची काळजी आहे. - आम्हाला पाठिंबा द्या - कस्टम - माउंट नेमस्पेस - डीफॉल्ट - साचा - वैयक्तिक - क्षमता - %1$s वर स्रोत कोड पहा
आमच्या %2$s चॅनेलमध्ये सामील व्हा
- प्रोफाइल नाव - इनहेरीटेड - जागतिक - गट - SELinux संदर्भ - उमाउंट मॉड्यूल्स - %s साठी अॅप प्रोफाइल अपडेट करण्यात अयशस्वी - डीफॉल्टनुसार मॉड्यूल्स उमाउंट करा - अॅप प्रोफाइलमधील \"उमाउंट मॉड्यूल्स\" साठी जागतिक डीफॉल्ट मूल्य. सक्षम असल्यास, ते प्रोफाइल सेट नसलेल्या ॲप्लिकेशनचे सिस्टममधील सर्व मॉड्यूल बदल काढून टाकेल. - हा पर्याय सक्षम केल्याने KernelSU ला या ऍप्लिकेशनसाठी मॉड्यूल्सद्वारे कोणत्याही सुधारित फाइल्स पुनर्संचयित करण्यास अनुमती मिळेल. - यासाठी SELinux नियम अपडेट करण्यात अयशस्वी: %s - नियम - अपडेट करा - डोमेन - मॉड्यूल डाउनलोड करत आहे: %s - डाउनलोड करणे सुरू करा: %s - नवीन आवृत्ती: %s उपलब्ध आहे, डाउनलोड करण्यासाठी क्लिक करा - सक्तीने थांबा - लाँच करा - पुन्हा सुरू करा - लॉग जतन करा -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-ms/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-ms/strings.xml deleted file mode 100644 index 46c1539c7ed0..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-ms/strings.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - Tidak Diketahui - Lumpuhkan - Permisif - Mulakan semula ke Download - Modul tidak berjaya Diaktifkan:%s - Mulakan semula ke EDL - Superusers%d - Modul%d - Enforcing - Cap Jari - Mulakan semula ke Recovery - Soft reboot - Padam - Pasang - Tekan untuk memasang - Modul - Tentang - Versi%d - Mulakan semula - KernelSU ketika ini hanya menyokong kernel GKI - Status SELinux - Tidak Disokong - Layar Utama - Apakah anda pasti ingin membuang modul %s\? - SuperUser - Tetapan - Berjalan - Gagal mematikan modul:%s - Tiada modul dipasang - Pasang - Kernel - Tidak terpasang - Mulakan semula ke bootloader - Versi Manager - Simpan Log - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-night-v27/themes.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-night-v27/themes.xml deleted file mode 100644 index 10a773b16f28..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-night-v27/themes.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-night/themes.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-night/themes.xml index 91abf657bfdc..d76ba8e6852b 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-night/themes.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/values-night/themes.xml @@ -1,10 +1,10 @@ - + - + + - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-vi/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-vi/strings.xml deleted file mode 100644 index 04d878381f78..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-vi/strings.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - Hồ sơ ứng dụng - Mặc định - Mẫu - Tuỳ chỉnh - Tên hồ sơ - Nhóm - Không thể cập nhật Hồ sơ ứng dụng cho %s - Ngắt mô-đun theo mặc định - Giá trị mặc định của \"Ngắt mô-đun\" trong Cấu hình ứng dụng. Nếu bật, KernelSU sẽ khôi phục mọi tệp hệ thống đã sửa đổi bởi mô-đun cho các ứng dụng chưa thiết lập Cấu hình. - Bật tùy chọn này sẽ khôi phục mọi tệp đã sửa đổi bởi các mô-đun cho ứng dụng này. - Cập nhật - Đang tải xuống mô-đun: %s - Bắt đầu tải xuống: %s - Phiên bản mới: %s đã có, bấm để nâng cấp - Tìm hiểu KernelSU - Tìm hiểu cách cài đặt KernelSU và sử dụng các mô-đun - Hỗ trợ chúng tôi - KernelSU sẽ luôn luôn miễn phí và mã nguồn mở. Tuy nhiên bạn có thể ủng hộ chúng tôi bằng một khoản đóng góp nhỏ. - Tham gia kênh %2$s của chúng tôi]]> - Các mô-đun bị vô hiệu hóa vì chúng xung đột với Magisk! - Bạn có muốn gỡ cài đặt mô-đun %s không\? - Nhật ký báo cáo - Trang chủ - Chưa cài đặt - Nhấn để cài đặt - Đang hoạt động - Phiên bản: %d - Không được hỗ trợ - KernelSU hiện tại chỉ hỗ trợ kernel GKI - Kernel - Phiên bản Manager - Fingerprint - Trạng thái SELinux - Vô hiệu hóa - Thực thi - Cho phép - Không rõ - SuperUser - Không thể kích hoạt mô-đun: %s - Không thể vô hiệu hóa mô-đun: %s - Chưa cài đặt mô-đun nào - Mô-đun - Gỡ cài đặt - Cài đặt - Cài đặt - Khởi động lại - Thiết đặt - Khởi động mềm - Khởi động lại vào Recovery - Khởi động lại vào Bootloader - Khởi động lại vào Download Mode - Khởi động lại vào EDL - Giới thiệu - %s được gỡ cài đặt - Lỗi khi gỡ cài đặt: %s - Phiên bản - Tác giả - overlayfs hiện không khả dụng, mô-đun không thể hoạt động! - Làm mới - Hiển thị ứng dụng hệ thống - Ẩn ứng dụng hệ thống - Chế độ an toàn - Khởi động lại để có hiệu lực - https://kernelsu.org/vi_VN/guide/what-is-kernelsu.html - Số superuser: %d - Số mô-đun: %d - Phạm vi - Quy định - Khởi chạy - Khởi động lại - Gắn namespace - Quyền - Không thể cập nhật quy định SELinux cho: %s - Buộc dừng - Thừa hưởng - Chung - Riêng - Bối cảnh SELinux - Ngắt mô-đun - KernelSU phiên bản %d quá thấp để trình quản lý hoạt động, hãy cập nhật lên %d hoặc mới hơn! - Đã nhập thành công - Xuất từ khay nhớ tạm - Không thể tìm thấy mẫu cục bộ để xuất! - id bản mẫu đã tồn tại! - Nhật ký thay đổi - Nhập từ khay nhớ tạm - Không nạp được nhật ký thay đổi: %s - Tên - Id mẫu không hợp lệ - Đồng bộ hóa các mẫu trực tuyến - Tạo Bản Mẫu - Nhập/Xuất - Không lưu được mẫu - Sửa Bản Mẫu - Mẫu Hồ Sơ Ứng Dụng - Mô tả - Lưu - Quản lý mẫu Hồ sơ Ứng dụng cục bộ và trực tuyến - Xóa - Clipboard trống! - Xem Bản Mẫu - chỉ đọc - id - Bật gỡ lỗi WebView - Có thể được sử dụng để gỡ lỗi WebUI, vui lòng chỉ bật khi cần. - Không cấp được quyền root! - Kiểm tra cập nhật - Tự động kiểm tra cập nhật khi mở ứng dụng - Mở - Cài đặt vào khe không hoạt động (Sau OTA) - Thiết bị của bạn sẽ **BẮT BUỘC** khởi động vào khe không hoạt động hiện tại sau khi khởi động lại! -\nChỉ sử dụng tùy chọn này sau khi OTA hoàn tất. -\nTiếp tục? - Tạm thời gỡ cài đặt KernelSU, khôi phục về trạng thái ban đầu sau lần khởi động lại tiếp theo. - Chọn KMI - Kế tiếp - Cài đặt trực tiếp (Được khuyến nghị) - Chọn một tệp - Gỡ cài đặt - Gỡ cài đặt tạm thời - Gỡ cài đặt vĩnh viễn - Khôi phục hình ảnh gốc - Gỡ cài đặt KernelSU (Root và tất cả các mô-đun) hoàn toàn và vĩnh viễn. - Khôi phục hình ảnh gốc của nhà máy (nếu có bản sao lưu), thường được sử dụng trước OTA; nếu bạn cần gỡ cài đặt KernelSU, vui lòng sử dụng \"Gỡ cài đặt vĩnh viễn\". - Đang cài - Cài thành công - Cài thất bại - Đã chọn lkm: %s - Nên sử dụng hình ảnh phân vùng %1$s - Giảm thiểu hình ảnh thưa thớt - Thay đổi kích thước hình ảnh thưa nơi đặt mô-đun theo kích thước thực tế của nó. Lưu ý điều này có thể khiến module hoạt động không bình thường nên vui lòng chỉ sử dụng khi cần thiết (chẳng hạn như để sao lưu) - Lưu Nhật Ký - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rCN/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rCN/strings.xml deleted file mode 100644 index ff11137df5ef..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - 主页 - 未安装 - 点击安装 - 工作中 - 版本: %d - 超级用户数:%d - 不支持 - KernelSU 现在只支持 GKI 内核 - 内核版本 - 管理器版本 - 系统指纹 - SELinux 状态 - 被禁用 - 强制执行 - 宽容模式 - 未知 - 超级用户 - 无法启用模块: %s - 无法禁用模块: %s - 没有安装模块 - 模块 - 卸载 - 安装 - 安装 - 重启 - 设置 - 软重启 - 重启到 Recovery - 重启到 BootLoader - 重启到 Download - 重启到 EDL - 关于 - 确定要卸载模块 %s 吗? - %s 已卸载 - 卸载失败: %s - 版本 - 作者 - 内核不支持 overlayfs,模块功能无法运作! - 刷新 - 显示系统应用 - 隐藏系统应用 - 发送日志 - 安全模式 - 重启生效 - 所有模块已被禁用,因为它与 Magisk 的模块系统有冲突! - 模块数:%d - 了解 KernelSU - https://kernelsu.org/zh_CN/guide/what-is-kernelsu.html - 了解如何安装 KernelSU 以及如何开发模块 - 支持开发 - KernelSU 将保持免费开源,向开发者捐赠以表示支持。 - 加入我们的 %2$s 频道
加入我们的 QQ 频道]]>
- 默认 - 模版 - 自定义 - 名称 - 命名空间 - 继承 - 全局 - 私有 - - 权能 - SELinux - 卸载模块 - 为 %s 更新 App Profile 失败 - 当前 KernelSU 版本 %d 过低,管理器无法正常工作,请升级内核 KernelSU 版本至 %d 或以上! - 默认卸载模块 - App Profile 中\"卸载模块\"的全局默认值,如果启用,将会为没有设置 Profile 的应用移除所有模块针对系统的修改。 - 启用后将允许 KernelSU 为本应用还原被模块修改过的文件。 - - 规则 - 更新 - 正在下载模块:%s - 开始下载:%s - 发现新版本:%s,点击升级 - 启动 - 强制停止 - 重新启动 - 为:%s 更新翻译失败 - 更新日志 - App Profile 模版 - 管理本地和在线的 App Profile 模版 - 创建模版 - 编辑模版 - 模版 id - 模版 id 不合法 - 名字 - 描述 - 保存 - 删除 - 查看模版 - 只读 - 模版 id 已存在! - 导入/导出 - 从剪切板导入 - 导出到剪切板 - 没有本地模版可以导出! - 导入成功! - 同步在线规则 - 模版保存失败! - 剪切板为空! - 获取更新日志失败:%s - 检查更新 - 在应用启动后自动检查是否有最新版 - 获取 root 失败! - 打开 - 启用 WebView 调试 - 可用于调试 WebUI ,请仅在需要时启用。 - 直接安装(推荐) - 选择一个文件 - 安装到未使用的槽位(OTA 后) - 将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认? - 下一步 - 建议选择 %1$s 分区镜像 - 选择 KMI - 最小化稀疏文件 - 将模块所在的稀疏文件镜像调整为其实际大小,注意这可能导致模块工作异常,请仅在必要时(如备份)使用 - 卸载 - 临时卸载 - 永久卸载 - 恢复原厂镜像 - 临时卸载 KernelSU,下次重启后恢复 - 完全并永久移除 KernelSU 和所有模块 - 恢复原厂镜像,一般在 OTA 前使用;如需卸载请使用“永久卸载” - 刷写中 - 刷写完成 - 刷写失败 - 选择的 LKM :%s - 保存日志保存日志 -
\ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rHK/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rHK/strings.xml deleted file mode 100644 index 154ddac9bb8d..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - 首頁 - 未安裝 - 按一下以安裝 - 運作中 - KernelSU 版本:%d - 超級使用者:%d 個 - 已安裝模組:%d 個 - 不支援 - KernelSU 現在僅支援 GKI 核心 - 核心 - 管理器版本 - 指紋 - SELinux 狀態 - 已停用 - 強制 - 寬鬆 - 未知 - 超級使用者 - 無法啟用模組:%s - 無法停用模組:%s - 尚未安裝模組 - 模組 - 解除安裝 - 安裝 - 安裝 - 重新啟動 - 設定 - 軟啟動 - 重新啟動至 Recovery - 重新啟動至 Bootloader - 重新啟動至 Download - 重新啟動至 EDL - 關於 - 您確定要解除安裝模組「%s」嗎? - 「%s」已解除安裝 - 無法解除安裝:%s - 版本 - 作者 - OverlayFS 無法使用,模組無法正常運作! - 重新整理 - 顯示系統應用程式 - 隱藏系統應用程式 - 傳送記錄 - 安全模式 - 重新啟動以生效 - 模組已停用,因其與 Magisk 的模組存在衝突! - 深入瞭解 KernelSU - https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html - 瞭解如何安裝 KernelSU 以及如何開發模組 - 支援開發 - KernelSU 將保持免費和開源,您可以考慮向開發人員贊助以表示支持。 - 加入我們的 %2$s 頻道]]> - 預設 - 設定檔名稱 - 範本 - 繼承 - 全域 - 功能 - 卸載模組 - 無法更新 %s 應用程式設定檔 - 規則 - 目前 KernelSU 版本 %d 過低,管理器無法正常運作。請升級至 %d 或更高版本! - 應用程式設定檔中「解除安裝模組」的全域預設值,如果啟用,將會為沒有設定檔的應用程式移除所有模組針對系統的修改。 - 啟用此選項將允許 KernelSU 為這個應用程式還原任何被模組修改過的檔案。 - 網域 - 更新 - 自訂 - 掛載命名空間 - 個人 - 群組 - SELinux 環境 - 預設解除安裝模組 - 正在下載模組:%s - 開始下載:%s - 新版本:%s 已可供使用,按一下以升級 - 啟動 - 強制停止 - 重新啟動 - 無法為 %s 更新 SELinux 規則 - 變更記錄 - 成功匯出 - 導出到剪貼板 - 本地沒有模板可匯出! - 模板 ID 已存在! - 從剪貼簿匯入 - 獲取更新日誌失敗:%s - 名字 - 模板 ID 無效 - 同步在線規則 - 創建模板 - 只讀 - 匯出 / 匯入 - 模板儲存失敗 - 編輯模板 - 模板 ID - App Profile 模板 - 描述 - 儲存 - 管理本地和線上的 App Profile 模板 - 刪除 - 剪貼簿沒有內容! - 查看模板 - 啟用 WebView 偵錯 - 可用於偵錯WebUI,請僅在需要時啟用。 - 直接安裝(建議) - 選擇一個文件 - 安裝到非活動插槽(OTA 後) - 重新啟動後,您的裝置將強制啟動到目前非活動插槽! -\n僅在 OTA 完成後使用此選項。 -\n繼續? - 下一個 - 選擇KMI - 建議使用 %1$s 分割區映像 - 授予root權限失敗! - 打開 - 檢查更新 - 開啟應用程式時自動檢查更新 - 最小化稀疏影像 - 將模組所在的稀疏影像調整為實際大小。 請注意,這可能會導致模組工作異常,因此請僅在必要時使用(例如備份) - 解除安裝 - 保存日志 - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rTW/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rTW/strings.xml deleted file mode 100644 index 7917ddef9994..000000000000 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - 首頁 - 未安裝 - 按一下以安裝 - 運作中 - KernelSU 版本:%d - 已授權 Root:%d 個 - 不支援 - KernelSU 現在僅支援 GKI 核心 - 核心 - 管理器版本 - 指紋 - SELinux 狀態 - 已停用 - 強制 - 寬鬆 - 未知 - Root 授權 - 無法啟用模組:%s - 無法停用模組:%s - 尚未安裝模組 - 模組 - 解除安裝 - 安裝 - 安裝 - 重新啟動 - 設定 - 軟重新啟動 - 重新啟動至 Recovery - 重新啟動至 Bootloader - 重新啟動至 Download - 重新啟動至 EDL - 關於 - 您確定要解除安裝模組「%s」嗎? - 「%s」已解除安裝 - 無法解除安裝:%s - 版本 - 作者 - OverlayFS 無法使用,模組無法正常運作! - 重新整理 - 顯示系統應用程式 - 隱藏系統應用程式 - 傳送記錄 - 安全模式 - 重新啟動以生效 - 模組已停用,因其與 Magisk 的模組存在衝突! - 已安裝模組:%d 個 - 深入瞭解 KernelSU - https://kernelsu.org/zh_TW/guide/what-is-kernelsu.html - 瞭解如何安裝 KernelSU 以及如何開發模組 - 支援開發 - KernelSU 將保持免費和開源,您可以考慮向開發人員贊助以表示支持。 - 加入我們的 %2$s 頻道]]> - 卸載模組 - 無法更新 %s 應用程式設定檔 - 目前安裝的 KernelSU 版本 %d 過低,管理器無法正常工作,請升級核心 KernelSU 版本至 %d 或以上! - 預設卸載模組 - 應用程式設定檔中「卸載模組」的全域預設值,如果啟用,將會為沒有設定檔的應用程式移除所有模組針對系統的修改。 - 啟用後將允許 KernelSU 為本應用程式還原被模組修改過的檔案。 - 預設 - 自訂 - 權限 - 規則 - 正在下載模組:%s - 重新啟動 - 模板 - 設定檔名稱 - 掛載命名空間 - 繼承 - 全域 - 私人 - 群組 - SELinux context - - 更新 - 開始下載:%s - 發現新版本:%s 已可供使用,按一下即可升級 - 啟動 - 強制停止 - 無法為 %s 更新 SELinux - 變更記錄 - 模板 ID 無效 - 創建模板 - 編輯模板 - 模板 ID - App Profile 模板 - 管理本地和線上的 App Profile 模板 - 成功匯入 - 匯出至剪貼簿 - 沒有本地模板可匯出! - 模板 ID 已存在! - 從剪貼簿匯入 - 獲取更新日誌失敗:%s - 名稱 - 與線上規則同步 - 唯讀 - 匯出 / 匯入 - 模板儲存失敗 - 描述 - 儲存 - 刪除 - 剪貼簿沒有內容! - 檢查模板 - 可用於偵錯 WebUI,請僅在需要時啟用。 - 啟用 WebView 偵錯 - 取得root失敗! - 開啟 - 檢查更新 - 在打開App時自動檢查更新 - 選擇一個檔案 - 安裝到非使用中的槽位(在 OTA 更新後) - 您的裝置將在下次重新啟動後強制切換到非使用中的槽位! -\n這個選項僅在 OTA 更新完畢後使用。 -\n請問是否繼續? - 直接安裝(建議) - 下一步 - 選擇 KMI - 建議使用 %1$s 分區 - 最小化模組稀疏映像 - 將模組的稀疏映像調整為其實際大小,請注意這可能導致模組工作異常,請僅在需要時(如備份)使用 - 解除安裝 - 暫時解除安裝 - 還原原廠映像 - 暫時卸載KernelSU,下次重啟後恢復原狀。 - 永久解除安裝 - 完全的(永久的)解除安裝 KernelSU(Root 和所有模組)。 - 寫入中 - 寫入完成 - 恢復原廠映像(如果有備份),通常在OTA之前使用;如果需要解除安裝KernelSU,請使用「永久解除安裝」。 - 寫入失敗 - 選擇的 LKM :%s - 儲存日誌 - \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values/colors.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values/colors.xml new file mode 100644 index 000000000000..a5b623aa4885 --- /dev/null +++ b/drivers/staging/kernelsu/manager/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #FFFFFFFF + \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values/strings.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values/strings.xml index d094969af1a2..39a26845e48c 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values/strings.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ - KernelSU + Confirm + KernelSU Next Home Not installed Click to install @@ -8,22 +9,25 @@ Version: %d Superusers: %d Modules: %d - Unsupported - KernelSU only supports GKI kernels now + Next v2 signature not found in kernel! + !KSU_NEXT || != size/hash Kernel - Manager Version - Fingerprint - SELinux status + Android + Manager + SELinux Disabled Enforcing Permissive Unknown - SuperUser + Superuser Failed to enable module: %s Failed to disable module: %s - No installed modules + No module installed Module + Confirm Installation + Do you want to continue installing this module %1$s? Uninstall + Restore Install Install Reboot @@ -35,24 +39,30 @@ Reboot to EDL About Are you sure you want to uninstall module %s? - %s is uninstalled + %s uninstalled Failed to uninstall: %s + Are you sure you want to restore module %s? + %s restoreed + Failed to restore: %s Version Author - overlayfs is not available, module cannot work! Refresh Show system apps Hide system apps - Report Log + Send logs Safe mode Reboot to take effect - Modules are disabled because it is conflict with Magisk\'s! - Learn KernelSU - https://kernelsu.org/guide/what-is-kernelsu.html - Learn how to install KernelSU and use modules - Support Us - KernelSU is, and always will be, free, and open source. You can however show us that you care by making a donation. - Join our %2$s channel]]> + Modules are unavailable due to a conflict with Magisk! + 🔥 Next Build + https://github.com/rifsxd/KernelSU-Next + Next experimental branch. Check it out on GitHub! + ⚠️ Experimental Development Warning! + 127.0.0.1 + Next is a non-official build which is always under active experimental development. It is provided as-is, with no guarantees of stability, performance, or reliability. + • Use at Your Own Risk: It may experience crashes, unexpected behavior, or cause system issues. + • No Warranty: The developers are not responsible for any data loss, system damage, or other consequences arising from its use. + • For Testing Purposes Only: It is intended for users who understand the risks and are comfortable troubleshooting issues. + App Profile Default Template @@ -67,38 +77,38 @@ SELinux context Umount modules Failed to update App Profile for %s - The current KernelSU version %d is too low for the manager to function properly. Please upgrade to version %d or higher! + The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher! Umount modules by default - The global default value for \"Umount modules\" in App Profiles. If enabled, it will remove all module modifications to the system for applications that do not have a Profile set. - Enabling this option will allow KernelSU to restore any modified files by the modules for this application. + The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set. + Enabling this option will allow KernelSU to restore any modified files by the modules for this app. Domain Rules Update Downloading module: %s Start downloading: %s - New version: %s is available, click to upgrade + New version %s is available, click to upgrade. Launch - Force Stop + Force stop Restart Failed to update SELinux rules for: %s Changelog App Profile Template Manage local and online template of App Profile - Create Template - Edit Template - id + Create template + Edit template + ID Invalid template id Name Description Save Delete - View Template - readonly - template id already exists! + View template + Read only + Template ID already exists! Import/Export Import from clipboard Export to clipboard - Can not find local template to export! + Cannot find local template to export! Imported successfully Sync online templates Failed to save template @@ -107,28 +117,30 @@ Check update Automatically check for updates when opening the app Failed to grant root! + Action Open - Enable WebView Debugging + Enable WebView debugging Can be used to debug WebUI, please enable only when needed. - Direct Install (Recommended) - Select a File - Install to Inactive Slot (After OTA) + Direct install (Recommended) + Select a file + Install to inactive slot (After OTA) Your device will be **FORCED** to boot to the current inactive slot after a reboot!\nOnly use this option after OTA is done.\nContinue? Next %1$s partition image is recommended Select KMI Minimize sparse image - Resize the sparse image where the module is located to its actual size. Note that this may cause the module to work abnormally, so please only use when necessary (such as for backup) + Resize the sparse image where the module is located to its actual size. Note that this may cause the module to work abnormally, so please only use when necessary (Such as for backup). Uninstall - Uninstall Temporarily - Uninstall Permanently - Restore Stock Image + Uninstall temporarily + Uninstall permanently + Restore stock image Temporarily uninstall KernelSU, restore to original state after next reboot. - Uninstalling KernelSU(Root and all modules) completely and permanently. - Restore the stock factory image (if a backup exists), usually used before OTA; if you need to uninstall KernelSU, please use \"Permanent Uninstall\". + Uninstalling KernelSU (Root and all modules) completely and permanently. + Restore the stock factory image (If a backup exists), usually used before OTA; if you need to uninstall KernelSU, please use \"Uninstall permanently\". Flashing Flash success Flash failed - Selected lkm: %s - Save Logs + Selected LKM: %s + Save logs + Logs saved \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/app/src/main/res/values/themes.xml b/drivers/staging/kernelsu/manager/app/src/main/res/values/themes.xml index 7d41d8ec77fc..31721d39e182 100644 --- a/drivers/staging/kernelsu/manager/app/src/main/res/values/themes.xml +++ b/drivers/staging/kernelsu/manager/app/src/main/res/values/themes.xml @@ -1,10 +1,13 @@ - + - + \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/build.gradle.kts b/drivers/staging/kernelsu/manager/build.gradle.kts index 0e503df3b636..3c4f02e7faef 100644 --- a/drivers/staging/kernelsu/manager/build.gradle.kts +++ b/drivers/staging/kernelsu/manager/build.gradle.kts @@ -15,29 +15,23 @@ cmaker { default { arguments.addAll( arrayOf( - "-DANDROID_STL=c++_static", + "-DANDROID_STL=none", ) ) - val flags = arrayOf( - "-Wno-gnu-string-literal-operator-template", - "-Wno-c++2b-extensions", - ) - cFlags.addAll(flags) - cppFlags.addAll(flags) - abiFilters("arm64-v8a", "x86_64") + abiFilters("arm64-v8a") } buildTypes { if (it.name == "release") { - arguments += "-DDEBUG_SYMBOLS_PATH=${buildDir.absolutePath}/symbols" + arguments += "-DDEBUG_SYMBOLS_PATH=${layout.buildDirectory.asFile.get().absolutePath}/symbols" } } } val androidMinSdkVersion = 26 -val androidTargetSdkVersion = 34 -val androidCompileSdkVersion = 34 -val androidBuildToolsVersion = "34.0.0" -val androidCompileNdkVersion = "26.3.11579264" +val androidTargetSdkVersion = 35 +val androidCompileSdkVersion = 35 +val androidBuildToolsVersion = "35.0.0" +val androidCompileNdkVersion = "27.0.12077973" val androidSourceCompatibility = JavaVersion.VERSION_21 val androidTargetCompatibility = JavaVersion.VERSION_21 val managerVersionCode by extra(getVersionCode()) @@ -85,6 +79,9 @@ subprojects { versionCode = managerVersionCode versionName = managerVersionName } + ndk { + abiFilters += listOf("arm64-v8a") + } } lint { diff --git a/drivers/staging/kernelsu/manager/gradle/libs.versions.toml b/drivers/staging/kernelsu/manager/gradle/libs.versions.toml index 6ec08d63e90b..23a61029556e 100644 --- a/drivers/staging/kernelsu/manager/gradle/libs.versions.toml +++ b/drivers/staging/kernelsu/manager/gradle/libs.versions.toml @@ -1,21 +1,20 @@ [versions] -agp = "8.4.1" -kotlin = "2.0.0" -ksp = "2.0.0-1.0.21" -compose-bom = "2024.05.00" -lifecycle = "2.8.0" -accompanist = "0.34.0" -navigation = "2.7.7" -activity-compose = "1.9.0" -kotlinx-coroutines = "1.8.1" -coil-compose = "2.6.0" -compose-destination = "1.10.2" +agp = "8.7.2" +kotlin = "2.0.21" +ksp = "2.0.21-1.0.28" +compose-bom = "2024.11.00" +lifecycle = "2.8.7" +navigation = "2.8.4" +activity-compose = "1.9.3" +kotlinx-coroutines = "1.9.0" +coil-compose = "2.7.0" +compose-destination = "2.1.0-beta14" sheets-compose-dialogs = "1.3.0" markdown = "4.6.2" -webkit = "1.11.0" +webkit = "1.12.1" appiconloader-coil = "1.5.0" parcelablelist = "2.0.1" -libsu = "5.2.2" +libsu = "6.0.0" apksign = "1.4" cmaker = "1.2" @@ -51,14 +50,9 @@ androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "l androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } -com-google-accompanist-drawablepainter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" } -com-google-accompanist-navigation-animation = { group = "com.google.accompanist", name = "accompanist-navigation-animation", version.ref = "accompanist" } -com-google-accompanist-systemuicontroller = { group = "com.google.accompanist", name = "accompanist-systemuicontroller", version.ref = "accompanist" } -com-google-accompanist-webview = { group = "com.google.accompanist", name = "accompanist-webview", version.ref = "accompanist" } - com-github-topjohnwu-libsu-core = { group = "com.github.topjohnwu.libsu", name = "core", version.ref = "libsu" } com-github-topjohnwu-libsu-service = { group = "com.github.topjohnwu.libsu", name = "service", version.ref = "libsu" } -com-github-topjohnwu-libsu-io= { group = "com.github.topjohnwu.libsu", name = "io", version.ref = "libsu" } +com-github-topjohnwu-libsu-io = { group = "com.github.topjohnwu.libsu", name = "io", version.ref = "libsu" } dev-rikka-rikkax-parcelablelist = { module = "dev.rikka.rikkax.parcelablelist:parcelablelist", version.ref = "parcelablelist" } @@ -68,11 +62,13 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c me-zhanghai-android-appiconloader-coil = { group = "me.zhanghai.android.appiconloader", name = "appiconloader-coil", version.ref = "appiconloader-coil" } -compose-destinations-animations-core = { group = "io.github.raamcosta.compose-destinations", name = "animations-core", version.ref = "compose-destination" } +compose-destinations-core = { group = "io.github.raamcosta.compose-destinations", name = "core", version.ref = "compose-destination" } compose-destinations-ksp = { group = "io.github.raamcosta.compose-destinations", name = "ksp", version.ref = "compose-destination" } sheet-compose-dialogs-core = { group = "com.maxkeppeler.sheets-compose-dialogs", name = "core", version.ref = "sheets-compose-dialogs" } sheet-compose-dialogs-list = { group = "com.maxkeppeler.sheets-compose-dialogs", name = "list", version.ref = "sheets-compose-dialogs" } sheet-compose-dialogs-input = { group = "com.maxkeppeler.sheets-compose-dialogs", name = "input", version.ref = "sheets-compose-dialogs" } -markdown = { group = "io.noties.markwon", name = "core", version.ref = "markdown" } \ No newline at end of file +markdown = { group = "io.noties.markwon", name = "core", version.ref = "markdown" } + +lsposed-cxx = { module = "org.lsposed.libcxx:libcxx", version = "27.0.12077973" } \ No newline at end of file diff --git a/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.jar b/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4..2c3521197d7c 100644 Binary files a/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.jar and b/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.jar differ diff --git a/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.properties b/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.properties index b82aa23a4f05..df97d72b8b91 100644 --- a/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.properties +++ b/drivers/staging/kernelsu/manager/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/drivers/staging/kernelsu/manager/gradlew b/drivers/staging/kernelsu/manager/gradlew index 4b6a9cfc46fa..f5feea6d6b11 100755 --- a/drivers/staging/kernelsu/manager/gradlew +++ b/drivers/staging/kernelsu/manager/gradlew @@ -1,4 +1,5 @@ #!/bin/sh + # # Copyright © 2015-2021 the original authors. # @@ -14,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -54,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/drivers/staging/kernelsu/manager/gradlew.bat b/drivers/staging/kernelsu/manager/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/drivers/staging/kernelsu/manager/gradlew.bat +++ b/drivers/staging/kernelsu/manager/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/drivers/staging/kernelsu/manager/settings.gradle.kts b/drivers/staging/kernelsu/manager/settings.gradle.kts index 2230bf48671a..e8f86c859b33 100644 --- a/drivers/staging/kernelsu/manager/settings.gradle.kts +++ b/drivers/staging/kernelsu/manager/settings.gradle.kts @@ -17,5 +17,5 @@ dependencyResolutionManagement { } } -rootProject.name = "KernelSU" +rootProject.name = "KernelSU-Next" include(":app") diff --git a/drivers/staging/kernelsu/userspace/ksud/Cargo.lock b/drivers/staging/kernelsu/userspace/ksud/Cargo.lock index 4e0b195fb99d..a373e3d6c386 100644 --- a/drivers/staging/kernelsu/userspace/ksud/Cargo.lock +++ b/drivers/staging/kernelsu/userspace/ksud/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "adler32" @@ -24,24 +24,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] -name = "aes" -version = "0.8.4" +name = "ahash" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", - "cipher", - "cpufeatures", + "cfg-if", + "once_cell", + "version_check", + "zerocopy", ] [[package]] -name = "aho-corasick" -version = "1.1.3" +name = "allocator-api2" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "android-properties" @@ -63,14 +61,13 @@ checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" [[package]] name = "android_logger" -version = "0.13.3" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" +checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" dependencies = [ "android_log-sys", - "env_logger 0.10.2", + "env_filter", "log", - "once_cell", ] [[package]] @@ -84,9 +81,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -99,91 +96,85 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - [[package]] name = "bitflags" version = "1.3.2" @@ -192,9 +183,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -219,48 +210,19 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.0.98" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ - "jobserver", - "libc", - "once_cell", + "shlex", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -281,21 +243,11 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - [[package]] name = "clap" -version = "4.5.4" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -303,9 +255,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -315,42 +267,42 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ "proc-macro2", "quote", @@ -358,33 +310,51 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "core-foundation-sys" -version = "0.8.6" +name = "core2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -454,10 +424,16 @@ dependencies = [ ] [[package]] -name = "deflate64" -version = "0.1.8" +name = "dary_heap" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d" +checksum = "04d2cd9c18b9f454ed67da600630b021a8a80bf33f8c95896ab33aaf1c26b728" + +[[package]] +name = "deflate64" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" [[package]] name = "deranged" @@ -470,24 +446,24 @@ dependencies = [ [[package]] name = "derive-new" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] @@ -498,59 +474,48 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", - "subtle", ] [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "env_filter", "log", @@ -580,7 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -605,21 +570,21 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.0.30" +name = "fastrand" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "generic-array" version = "0.14.7" @@ -645,22 +610,32 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -674,35 +649,13 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "hole-punch" -version = "0.0.4-alpha.0" -source = "git+https://github.com/tiann/hole-punch#11ab7a61bfb98682b72fd7f58a47d8e5d997328e" -dependencies = [ - "cfg-if 0.1.10", - "errno 0.2.8", - "libc", - "memmap", - "thiserror", - "winapi", -] - [[package]] name = "home" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -716,9 +669,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -739,103 +692,73 @@ dependencies = [ [[package]] name = "include-flate" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e11569346406931d20276cc460215ee2826e7cad43aa986999cb244dd7adb0" +checksum = "df49c16750695486c1f34de05da5b7438096156466e7f76c38fcdf285cf0113e" dependencies = [ - "include-flate-codegen-exports", + "include-flate-codegen", "lazy_static", "libflate", ] [[package]] name = "include-flate-codegen" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a7d6e1419fa3129eb0802b4c99603c0d425c79fb5d76191d5a20d0ab0d664e8" +checksum = "8c5b246c6261be723b85c61ecf87804e8ea4a35cb68be0ff282ed84b95ffe7d7" dependencies = [ "libflate", - "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.109", -] - -[[package]] -name = "include-flate-codegen-exports" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75657043ffe3d8280f1cb8aef0f505532b392ed7758e0baeac22edadcee31a03" -dependencies = [ - "include-flate-codegen", - "proc-macro-hack", + "syn", ] [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", + "hashbrown 0.15.0", ] [[package]] name = "is_executable" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" +checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2" dependencies = [ "winapi", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" [[package]] name = "java-properties" version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf6f484471c451f2b51eabd9e66b3fa7274550c5ec4b6c3d6070840945117f" +source = "git+https://github.com/Kernel-SU/java-properties.git?branch=master#42a4aa941b70ded2dd3be9e9f892471023e70229" dependencies = [ "encoding_rs", "lazy_static", - "regex", -] - -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", + "regex-lite", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -862,10 +785,9 @@ dependencies = [ "const_format", "derive-new", "encoding_rs", - "env_logger 0.11.3", + "env_logger", "extattr", "getopts", - "hole-punch", "humansize", "is_executable", "java-properties", @@ -875,57 +797,61 @@ dependencies = [ "loopdev", "nom", "procfs", - "regex", + "regex-lite", "retry", "rust-embed", - "rustix 0.38.30", + "rustix 0.38.34", "serde", "serde_json", "sha1", "sha256", - "tempdir", + "tempfile", "which", - "zip 2.1.0", + "zip", "zip-extensions", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libflate" -version = "1.4.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18" +checksum = "45d9dfdc14ea4ef0900c1cddbc8dcd553fbaacd8a4a282cf4018ae9dd04fb21e" dependencies = [ "adler32", + "core2", "crc32fast", + "dary_heap", "libflate_lz77", ] [[package]] name = "libflate_lz77" -version = "1.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf" +checksum = "e6e0d73b369f386f1c44abd9c570d5318f55ccde816ff4b562fa452e5182863d" dependencies = [ + "core2", + "hashbrown 0.14.5", "rle-decode-fast", ] [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "linux-raw-sys" @@ -941,9 +867,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loopdev" @@ -955,20 +881,20 @@ dependencies = [ ] [[package]] -name = "memchr" -version = "2.7.2" +name = "lzma-rs" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] [[package]] -name = "memmap" -version = "0.7.0" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" @@ -978,11 +904,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1012,53 +938,24 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "powerfmt" @@ -1068,73 +965,56 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" +checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "chrono", "flate2", "hex", - "lazy_static", "procfs-core", - "rustix 0.38.34", + "rustix 0.38.41", ] [[package]] name = "procfs-core" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" +checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "chrono", "hex", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -1143,7 +1023,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -1153,24 +1033,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -1201,51 +1066,10 @@ dependencies = [ ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "regex-lite" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "retry" @@ -1253,7 +1077,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9166d72162de3575f950507683fac47e30f6f2c3836b71b7fbc61aa517c9c5f4" dependencies = [ - "rand 0.8.5", + "rand", ] [[package]] @@ -1264,9 +1088,9 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rust-embed" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ "include-flate", "rust-embed-impl", @@ -1276,22 +1100,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.65", + "syn", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ "sha2", "walkdir", @@ -1305,29 +1129,29 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.30" -source = "git+https://github.com/Kernel-SU/rustix.git?branch=main#0e270bce2d97466be6b987bb5f7ea5b1e8d84969" +version = "0.38.34" +source = "git+https://github.com/Kernel-SU/rustix.git?branch=main#4a53fbc7cb7a07cabe87125cc21dbc27db316259" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno 0.3.9", "itoa", "libc", "linux-raw-sys", "once_cell", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno 0.3.9", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1347,31 +1171,32 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1382,7 +1207,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", "cpufeatures", "digest", ] @@ -1393,7 +1218,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] @@ -1411,6 +1236,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1423,17 +1254,11 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - [[package]] name = "syn" -version = "1.0.109" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -1441,44 +1266,36 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.65" +name = "tempfile" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand 0.4.6", - "remove_dir_all", + "cfg-if", + "fastrand", + "once_cell", + "rustix 0.38.41", + "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", ] [[package]] @@ -1502,9 +1319,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tokio" -version = "1.37.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -1519,33 +1336,33 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -1565,34 +1382,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.65", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1600,32 +1418,32 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.65", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "which" -version = "6.0.1" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" dependencies = [ "either", "home", - "rustix 0.38.34", + "rustix 0.38.41", "winsafe", ] @@ -1647,11 +1465,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1679,10 +1497,19 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.52.5" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1696,51 +1523,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winsafe" @@ -1749,53 +1576,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] -name = "zip" -version = "0.6.6" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "aes", "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "zip" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2568cd0f20e86cd9a7349fe05178f7bd22f22724678448ae5a9bac266df2689" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", - "bzip2", "crc32fast", "crossbeam-utils", "deflate64", "displaydoc", "flate2", "indexmap", + "lzma-rs", "memchr", "thiserror", "time", "zopfli", - "zstd 0.13.1", ] [[package]] name = "zip-extensions" -version = "0.6.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecf62554c4ff96bce01a7ef123d160c3ffe9180638820f8b4d545c65b221b8c" +checksum = "386508a00aae1d8218b9252a41f59bba739ccee3f8e420bb90bcb1c30d960d4a" dependencies = [ - "zip 0.6.6", + "zip", ] [[package]] @@ -1811,50 +1638,3 @@ dependencies = [ "once_cell", "simd-adler32", ] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" -dependencies = [ - "zstd-safe 7.1.0", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/drivers/staging/kernelsu/userspace/ksud/Cargo.toml b/drivers/staging/kernelsu/userspace/ksud/Cargo.toml index d031660307dc..b2700f56359e 100644 --- a/drivers/staging/kernelsu/userspace/ksud/Cargo.toml +++ b/drivers/staging/kernelsu/userspace/ksud/Cargo.toml @@ -2,48 +2,46 @@ name = "ksud" version = "0.1.0" edition = "2021" -rust-version = "1.77.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1" -clap = { version = "4", features = ["derive"] } +anyhow = "1.0" +clap = { version = "4.5", features = ["derive"] } const_format = "0.2" -zip = { version = "2", features = [ +zip = { version = "2.2", default-features = false } +zip-extensions = { version = "0.8", features = [ "deflate", "deflate64", - "bzip2", "time", - "zstd", + "lzma", + "xz", ], default-features = false } -zip-extensions = "0.6" -java-properties = "2" +java-properties = { git = "https://github.com/Kernel-SU/java-properties.git", branch = "master", default-features = false } log = "0.4" env_logger = { version = "0.11", default-features = false } -serde = { version = "1" } -serde_json = "1" -regex = "1" +serde = { version = "1.0" } +serde_json = "1.0" encoding_rs = "0.8" -retry = "2" -humansize = "2" +retry = "2.0" +humansize = "2.1" libc = "0.2" -extattr = "1" +extattr = "1.0" jwalk = "0.8" -is_executable = "1" -nom = "7" -derive-new = "0.6" -rust-embed = { version = "8", features = [ +is_executable = "1.0" +nom = "7.1" +derive-new = "0.7" +rust-embed = { version = "8.5", features = [ "debug-embed", "compression", # must clean build after updating binaries ] } -which = "6" +which = "7.0" getopts = "0.2" sha256 = "1" sha1 = "0.10" -tempdir = "0.3" +tempfile = "3.14" chrono = "0.4" -hole-punch = { git = "https://github.com/tiann/hole-punch" } +regex-lite = "0.1" [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] rustix = { git = "https://github.com/Kernel-SU/rustix.git", branch = "main", features = [ @@ -51,13 +49,14 @@ rustix = { git = "https://github.com/Kernel-SU/rustix.git", branch = "main", fea ] } # some android specific dependencies which compiles under unix are also listed here for convenience of coding android-properties = { version = "0.2", features = ["bionic-deprecated"] } -procfs = "0.16" +procfs = "0.17" loopdev = { git = "https://github.com/Kernel-SU/loopdev" } [target.'cfg(target_os = "android")'.dependencies] -android_logger = "0.13" +android_logger = { version = "0.14", default-features = false } [profile.release] strip = true opt-level = "z" -lto = true \ No newline at end of file +lto = true +codegen-units = 1 diff --git a/drivers/staging/kernelsu/userspace/ksud/bin/aarch64/resetprop b/drivers/staging/kernelsu/userspace/ksud/bin/aarch64/resetprop index 1155e5f49a3e..305032c90dc9 100644 Binary files a/drivers/staging/kernelsu/userspace/ksud/bin/aarch64/resetprop and b/drivers/staging/kernelsu/userspace/ksud/bin/aarch64/resetprop differ diff --git a/drivers/staging/kernelsu/userspace/ksud/bin/x86_64/resetprop b/drivers/staging/kernelsu/userspace/ksud/bin/x86_64/resetprop index dc4d9910e9ed..80030612649b 100644 Binary files a/drivers/staging/kernelsu/userspace/ksud/bin/x86_64/resetprop and b/drivers/staging/kernelsu/userspace/ksud/bin/x86_64/resetprop differ diff --git a/drivers/staging/kernelsu/userspace/ksud/src/banner b/drivers/staging/kernelsu/userspace/ksud/src/banner index 6087569c3f04..bf46a6ce9546 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/banner +++ b/drivers/staging/kernelsu/userspace/ksud/src/banner @@ -3,3 +3,7 @@ | ' // _ \ '__| '_ \ / _ \ \___ \| | | | | . \ __/ | | | | | __/ |___) | |_| | |_|\_\___|_| |_| |_|\___|_|____/ \___/ + | \ | | _____ _| |_ + | \| |/ _ \ \/ / __| + | |\ | __/> <| |_ + |_| \_|\___/_/\_\\__| diff --git a/drivers/staging/kernelsu/userspace/ksud/src/boot_patch.rs b/drivers/staging/kernelsu/userspace/ksud/src/boot_patch.rs index c2661c68fc76..3cc7305e34fa 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/boot_patch.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/boot_patch.rs @@ -10,6 +10,7 @@ use anyhow::bail; use anyhow::ensure; use anyhow::Context; use anyhow::Result; +use regex_lite::Regex; use which::which; use crate::defs; @@ -27,7 +28,6 @@ fn ensure_gki_kernel() -> Result<()> { #[cfg(target_os = "android")] pub fn get_kernel_version() -> Result<(i32, i32, i32)> { - use regex::Regex; let uname = rustix::system::uname(); let version = uname.release().to_string_lossy(); let re = Regex::new(r"(\d+)\.(\d+)\.(\d+)")?; @@ -52,7 +52,6 @@ pub fn get_kernel_version() -> Result<(i32, i32, i32)> { #[cfg(target_os = "android")] fn parse_kmi(version: &str) -> Result { - use regex::Regex; let re = Regex::new(r"(.* )?(\d+\.\d+)(\S+)?(android\d+)(.*)")?; let cap = re .captures(version) @@ -97,6 +96,63 @@ pub fn get_current_kmi() -> Result { bail!("Unsupported platform") } +fn parse_kmi_from_kernel(kernel: &PathBuf, workdir: &Path) -> Result { + use std::fs::{copy, File}; + use std::io::{BufReader, Read}; + let kernel_path = workdir.join("kernel"); + copy(kernel, &kernel_path).context("Failed to copy kernel")?; + + let file = File::open(&kernel_path).context("Failed to open kernel file")?; + let mut reader = BufReader::new(file); + let mut buffer = Vec::new(); + reader + .read_to_end(&mut buffer) + .context("Failed to read kernel file")?; + + let printable_strings: Vec<&str> = buffer + .split(|&b| b == 0) + .filter_map(|slice| std::str::from_utf8(slice).ok()) + .filter(|s| s.chars().all(|c| c.is_ascii_graphic() || c == ' ')) + .collect(); + + let re = + Regex::new(r"(?:.* )?(\d+\.\d+)(?:\S+)?(android\d+)").context("Failed to compile regex")?; + for s in printable_strings { + if let Some(caps) = re.captures(s) { + if let (Some(kernel_version), Some(android_version)) = (caps.get(1), caps.get(2)) { + let kmi = format!("{}-{}", android_version.as_str(), kernel_version.as_str()); + return Ok(kmi); + } + } + } + println!("- Failed to get KMI version"); + bail!("Try to choose LKM manually") +} + +fn parse_kmi_from_boot(magiskboot: &Path, image: &PathBuf, workdir: &Path) -> Result { + let image_path = workdir.join("image"); + + std::fs::copy(image, &image_path).context("Failed to copy image")?; + + let status = Command::new(magiskboot) + .current_dir(workdir) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .arg("unpack") + .arg(&image_path) + .status() + .context("Failed to execute magiskboot command")?; + + if !status.success() { + bail!( + "magiskboot unpack failed with status: {:?}", + status.code().unwrap() + ); + } + + parse_kmi_from_kernel(&image_path, workdir) +} + fn do_cpio_cmd(magiskboot: &Path, workdir: &Path, cmd: &str) -> Result<()> { let status = Command::new(magiskboot) .current_dir(workdir) @@ -155,7 +211,10 @@ pub fn restore( magiskboot_path: Option, flash: bool, ) -> Result<()> { - let tmpdir = tempdir::TempDir::new("KernelSU").context("create temp dir failed")?; + let tmpdir = tempfile::Builder::new() + .prefix("KernelSU") + .tempdir() + .context("create temp dir failed")?; let workdir = tmpdir.path(); let magiskboot = find_magiskboot(magiskboot_path, workdir)?; @@ -239,7 +298,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") )); @@ -310,13 +369,39 @@ fn do_patch( ); } - let tmpdir = tempdir::TempDir::new("KernelSU").context("create temp dir failed")?; + let tmpdir = tempfile::Builder::new() + .prefix("KernelSU") + .tempdir() + .context("create temp dir failed")?; let workdir = tmpdir.path(); + // extract magiskboot + let magiskboot = find_magiskboot(magiskboot_path, workdir)?; + let kmi = if let Some(kmi) = kmi { kmi } else { - get_current_kmi().context("Unknown KMI, please choose LKM manually")? + match get_current_kmi() { + Ok(value) => value, + Err(e) => { + println!("- {}", e); + if let Some(image_path) = &image { + println!( + "- Trying to auto detect KMI version for {}", + image_path.to_str().unwrap() + ); + parse_kmi_from_boot(&magiskboot, image_path, tmpdir.path())? + } else if let Some(kernel_path) = &kernel { + println!( + "- Trying to auto detect KMI version for {}", + kernel_path.to_str().unwrap() + ); + parse_kmi_from_kernel(kernel_path, tmpdir.path())? + } else { + "".to_string() + } + } + } }; let skip_init = kmi.starts_with("android12-"); @@ -329,9 +414,6 @@ fn do_patch( // try extract magiskboot/bootctl let _ = assets::ensure_binaries(false); - // extract magiskboot - let magiskboot = find_magiskboot(magiskboot_path, workdir)?; - if let Some(kernel) = kernel { std::fs::copy(kernel, workdir.join("kernel")).context("copy kernel from failed")?; } @@ -419,7 +501,7 @@ fn do_patch( let output_dir = out.unwrap_or(std::env::current_dir()?); let now = chrono::Utc::now(); let output_image = output_dir.join(format!( - "kernelsu_patched_{}.img", + "kernelsu_next_patched_{}.img", now.format("%Y%m%d_%H%M%S") )); @@ -558,7 +640,7 @@ fn find_boot_image( } else { if cfg!(not(target_os = "android")) { println!("- Current OS is not android, refusing auto bootimage/bootdevice detection"); - bail!("please specify a boot image"); + bail!("Please specify a boot image"); } let mut slot_suffix = utils::getprop("ro.boot.slot_suffix").unwrap_or_else(|| String::from("")); diff --git a/drivers/staging/kernelsu/userspace/ksud/src/cli.rs b/drivers/staging/kernelsu/userspace/ksud/src/cli.rs index cd96a360f346..8cdb4a5ba30b 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/cli.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/cli.rs @@ -1,12 +1,13 @@ use anyhow::{Ok, Result}; use clap::Parser; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; #[cfg(target_os = "android")] use android_logger::Config; #[cfg(target_os = "android")] use log::LevelFilter; +use crate::defs::KSUD_VERBOSE_LOG_FILE; use crate::{apk_sign, assets, debug, defs, init_event, ksucalls, module, utils}; /// KernelSU userspace cli @@ -15,6 +16,9 @@ use crate::{apk_sign, assets, debug, defs, init_event, ksucalls, module, utils}; struct Args { #[command(subcommand)] command: Commands, + + #[arg(short, long, default_value_t = cfg!(debug_assertions))] + verbose: bool, } #[derive(clap::Subcommand, Debug)] @@ -139,7 +143,7 @@ enum Debug { /// Set the manager app, kernel CONFIG_KSU_DEBUG should be enabled. SetManager { /// manager package name - #[arg(default_value_t = String::from("me.weishu.kernelsu"))] + #[arg(default_value_t = String::from("com.rifsxd.ksunext"))] apk: String, }, @@ -161,17 +165,6 @@ enum Debug { Mount, - /// Copy sparse file - Xcp { - /// source file - src: String, - /// destination file - dst: String, - /// punch hole - #[arg(short, long, default_value = "false")] - punch_hole: bool, - }, - /// For testing Test, } @@ -211,6 +204,12 @@ enum Module { id: String, }, + /// Restore module + Restore { + /// module id + id: String, + }, + /// enable module Enable { /// module id @@ -223,11 +222,14 @@ enum Module { id: String, }, + /// run action for module + Action { + // module id + id: String, + }, + /// list all modules List, - - /// Shrink module image size - Shrink, } #[derive(clap::Subcommand, Debug)] @@ -289,6 +291,10 @@ pub fn run() -> Result<()> { let cli = Args::parse(); + if !cli.verbose && !Path::new(KSUD_VERBOSE_LOG_FILE).exists() { + log::set_max_level(LevelFilter::Info); + } + log::info!("command: {:?}", cli.command); let result = match cli.command { @@ -304,10 +310,11 @@ pub fn run() -> Result<()> { match command { Module::Install { zip } => module::install_module(&zip), Module::Uninstall { id } => module::uninstall_module(&id), + Module::Restore { id } => module::restore_module(&id), Module::Enable { id } => module::enable_module(&id), Module::Disable { id } => module::disable_module(&id), + Module::Action { id } => module::run_action(&id), Module::List => module::list_modules(), - Module::Shrink => module::shrink_ksu_images(), } } Commands::Install { magiskboot } => utils::install(magiskboot), @@ -341,15 +348,7 @@ pub fn run() -> Result<()> { Ok(()) } Debug::Su { global_mnt } => crate::su::grant_root(global_mnt), - Debug::Mount => init_event::mount_modules_systemlessly(defs::MODULE_DIR), - Debug::Xcp { - src, - dst, - punch_hole, - } => { - utils::copy_sparse_file(src, dst, punch_hole)?; - Ok(()) - } + Debug::Mount => init_event::mount_modules_systemlessly(), Debug::Test => assets::ensure_binaries(false), }, diff --git a/drivers/staging/kernelsu/userspace/ksud/src/defs.rs b/drivers/staging/kernelsu/userspace/ksud/src/defs.rs index c4b9fc3f989b..5454def17cf7 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/defs.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/defs.rs @@ -10,7 +10,7 @@ pub const PROFILE_SELINUX_DIR: &str = concatcp!(PROFILE_DIR, "selinux/"); pub const PROFILE_TEMPLATE_DIR: &str = concatcp!(PROFILE_DIR, "templates/"); pub const KSURC_PATH: &str = concatcp!(WORKING_DIR, ".ksurc"); -pub const KSU_OVERLAY_SOURCE: &str = "KSU"; +pub const KSU_MOUNT_SOURCE: &str = "KSU"; pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud"); pub const MAGISKBOOT_PATH: &str = concatcp!(BINARY_DIR, "magiskboot"); @@ -18,24 +18,20 @@ pub const MAGISKBOOT_PATH: &str = concatcp!(BINARY_DIR, "magiskboot"); pub const DAEMON_LINK_PATH: &str = concatcp!(BINARY_DIR, "ksud"); pub const MODULE_DIR: &str = concatcp!(ADB_DIR, "modules/"); -pub const MODULE_IMG: &str = concatcp!(WORKING_DIR, "modules.img"); -pub const MODULE_UPDATE_IMG: &str = concatcp!(WORKING_DIR, "modules_update.img"); - -pub const MODULE_UPDATE_TMP_IMG: &str = concatcp!(WORKING_DIR, "update_tmp.img"); // warning: this directory should not change, or you need to change the code in module_installer.sh!!! -pub const MODULE_UPDATE_TMP_DIR: &str = concatcp!(ADB_DIR, "modules_update/"); +pub const MODULE_UPDATE_DIR: &str = concatcp!(ADB_DIR, "modules_update/"); -pub const SYSTEM_RW_DIR: &str = concatcp!(MODULE_DIR, ".rw/"); +pub const KSUD_VERBOSE_LOG_FILE: &str = concatcp!(ADB_DIR, "verbose"); pub const TEMP_DIR: &str = "/debug_ramdisk"; -pub const TEMP_DIR_LEGACY: &str = "/sbin"; - pub const MODULE_WEB_DIR: &str = "webroot"; +pub const MODULE_ACTION_SH: &str = "action.sh"; pub const DISABLE_FILE_NAME: &str = "disable"; pub const UPDATE_FILE_NAME: &str = "update"; pub const REMOVE_FILE_NAME: &str = "remove"; pub const SKIP_MOUNT_FILE_NAME: &str = "skip_mount"; +pub const MAGIC_MOUNT_WORK_DIR: &str = concatcp!(TEMP_DIR, "/workdir"); pub const VERSION_CODE: &str = include_str!(concat!(env!("OUT_DIR"), "/VERSION_CODE")); pub const VERSION_NAME: &str = include_str!(concat!(env!("OUT_DIR"), "/VERSION_NAME")); diff --git a/drivers/staging/kernelsu/userspace/ksud/src/init_event.rs b/drivers/staging/kernelsu/userspace/ksud/src/init_event.rs index 7107ff74225d..f5bb8b871050 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/init_event.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/init_event.rs @@ -1,100 +1,10 @@ -use anyhow::{bail, Context, Result}; +use crate::defs::{KSU_MOUNT_SOURCE, TEMP_DIR}; +use crate::module::{handle_updated_modules, prune_modules}; +use crate::{assets, defs, ksucalls, restorecon, utils}; +use anyhow::{Context, Result}; use log::{info, warn}; -use std::{collections::HashMap, path::Path}; - -use crate::module::prune_modules; -use crate::{ - assets, defs, ksucalls, mount, restorecon, - utils::{self, ensure_clean_dir}, -}; - -fn mount_partition(partition_name: &str, lowerdir: &Vec) -> Result<()> { - if lowerdir.is_empty() { - warn!("partition: {partition_name} lowerdir is empty"); - return Ok(()); - } - - let partition = format!("/{partition_name}"); - - // if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately - if Path::new(&partition).read_link().is_ok() { - warn!("partition: {partition} is a symlink"); - return Ok(()); - } - - let mut workdir = None; - let mut upperdir = None; - let system_rw_dir = Path::new(defs::SYSTEM_RW_DIR); - if system_rw_dir.exists() { - workdir = Some(system_rw_dir.join(partition_name).join("workdir")); - upperdir = Some(system_rw_dir.join(partition_name).join("upperdir")); - } - - mount::mount_overlay(&partition, lowerdir, workdir, upperdir) -} - -pub fn mount_modules_systemlessly(module_dir: &str) -> Result<()> { - // construct overlay mount params - let dir = std::fs::read_dir(module_dir); - let Ok(dir) = dir else { - bail!("open {} failed", defs::MODULE_DIR); - }; - - let mut system_lowerdir: Vec = Vec::new(); - - let partition = vec!["vendor", "product", "system_ext", "odm", "oem"]; - let mut partition_lowerdir: HashMap> = HashMap::new(); - for ele in &partition { - partition_lowerdir.insert((*ele).to_string(), Vec::new()); - } - - for entry in dir.flatten() { - let module = entry.path(); - if !module.is_dir() { - continue; - } - let disabled = module.join(defs::DISABLE_FILE_NAME).exists(); - if disabled { - info!("module: {} is disabled, ignore!", module.display()); - continue; - } - let skip_mount = module.join(defs::SKIP_MOUNT_FILE_NAME).exists(); - if skip_mount { - info!("module: {} skip_mount exist, skip!", module.display()); - continue; - } - - let module_system = Path::new(&module).join("system"); - if module_system.is_dir() { - system_lowerdir.push(format!("{}", module_system.display())); - } - - for part in &partition { - // if /partition is a mountpoint, we would move it to $MODPATH/$partition when install - // otherwise it must be a symlink and we don't need to overlay! - let part_path = Path::new(&module).join(part); - if part_path.is_dir() { - if let Some(v) = partition_lowerdir.get_mut(*part) { - v.push(format!("{}", part_path.display())); - } - } - } - } - - // mount /system first - if let Err(e) = mount_partition("system", &system_lowerdir) { - warn!("mount system failed: {:#}", e); - } - - // mount other partitions - for (k, v) in partition_lowerdir { - if let Err(e) = mount_partition(&k, &v) { - warn!("mount {k} failed: {:#}", e); - } - } - - Ok(()) -} +use rustix::fs::{mount, MountFlags}; +use std::path::Path; pub fn on_post_data_fs() -> Result<()> { ksucalls::report_post_fs_data(); @@ -111,11 +21,9 @@ pub fn on_post_data_fs() -> Result<()> { return Ok(()); } - let safe_mode = crate::utils::is_safe_mode(); + let safe_mode = utils::is_safe_mode(); if safe_mode { - // we should still mount modules.img to `/data/adb/modules` in safe mode - // becuase we may need to operate the module dir in safe mode warn!("safe mode, skip common post-fs-data.d scripts"); } else { // Then exec common post-fs-data scripts @@ -124,43 +32,8 @@ pub fn on_post_data_fs() -> Result<()> { } } - let module_update_img = defs::MODULE_UPDATE_IMG; - let module_img = defs::MODULE_IMG; - let module_dir = defs::MODULE_DIR; - let module_update_flag = Path::new(defs::WORKING_DIR).join(defs::UPDATE_FILE_NAME); - - // modules.img is the default image - let mut target_update_img = &module_img; - - // we should clean the module mount point if it exists - ensure_clean_dir(module_dir)?; - assets::ensure_binaries(true).with_context(|| "Failed to extract bin assets")?; - if Path::new(module_update_img).exists() { - if module_update_flag.exists() { - // if modules_update.img exists, and the the flag indicate this is an update - // this make sure that if the update failed, we will fallback to the old image - // if we boot succeed, we will rename the modules_update.img to modules.img #on_boot_complete - target_update_img = &module_update_img; - // And we should delete the flag immediately - std::fs::remove_file(module_update_flag)?; - } else { - // if modules_update.img exists, but the flag not exist, we should delete it - std::fs::remove_file(module_update_img)?; - } - } - - if !Path::new(target_update_img).exists() { - return Ok(()); - } - - // we should always mount the module.img to module dir - // becuase we may need to operate the module dir in safe mode - info!("mount module image: {target_update_img} to {module_dir}"); - mount::AutoMountExt4::try_new(target_update_img, module_dir, false) - .with_context(|| "mount module image failed".to_string())?; - // tell kernel that we've mount the module, so that it can do some optimization ksucalls::report_module_mounted(); @@ -177,6 +50,10 @@ pub fn on_post_data_fs() -> Result<()> { warn!("prune modules failed: {}", e); } + if let Err(e) = handle_updated_modules() { + warn!("handle updated modules failed: {}", e); + } + if let Err(e) = restorecon::restorecon() { warn!("restorecon failed: {}", e); } @@ -191,7 +68,7 @@ pub fn on_post_data_fs() -> Result<()> { } // mount temp dir - if let Err(e) = mount::mount_tmpfs(utils::get_tmp_path()) { + if let Err(e) = mount(KSU_MOUNT_SOURCE, TEMP_DIR, "tmpfs", MountFlags::empty(), "") { warn!("do temp dir mount failed: {}", e); } @@ -206,15 +83,23 @@ pub fn on_post_data_fs() -> Result<()> { warn!("load system.prop failed: {}", e); } - // mount module systemlessly by overlay - if let Err(e) = mount_modules_systemlessly(module_dir) { + // mount module systemlessly by magic mount + if let Err(e) = mount_modules_systemlessly() { warn!("do systemless mount failed: {}", e); } run_stage("post-mount", true); - std::env::set_current_dir("/").with_context(|| "failed to chdir to /")?; + Ok(()) +} +#[cfg(target_os = "android")] +pub fn mount_modules_systemlessly() -> Result<()> { + crate::magic_mount::magic_mount() +} + +#[cfg(not(target_os = "android"))] +pub fn mount_modules_systemlessly() -> Result<()> { Ok(()) } @@ -249,17 +134,6 @@ pub fn on_services() -> Result<()> { pub fn on_boot_completed() -> Result<()> { ksucalls::report_boot_complete(); info!("on_boot_completed triggered!"); - let module_update_img = Path::new(defs::MODULE_UPDATE_IMG); - let module_img = Path::new(defs::MODULE_IMG); - if module_update_img.exists() { - // this is a update and we successfully booted - if std::fs::rename(module_update_img, module_img).is_err() { - warn!("Failed to rename images, copy it now.",); - utils::copy_sparse_file(module_update_img, module_img, false) - .with_context(|| "Failed to copy images")?; - std::fs::remove_file(module_update_img).with_context(|| "Failed to remove image!")?; - } - } run_stage("boot-completed", false); diff --git a/drivers/staging/kernelsu/userspace/ksud/src/installer.sh b/drivers/staging/kernelsu/userspace/ksud/src/installer.sh index 40138ae3b15a..2ebdddc7eee8 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/installer.sh +++ b/drivers/staging/kernelsu/userspace/ksud/src/installer.sh @@ -85,7 +85,7 @@ setup_flashable() { $BOOTMODE && return if [ -z $OUTFD ] || readlink /proc/$$/fd/$OUTFD | grep -q /tmp; then # We will have to manually find out OUTFD - for FD in `ls /proc/$$/fd`; do + for FD in /proc/$$/fd/*; do if readlink /proc/$$/fd/$FD | grep -q pipe; then if ps | grep -v grep | grep -qE " 3 $FD |status_fd=$FD"; then OUTFD=$FD @@ -302,18 +302,16 @@ is_legacy_script() { } handle_partition() { - # if /system/vendor is a symlink, we need to move it out of $MODPATH/system, otherwise it will be overlayed - # if /system/vendor is a normal directory, it is ok to overlay it and we don't need to overlay it separately. - if [ ! -e $MODPATH/system/$1 ]; then + PARTITION="$1" + REQUIRE_SYMLINK="$2" + if [ ! -e "$MODPATH/system/$PARTITION" ]; then # no partition found return; fi - if [ -L "/system/$1" ] && [ "$(readlink -f /system/$1)" = "/$1" ]; then - ui_print "- Handle partition /$1" - # we create a symlink if module want to access $MODPATH/system/$1 - # but it doesn't always work(ie. write it in post-fs-data.sh would fail because it is readonly) - mv -f $MODPATH/system/$1 $MODPATH/$1 && ln -sf ../$1 $MODPATH/system/$1 + if [ "$REQUIRE_SYMLINK" = "false" ] || [ -L "/system/$PARTITION" ] && [ "$(readlink -f "/system/$PARTITION")" = "/$PARTITION" ]; then + ui_print "- Handle partition /$PARTITION" + ln -sf "./system/$PARTITION" "$MODPATH/$PARTITION" fi } @@ -391,22 +389,23 @@ install_module() { [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh fi + handle_partition vendor true + handle_partition system_ext true + handle_partition product true + handle_partition odm false + # Handle replace folders for TARGET in $REPLACE; do ui_print "- Replace target: $TARGET" - mark_replace $MODPATH$TARGET + mark_replace "$MODPATH$TARGET" done # Handle remove files for TARGET in $REMOVE; do ui_print "- Remove target: $TARGET" - mark_remove $MODPATH$TARGET + mark_remove "$MODPATH$TARGET" done - handle_partition vendor - handle_partition system_ext - handle_partition product - if $BOOTMODE; then mktouch $NVBASE/modules/$MODID/update rm -rf $NVBASE/modules/$MODID/remove 2>/dev/null diff --git a/drivers/staging/kernelsu/userspace/ksud/src/magic_mount.rs b/drivers/staging/kernelsu/userspace/ksud/src/magic_mount.rs new file mode 100644 index 000000000000..c6bd9f1869d5 --- /dev/null +++ b/drivers/staging/kernelsu/userspace/ksud/src/magic_mount.rs @@ -0,0 +1,434 @@ +use crate::defs::{ + DISABLE_FILE_NAME, KSU_MOUNT_SOURCE, MAGIC_MOUNT_WORK_DIR, MODULE_DIR, SKIP_MOUNT_FILE_NAME, +}; +use crate::magic_mount::NodeFileType::{Directory, RegularFile, Symlink, Whiteout}; +use crate::restorecon::{lgetfilecon, lsetfilecon}; +use crate::utils::ensure_dir_exists; +use anyhow::{bail, Context, Result}; +use extattr::lgetxattr; +use rustix::fs::{ + bind_mount, chmod, chown, mount, move_mount, unmount, Gid, MetadataExt, Mode, MountFlags, + MountPropagationFlags, Uid, UnmountFlags, +}; +use rustix::mount::mount_change; +use rustix::path::Arg; +use std::cmp::PartialEq; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::fs; +use std::fs::{create_dir, create_dir_all, read_dir, read_link, DirEntry, FileType}; +use std::os::unix::fs::{symlink, FileTypeExt}; +use std::path::{Path, PathBuf}; + +const REPLACE_DIR_XATTR: &str = "trusted.overlay.opaque"; + +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +enum NodeFileType { + RegularFile, + Directory, + Symlink, + Whiteout, +} + +impl NodeFileType { + fn from_file_type(file_type: FileType) -> Option { + if file_type.is_file() { + Some(RegularFile) + } else if file_type.is_dir() { + Some(Directory) + } else if file_type.is_symlink() { + Some(Symlink) + } else { + None + } + } +} + +#[derive(Debug)] +struct Node { + name: String, + file_type: NodeFileType, + children: HashMap, + // the module that owned this node + module_path: Option, + replace: bool, + skip: bool, +} + +impl Node { + fn collect_module_files>(&mut self, module_dir: T) -> Result { + let dir = module_dir.as_ref(); + let mut has_file = false; + for entry in dir.read_dir()?.flatten() { + let name = entry.file_name().to_string_lossy().to_string(); + + let node = match self.children.entry(name.clone()) { + Entry::Occupied(o) => Some(o.into_mut()), + Entry::Vacant(v) => Self::new_module(&name, &entry).map(|it| v.insert(it)), + }; + + if let Some(node) = node { + has_file |= if node.file_type == Directory { + node.collect_module_files(dir.join(&node.name))? || node.replace + } else { + true + } + } + } + + Ok(has_file) + } + + fn new_root(name: T) -> Self { + Node { + name: name.to_string(), + file_type: Directory, + children: Default::default(), + module_path: None, + replace: false, + skip: false, + } + } + + fn new_module(name: T, entry: &DirEntry) -> Option { + if let Ok(metadata) = entry.metadata() { + let path = entry.path(); + let file_type = if metadata.file_type().is_char_device() && metadata.rdev() == 0 { + Some(Whiteout) + } else { + NodeFileType::from_file_type(metadata.file_type()) + }; + if let Some(file_type) = file_type { + let mut replace = false; + if file_type == Directory { + if let Ok(v) = lgetxattr(&path, REPLACE_DIR_XATTR) { + if String::from_utf8_lossy(&v) == "y" { + replace = true; + } + } + } + return Some(Node { + name: name.to_string(), + file_type, + children: Default::default(), + module_path: Some(path), + replace, + skip: false, + }); + } + } + + None + } +} + +fn collect_module_files() -> Result> { + let mut root = Node::new_root(""); + let mut system = Node::new_root("system"); + let module_root = Path::new(MODULE_DIR); + let mut has_file = false; + for entry in module_root.read_dir()?.flatten() { + if !entry.file_type()?.is_dir() { + continue; + } + + if entry.path().join(DISABLE_FILE_NAME).exists() + || entry.path().join(SKIP_MOUNT_FILE_NAME).exists() + { + continue; + } + + let mod_system = entry.path().join("system"); + if !mod_system.is_dir() { + continue; + } + + log::debug!("collecting {}", entry.path().display()); + + has_file |= system.collect_module_files(&mod_system)?; + } + + if has_file { + for (partition, require_symlink) in [ + ("vendor", true), + ("system_ext", true), + ("product", true), + ("odm", false), + ] { + let path_of_root = Path::new("/").join(partition); + let path_of_system = Path::new("/system").join(partition); + if path_of_root.is_dir() && (!require_symlink || path_of_system.is_symlink()) { + let name = partition.to_string(); + if let Some(node) = system.children.remove(&name) { + root.children.insert(name, node); + } + } + } + root.children.insert("system".to_string(), system); + Ok(Some(root)) + } else { + Ok(None) + } +} + +fn clone_symlink, Dst: AsRef>(src: Src, dst: Dst) -> Result<()> { + let src_symlink = read_link(src.as_ref())?; + symlink(&src_symlink, dst.as_ref())?; + lsetfilecon(dst.as_ref(), lgetfilecon(src.as_ref())?.as_str())?; + log::debug!( + "clone symlink {} -> {}({})", + dst.as_ref().display(), + dst.as_ref().display(), + src_symlink.display() + ); + Ok(()) +} + +fn mount_mirror, WP: AsRef>( + path: P, + work_dir_path: WP, + entry: &DirEntry, +) -> Result<()> { + let path = path.as_ref().join(entry.file_name()); + let work_dir_path = work_dir_path.as_ref().join(entry.file_name()); + let file_type = entry.file_type()?; + + if file_type.is_file() { + log::debug!( + "mount mirror file {} -> {}", + path.display(), + work_dir_path.display() + ); + fs::File::create(&work_dir_path)?; + bind_mount(&path, &work_dir_path)?; + } else if file_type.is_dir() { + log::debug!( + "mount mirror dir {} -> {}", + path.display(), + work_dir_path.display() + ); + create_dir(&work_dir_path)?; + let metadata = entry.metadata()?; + chmod(&work_dir_path, Mode::from_raw_mode(metadata.mode()))?; + unsafe { + chown( + &work_dir_path, + Some(Uid::from_raw(metadata.uid())), + Some(Gid::from_raw(metadata.gid())), + )?; + } + lsetfilecon(&work_dir_path, lgetfilecon(&path)?.as_str())?; + for entry in read_dir(&path)?.flatten() { + mount_mirror(&path, &work_dir_path, &entry)?; + } + } else if file_type.is_symlink() { + log::debug!( + "create mirror symlink {} -> {}", + path.display(), + work_dir_path.display() + ); + clone_symlink(&path, &work_dir_path)?; + } + + Ok(()) +} + +fn do_magic_mount, WP: AsRef>( + path: P, + work_dir_path: WP, + current: Node, + has_tmpfs: bool, +) -> Result<()> { + let mut current = current; + let path = path.as_ref().join(¤t.name); + let work_dir_path = work_dir_path.as_ref().join(¤t.name); + match current.file_type { + RegularFile => { + let target_path = if has_tmpfs { + fs::File::create(&work_dir_path)?; + &work_dir_path + } else { + &path + }; + if let Some(module_path) = ¤t.module_path { + log::debug!( + "mount module file {} -> {}", + module_path.display(), + work_dir_path.display() + ); + bind_mount(module_path, target_path)?; + } else { + bail!("cannot mount root file {}!", path.display()); + } + } + Symlink => { + if let Some(module_path) = ¤t.module_path { + log::debug!( + "create module symlink {} -> {}", + module_path.display(), + work_dir_path.display() + ); + clone_symlink(module_path, &work_dir_path)?; + } else { + bail!("cannot mount root symlink {}!", path.display()); + } + } + Directory => { + let mut create_tmpfs = !has_tmpfs && current.replace && current.module_path.is_some(); + if !has_tmpfs && !create_tmpfs { + for it in &mut current.children { + let (name, node) = it; + let real_path = path.join(name); + let need = match node.file_type { + Symlink => true, + Whiteout => real_path.exists(), + _ => { + if let Ok(metadata) = real_path.metadata() { + let file_type = NodeFileType::from_file_type(metadata.file_type()) + .unwrap_or(Whiteout); + file_type != node.file_type || file_type == Symlink + } else { + // real path not exists + true + } + } + }; + if need { + if current.module_path.is_none() { + log::error!( + "cannot create tmpfs on {}, ignore: {name}", + path.display() + ); + node.skip = true; + continue; + } + create_tmpfs = true; + break; + } + } + } + + let has_tmpfs = has_tmpfs || create_tmpfs; + + if has_tmpfs { + log::debug!( + "creating tmpfs skeleton for {} at {}", + path.display(), + work_dir_path.display() + ); + create_dir_all(&work_dir_path)?; + let (metadata, path) = if path.exists() { + (path.metadata()?, &path) + } else if let Some(module_path) = ¤t.module_path { + (module_path.metadata()?, module_path) + } else { + bail!("cannot mount root dir {}!", path.display()); + }; + chmod(&work_dir_path, Mode::from_raw_mode(metadata.mode()))?; + unsafe { + chown( + &work_dir_path, + Some(Uid::from_raw(metadata.uid())), + Some(Gid::from_raw(metadata.gid())), + )?; + } + lsetfilecon(&work_dir_path, lgetfilecon(path)?.as_str())?; + } + + if create_tmpfs { + log::debug!( + "creating tmpfs for {} at {}", + path.display(), + work_dir_path.display() + ); + bind_mount(&work_dir_path, &work_dir_path).context("bind self")?; + } + + if path.exists() && !current.replace { + for entry in path.read_dir()?.flatten() { + let name = entry.file_name().to_string_lossy().to_string(); + let result = if let Some(node) = current.children.remove(&name) { + if node.skip { + continue; + } + do_magic_mount(&path, &work_dir_path, node, has_tmpfs) + .with_context(|| format!("magic mount {}/{name}", path.display())) + } else if has_tmpfs { + mount_mirror(&path, &work_dir_path, &entry) + .with_context(|| format!("mount mirror {}/{name}", path.display())) + } else { + Ok(()) + }; + + if let Err(e) = result { + if has_tmpfs { + return Err(e); + } else { + log::error!("mount child {}/{name} failed: {}", path.display(), e); + } + } + } + } + + if current.replace { + if current.module_path.is_none() { + bail!( + "dir {} is declared as replaced but it is root!", + path.display() + ); + } else { + log::debug!("dir {} is replaced", path.display()); + } + } + + for (name, node) in current.children.into_iter() { + if node.skip { + continue; + } + if let Err(e) = do_magic_mount(&path, &work_dir_path, node, has_tmpfs) + .with_context(|| format!("magic mount {}/{name}", path.display())) + { + if has_tmpfs { + return Err(e); + } else { + log::error!("mount child {}/{name} failed: {}", path.display(), e); + } + } + } + + if create_tmpfs { + log::debug!( + "moving tmpfs {} -> {}", + work_dir_path.display(), + path.display() + ); + move_mount(&work_dir_path, &path).context("move self")?; + mount_change(&path, MountPropagationFlags::PRIVATE).context("make self private")?; + } + } + Whiteout => { + log::debug!("file {} is removed", path.display()); + } + } + + Ok(()) +} + +pub fn magic_mount() -> Result<()> { + if let Some(root) = collect_module_files()? { + log::debug!("collected: {:#?}", root); + let tmp_dir = PathBuf::from(MAGIC_MOUNT_WORK_DIR); + ensure_dir_exists(&tmp_dir)?; + mount(KSU_MOUNT_SOURCE, &tmp_dir, "tmpfs", MountFlags::empty(), "").context("mount tmp")?; + mount_change(&tmp_dir, MountPropagationFlags::PRIVATE).context("make tmp private")?; + let result = do_magic_mount("/", &tmp_dir, root, false); + if let Err(e) = unmount(&tmp_dir, UnmountFlags::DETACH) { + log::error!("failed to unmount tmp {}", e); + } + fs::remove_dir(tmp_dir).ok(); + result + } else { + log::info!("no modules to mount, skipping!"); + Ok(()) + } +} diff --git a/drivers/staging/kernelsu/userspace/ksud/src/main.rs b/drivers/staging/kernelsu/userspace/ksud/src/main.rs index 3b51720557c1..a91fc0cb5006 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/main.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/main.rs @@ -6,8 +6,9 @@ mod debug; mod defs; mod init_event; mod ksucalls; +#[cfg(target_os = "android")] +mod magic_mount; mod module; -mod mount; mod profile; mod restorecon; mod sepolicy; diff --git a/drivers/staging/kernelsu/userspace/ksud/src/module.rs b/drivers/staging/kernelsu/userspace/ksud/src/module.rs index ac3ff213b62f..8c5c8c87c4d9 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/module.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/module.rs @@ -1,9 +1,9 @@ #[allow(clippy::wildcard_imports)] use crate::utils::*; use crate::{ - assets, defs, ksucalls, mount, + assets, defs, ksucalls, restorecon::{restore_syscon, setsyscon}, - sepolicy, utils, + sepolicy, }; use anyhow::{anyhow, bail, ensure, Context, Result}; @@ -12,20 +12,21 @@ use is_executable::is_executable; use java_properties::PropertiesIter; use log::{info, warn}; -use std::fs::OpenOptions; +use std::fs::{copy, rename}; use std::{ collections::HashMap, env::var as env_var, fs::{remove_dir_all, remove_file, set_permissions, File, Permissions}, io::Cursor, path::{Path, PathBuf}, - process::{Command, Stdio}, + process::Command, str::FromStr, }; use zip_extensions::zip_extract_file_to_memory; +use crate::defs::{MODULE_DIR, MODULE_UPDATE_DIR, UPDATE_FILE_NAME}; #[cfg(unix)] -use std::os::unix::{fs::MetadataExt, prelude::PermissionsExt, process::CommandExt}; +use std::os::unix::{prelude::PermissionsExt, process::CommandExt}; const INSTALLER_CONTENT: &str = include_str!("./installer.sh"); const INSTALL_MODULE_SCRIPT: &str = concatcp!( @@ -75,24 +76,34 @@ fn ensure_boot_completed() -> Result<()> { Ok(()) } -fn mark_update() -> Result<()> { - ensure_file_exists(concatcp!(defs::WORKING_DIR, defs::UPDATE_FILE_NAME)) -} - -fn mark_module_state(module: &str, flag_file: &str, create_or_delete: bool) -> Result<()> { - let module_state_file = Path::new(defs::MODULE_DIR).join(module).join(flag_file); - if create_or_delete { +fn mark_module_state(module: &str, flag_file: &str, create: bool) -> Result<()> { + let module_state_file = Path::new(MODULE_DIR).join(module).join(flag_file); + if create { ensure_file_exists(module_state_file) } else { if module_state_file.exists() { - std::fs::remove_file(module_state_file)?; + remove_file(module_state_file)?; } Ok(()) } } -fn foreach_module(active_only: bool, mut f: impl FnMut(&Path) -> Result<()>) -> Result<()> { - let modules_dir = Path::new(defs::MODULE_DIR); +#[derive(PartialEq, Eq)] +enum ModuleType { + All, + Active, + Updated, +} + +fn foreach_module(module_type: ModuleType, mut f: impl FnMut(&Path) -> Result<()>) -> Result<()> { + let modules_dir = Path::new(match module_type { + ModuleType::Updated => MODULE_UPDATE_DIR, + _ => defs::MODULE_DIR, + }); + if !modules_dir.is_dir() { + warn!("{} is not a directory, skip", modules_dir.display()); + return Ok(()); + } let dir = std::fs::read_dir(modules_dir)?; for entry in dir.flatten() { let path = entry.path(); @@ -101,11 +112,11 @@ fn foreach_module(active_only: bool, mut f: impl FnMut(&Path) -> Result<()>) -> continue; } - if active_only && path.join(defs::DISABLE_FILE_NAME).exists() { + if module_type == ModuleType::Active && path.join(defs::DISABLE_FILE_NAME).exists() { info!("{} is disabled, skip", path.display()); continue; } - if active_only && path.join(defs::REMOVE_FILE_NAME).exists() { + if module_type == ModuleType::Active && path.join(defs::REMOVE_FILE_NAME).exists() { warn!("{} is removed, skip", path.display()); continue; } @@ -117,27 +128,7 @@ fn foreach_module(active_only: bool, mut f: impl FnMut(&Path) -> Result<()>) -> } fn foreach_active_module(f: impl FnMut(&Path) -> Result<()>) -> Result<()> { - foreach_module(true, f) -} - -fn check_image(img: &str) -> Result<()> { - let result = Command::new("e2fsck") - .args(["-yf", img]) - .stdout(Stdio::piped()) - .status() - .with_context(|| format!("Failed to exec e2fsck {img}"))?; - let code = result.code(); - // 0 or 1 is ok - // 0: no error - // 1: file system errors corrected - // https://man7.org/linux/man-pages/man8/e2fsck.8.html - // ensure!( - // code == Some(0) || code == Some(1), - // "Failed to check image, e2fsck exit code: {}", - // code.unwrap_or(-1) - // ); - info!("e2fsck exit code: {}", code.unwrap_or(-1)); - Ok(()) + foreach_module(ModuleType::Active, f) } pub fn load_sepolicy_rule() -> Result<()> { @@ -256,351 +247,166 @@ pub fn load_system_prop() -> Result<()> { } pub fn prune_modules() -> Result<()> { - foreach_module(false, |module| { - remove_file(module.join(defs::UPDATE_FILE_NAME)).ok(); + foreach_module(ModuleType::All, |module| { + if module.join(defs::REMOVE_FILE_NAME).exists() { + info!("remove module: {}", module.display()); - if !module.join(defs::REMOVE_FILE_NAME).exists() { - return Ok(()); - } - - info!("remove module: {}", module.display()); - - let uninstaller = module.join("uninstall.sh"); - if uninstaller.exists() { - if let Err(e) = exec_script(uninstaller, true) { - warn!("Failed to exec uninstaller: {}", e); + let uninstaller = module.join("uninstall.sh"); + if uninstaller.exists() { + if let Err(e) = exec_script(uninstaller, true) { + warn!("Failed to exec uninstaller: {}", e); + } } - } - if let Err(e) = remove_dir_all(module) { - warn!("Failed to remove {}: {}", module.display(), e); + if let Err(e) = remove_dir_all(module) { + warn!("Failed to remove {}: {}", module.display(), e); + } + } else { + remove_file(module.join(defs::UPDATE_FILE_NAME)).ok(); } - Ok(()) })?; Ok(()) } -fn create_module_image(image: &str, image_size: u64, journal_size: u64) -> Result<()> { - File::create(image) - .context("Failed to create ext4 image file")? - .set_len(image_size) - .context("Failed to truncate ext4 image")?; +pub fn handle_updated_modules() -> Result<()> { + let modules_root = Path::new(MODULE_DIR); + foreach_module(ModuleType::Updated, |module| { + if !module.is_dir() { + return Ok(()); + } - // format the img to ext4 filesystem - let result = Command::new("mkfs.ext4") - .arg("-J") - .arg(format!("size={journal_size}")) - .arg(image) - .stdout(Stdio::piped()) - .output()?; - ensure!( - result.status.success(), - "Failed to format ext4 image: {}", - String::from_utf8(result.stderr).unwrap() - ); - check_image(image)?; - Ok(()) -} -fn _install_module(zip: &str) -> Result<()> { - ensure_boot_completed()?; - - // print banner - println!(include_str!("banner")); - - assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?; - - // first check if workding dir is usable - ensure_dir_exists(defs::WORKING_DIR).with_context(|| "Failed to create working dir")?; - ensure_dir_exists(defs::BINARY_DIR).with_context(|| "Failed to create bin dir")?; - - // read the module_id from zip, if faild if will return early. - let mut buffer: Vec = Vec::new(); - let entry_path = PathBuf::from_str("module.prop")?; - let zip_path = PathBuf::from_str(zip)?; - let zip_path = zip_path.canonicalize()?; - zip_extract_file_to_memory(&zip_path, &entry_path, &mut buffer)?; - - let mut module_prop = HashMap::new(); - PropertiesIter::new_with_encoding(Cursor::new(buffer), encoding_rs::UTF_8).read_into( - |k, v| { - module_prop.insert(k, v); - }, - )?; - info!("module prop: {:?}", module_prop); - - let Some(module_id) = module_prop.get("id") else { - bail!("module id not found in module.prop!"); - }; - let module_id = module_id.trim(); - - let modules_img = Path::new(defs::MODULE_IMG); - let modules_update_img = Path::new(defs::MODULE_UPDATE_IMG); - let module_update_tmp_dir = defs::MODULE_UPDATE_TMP_DIR; - - let modules_img_exist = modules_img.exists(); - let modules_update_img_exist = modules_update_img.exists(); - - // prepare the tmp module img - let tmp_module_img = defs::MODULE_UPDATE_TMP_IMG; - let tmp_module_path = Path::new(tmp_module_img); - if tmp_module_path.exists() { - std::fs::remove_file(tmp_module_path)?; - } - - let zip_uncompressed_size = get_zip_uncompressed_size(zip)?; - - info!( - "zip uncompressed size: {}", - humansize::format_size(zip_uncompressed_size, humansize::DECIMAL) - ); - - println!("- Preparing image"); - println!( - "- Module size: {}", - humansize::format_size(zip_uncompressed_size, humansize::DECIMAL) - ); - - let sparse_image_size = 1 << 40; // 1T - let journal_size = 8; // 8M - if !modules_img_exist && !modules_update_img_exist { - // if no modules and modules_update, it is brand new installation, we should create a new img - // create a tmp module img and mount it to modules_update - info!("Creating brand new module image"); - create_module_image(tmp_module_img, sparse_image_size, journal_size)?; - } else if modules_update_img_exist { - // modules_update.img exists, we should use it as tmp img - info!("Using existing modules_update.img as tmp image"); - utils::copy_sparse_file(modules_update_img, tmp_module_img, true).with_context(|| { - format!( - "Failed to copy {} to {}", - modules_update_img.display(), - tmp_module_img - ) - })?; - } else { - // modules.img exists, we should use it as tmp img - info!("Using existing modules.img as tmp image"); - - #[cfg(unix)] - let blksize = std::fs::metadata(defs::MODULE_DIR)?.blksize(); - #[cfg(not(unix))] - let blksize = 0; - // legacy image, it's block size is 1024 with unlimited journal size - if blksize == 1024 { - println!("- Legacy image, migrating to new format, please be patient..."); - create_module_image(tmp_module_img, sparse_image_size, journal_size)?; - let _dontdrop = - mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true) - .with_context(|| format!("Failed to mount {tmp_module_img}"))?; - utils::copy_module_files(defs::MODULE_DIR, module_update_tmp_dir) - .with_context(|| "Failed to migrate module files".to_string())?; - } else { - utils::copy_sparse_file(modules_img, tmp_module_img, true) - .with_context(|| "Failed to copy module image".to_string())?; - - if std::fs::metadata(tmp_module_img)?.len() < sparse_image_size { - // truncate the file to new size - OpenOptions::new() - .write(true) - .open(tmp_module_img) - .context("Failed to open ext4 image")? - .set_len(sparse_image_size) - .context("Failed to truncate ext4 image")?; - - // resize the image to new size - check_image(tmp_module_img)?; - Command::new("resize2fs") - .arg(tmp_module_img) - .stdout(Stdio::piped()) - .status()?; + if let Some(name) = module.file_name() { + let old_dir = modules_root.join(name); + if old_dir.exists() { + if let Err(e) = remove_dir_all(&old_dir) { + log::error!("Failed to remove old {}: {}", old_dir.display(), e); + } + } + if let Err(e) = rename(module, &old_dir) { + log::error!("Failed to move new module {}: {}", module.display(), e); } } - } - - // ensure modules_update exists - ensure_dir_exists(module_update_tmp_dir)?; - - // mount the modules_update.img to mountpoint - println!("- Mounting image"); - - let _dontdrop = mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true)?; - - info!("mounted {} to {}", tmp_module_img, module_update_tmp_dir); - - setsyscon(module_update_tmp_dir)?; - - let module_dir = format!("{module_update_tmp_dir}/{module_id}"); - ensure_clean_dir(&module_dir)?; - info!("module dir: {}", module_dir); - - // unzip the image and move it to modules_update/ dir - let file = File::open(zip)?; - let mut archive = zip::ZipArchive::new(file)?; - archive.extract(&module_dir)?; - - // set permission and selinux context for $MOD/system - let module_system_dir = PathBuf::from(module_dir).join("system"); - if module_system_dir.exists() { - #[cfg(unix)] - set_permissions(&module_system_dir, Permissions::from_mode(0o755))?; - restore_syscon(&module_system_dir)?; - } - - exec_install_script(zip)?; - - info!("rename {tmp_module_img} to {}", defs::MODULE_UPDATE_IMG); - // all done, rename the tmp image to modules_update.img - if std::fs::rename(tmp_module_img, defs::MODULE_UPDATE_IMG).is_err() { - warn!("Rename image failed, try copy it."); - utils::copy_sparse_file(tmp_module_img, defs::MODULE_UPDATE_IMG, true) - .with_context(|| "Failed to copy image.".to_string())?; - let _ = std::fs::remove_file(tmp_module_img); - } - - mark_update()?; - - info!("Module install successfully!"); - + Ok(()) + })?; Ok(()) } pub fn install_module(zip: &str) -> Result<()> { - let result = _install_module(zip); + fn inner(zip: &str) -> Result<()> { + ensure_boot_completed()?; + + // print banner + println!(include_str!("banner")); + + assets::ensure_binaries(false).with_context(|| "Failed to extract assets")?; + + // first check if working dir is usable + ensure_dir_exists(defs::WORKING_DIR).with_context(|| "Failed to create working dir")?; + ensure_dir_exists(defs::BINARY_DIR).with_context(|| "Failed to create bin dir")?; + + // read the module_id from zip, if failed it will return early. + let mut buffer: Vec = Vec::new(); + let entry_path = PathBuf::from_str("module.prop")?; + let zip_path = PathBuf::from_str(zip)?; + let zip_path = zip_path.canonicalize()?; + zip_extract_file_to_memory(&zip_path, &entry_path, &mut buffer)?; + + let mut module_prop = HashMap::new(); + PropertiesIter::new_with_encoding(Cursor::new(buffer), encoding_rs::UTF_8).read_into( + |k, v| { + module_prop.insert(k, v); + }, + )?; + info!("module prop: {:?}", module_prop); + + let Some(module_id) = module_prop.get("id") else { + bail!("module id not found in module.prop!"); + }; + let module_id = module_id.trim(); + + let zip_uncompressed_size = get_zip_uncompressed_size(zip)?; + + info!( + "zip uncompressed size: {}", + humansize::format_size(zip_uncompressed_size, humansize::DECIMAL) + ); + + println!("- Preparing Zip"); + println!( + "- Module size: {}", + humansize::format_size(zip_uncompressed_size, humansize::DECIMAL) + ); + + // ensure modules_update exists + ensure_dir_exists(MODULE_UPDATE_DIR)?; + setsyscon(MODULE_UPDATE_DIR)?; + + let update_module_dir = Path::new(MODULE_UPDATE_DIR).join(module_id); + ensure_clean_dir(&update_module_dir)?; + info!("module dir: {}", update_module_dir.display()); + + let do_install = || -> Result<()> { + // unzip the image and move it to modules_update/ dir + let file = File::open(zip)?; + let mut archive = zip::ZipArchive::new(file)?; + archive.extract(&update_module_dir)?; + + // set permission and selinux context for $MOD/system + let module_system_dir = update_module_dir.join("system"); + if module_system_dir.exists() { + #[cfg(unix)] + set_permissions(&module_system_dir, Permissions::from_mode(0o755))?; + restore_syscon(&module_system_dir)?; + } + + exec_install_script(zip)?; + + let module_dir = Path::new(MODULE_DIR).join(module_id); + ensure_dir_exists(&module_dir)?; + copy( + update_module_dir.join("module.prop"), + module_dir.join("module.prop"), + )?; + ensure_file_exists(module_dir.join(UPDATE_FILE_NAME))?; + + info!("Module install successfully!"); + + Ok(()) + }; + let result = do_install(); + if result.is_err() { + remove_dir_all(&update_module_dir).ok(); + } + result + } + let result = inner(zip); if let Err(ref e) = result { - // error happened, do some cleanup! - let _ = std::fs::remove_file(defs::MODULE_UPDATE_TMP_IMG); - let _ = mount::umount_dir(defs::MODULE_UPDATE_TMP_DIR); println!("- Error: {e}"); } result } -fn update_module(update_dir: &str, id: &str, func: F) -> Result<()> -where - F: Fn(&str, &str) -> Result<()>, -{ - ensure_boot_completed()?; - - let modules_img = Path::new(defs::MODULE_IMG); - let modules_update_img = Path::new(defs::MODULE_UPDATE_IMG); - let modules_update_tmp_img = Path::new(defs::MODULE_UPDATE_TMP_IMG); - if !modules_update_img.exists() && !modules_img.exists() { - bail!("Please install module first!"); - } else if modules_update_img.exists() { - info!( - "copy {} to {}", - modules_update_img.display(), - modules_update_tmp_img.display() - ); - utils::copy_sparse_file(modules_update_img, modules_update_tmp_img, true)?; - } else { - info!( - "copy {} to {}", - modules_img.display(), - modules_update_tmp_img.display() - ); - utils::copy_sparse_file(modules_img, modules_update_tmp_img, true)?; - } - - // ensure modules_update dir exist - ensure_clean_dir(update_dir)?; - - // mount the modules_update img - let _dontdrop = mount::AutoMountExt4::try_new(defs::MODULE_UPDATE_TMP_IMG, update_dir, true)?; - - // call the operation func - let result = func(id, update_dir); - - if let Err(e) = std::fs::rename(modules_update_tmp_img, defs::MODULE_UPDATE_IMG) { - warn!("Rename image failed: {e}, try copy it."); - utils::copy_sparse_file(modules_update_tmp_img, defs::MODULE_UPDATE_IMG, true) - .with_context(|| "Failed to copy image.".to_string())?; - let _ = std::fs::remove_file(modules_update_tmp_img); - } - - mark_update()?; - - result -} - pub fn uninstall_module(id: &str) -> Result<()> { - update_module(defs::MODULE_UPDATE_TMP_DIR, id, |mid, update_dir| { - let dir = Path::new(update_dir); - ensure!(dir.exists(), "No module installed"); - - // iterate the modules_update dir, find the module to be removed - let dir = std::fs::read_dir(dir)?; - for entry in dir.flatten() { - let path = entry.path(); - let module_prop = path.join("module.prop"); - if !module_prop.exists() { - continue; - } - let content = std::fs::read(module_prop)?; - let mut module_id: String = String::new(); - PropertiesIter::new_with_encoding(Cursor::new(content), encoding_rs::UTF_8).read_into( - |k, v| { - if k.eq("id") { - module_id = v; - } - }, - )?; - if module_id.eq(mid) { - let remove_file = path.join(defs::REMOVE_FILE_NAME); - File::create(remove_file).with_context(|| "Failed to create remove file.")?; - break; - } - } - - // santity check - let target_module_path = format!("{update_dir}/{mid}"); - let target_module = Path::new(&target_module_path); - if target_module.exists() { - let remove_file = target_module.join(defs::REMOVE_FILE_NAME); - if !remove_file.exists() { - File::create(remove_file).with_context(|| "Failed to create remove file.")?; - } - } - - let _ = mark_module_state(id, defs::REMOVE_FILE_NAME, true); - - Ok(()) - }) + mark_module_state(id, defs::REMOVE_FILE_NAME, true) } -fn _enable_module(module_dir: &str, mid: &str, enable: bool) -> Result<()> { - let src_module_path = format!("{module_dir}/{mid}"); - let src_module = Path::new(&src_module_path); - ensure!(src_module.exists(), "module: {} not found!", mid); +pub fn restore_module(id: &str) -> Result<()> { + mark_module_state(id, defs::REMOVE_FILE_NAME, false) +} - let disable_path = src_module.join(defs::DISABLE_FILE_NAME); - if enable { - if disable_path.exists() { - std::fs::remove_file(&disable_path).with_context(|| { - format!("Failed to remove disable file: {}", &disable_path.display()) - })?; - } - } else { - ensure_file_exists(disable_path)?; - } - - let _ = mark_module_state(mid, defs::DISABLE_FILE_NAME, !enable); - - Ok(()) +pub fn run_action(id: &str) -> Result<()> { + let action_script_path = format!("/data/adb/modules/{}/action.sh", id); + exec_script(&action_script_path, true) } pub fn enable_module(id: &str) -> Result<()> { - update_module(defs::MODULE_UPDATE_TMP_DIR, id, |mid, update_dir| { - _enable_module(update_dir, mid, true) - }) + mark_module_state(id, defs::DISABLE_FILE_NAME, false) } pub fn disable_module(id: &str) -> Result<()> { - update_module(defs::MODULE_UPDATE_TMP_DIR, id, |mid, update_dir| { - _enable_module(update_dir, mid, false) - }) + mark_module_state(id, defs::DISABLE_FILE_NAME, true) } pub fn disable_all_modules() -> Result<()> { @@ -612,8 +418,7 @@ pub fn uninstall_all_modules() -> Result<()> { } fn mark_all_modules(flag_file: &str) -> Result<()> { - // we assume the module dir is already mounted - let dir = std::fs::read_dir(defs::MODULE_DIR)?; + let dir = std::fs::read_dir(MODULE_DIR)?; for entry in dir.flatten() { let path = entry.path(); let flag = path.join(flag_file); @@ -668,11 +473,13 @@ fn _list_modules(path: &str) -> Vec> { let update = path.join(defs::UPDATE_FILE_NAME).exists(); let remove = path.join(defs::REMOVE_FILE_NAME).exists(); let web = path.join(defs::MODULE_WEB_DIR).exists(); + let action = path.join(defs::MODULE_ACTION_SH).exists(); module_prop_map.insert("enabled".to_owned(), enabled.to_string()); module_prop_map.insert("update".to_owned(), update.to_string()); module_prop_map.insert("remove".to_owned(), remove.to_string()); module_prop_map.insert("web".to_owned(), web.to_string()); + module_prop_map.insert("action".to_owned(), action.to_string()); if result.is_err() { warn!("Failed to parse module.prop: {}", module_prop.display()); @@ -689,21 +496,3 @@ pub fn list_modules() -> Result<()> { println!("{}", serde_json::to_string_pretty(&modules)?); Ok(()) } - -pub fn shrink_image(img: &str) -> Result<()> { - check_image(img)?; - Command::new("resize2fs") - .arg("-M") - .arg(img) - .stdout(Stdio::piped()) - .status()?; - Ok(()) -} - -pub fn shrink_ksu_images() -> Result<()> { - shrink_image(defs::MODULE_IMG)?; - if Path::new(defs::MODULE_UPDATE_IMG).exists() { - shrink_image(defs::MODULE_UPDATE_IMG)?; - } - Ok(()) -} diff --git a/drivers/staging/kernelsu/userspace/ksud/src/mount.rs b/drivers/staging/kernelsu/userspace/ksud/src/mount.rs deleted file mode 100644 index 11be898bbeb7..000000000000 --- a/drivers/staging/kernelsu/userspace/ksud/src/mount.rs +++ /dev/null @@ -1,327 +0,0 @@ -use anyhow::{anyhow, bail, Ok, Result}; - -#[cfg(any(target_os = "linux", target_os = "android"))] -use anyhow::Context; -#[cfg(any(target_os = "linux", target_os = "android"))] -use rustix::{fd::AsFd, fs::CWD, mount::*}; - -use crate::defs::KSU_OVERLAY_SOURCE; -use log::{info, warn}; -#[cfg(any(target_os = "linux", target_os = "android"))] -use procfs::process::Process; -use std::path::Path; -use std::path::PathBuf; - -pub struct AutoMountExt4 { - target: String, - auto_umount: bool, -} - -impl AutoMountExt4 { - #[cfg(any(target_os = "linux", target_os = "android"))] - pub fn try_new(source: &str, target: &str, auto_umount: bool) -> Result { - mount_ext4(source, target)?; - Ok(Self { - target: target.to_string(), - auto_umount, - }) - } - - #[cfg(not(any(target_os = "linux", target_os = "android")))] - pub fn try_new(_src: &str, _mnt: &str, _auto_umount: bool) -> Result { - unimplemented!() - } - - #[cfg(any(target_os = "linux", target_os = "android"))] - pub fn umount(&self) -> Result<()> { - unmount(self.target.as_str(), UnmountFlags::DETACH)?; - Ok(()) - } -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -impl Drop for AutoMountExt4 { - fn drop(&mut self) { - log::info!( - "AutoMountExt4 drop: {}, auto_umount: {}", - self.target, - self.auto_umount - ); - if self.auto_umount { - let _ = self.umount(); - } - } -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_ext4(source: impl AsRef, target: impl AsRef) -> Result<()> { - let new_loopback = loopdev::LoopControl::open()? - .next_free() - .with_context(|| "Failed to alloc loop")?; - new_loopback - .with() - .attach(source) - .with_context(|| "Failed to attach loop")?; - let lo = new_loopback.path().ok_or(anyhow!("no loop"))?; - if let Result::Ok(fs) = fsopen("ext4", FsOpenFlags::FSOPEN_CLOEXEC) { - let fs = fs.as_fd(); - fsconfig_set_string(fs, "source", lo)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - target.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; - } else { - mount(lo, target.as_ref(), "ext4", MountFlags::empty(), "")?; - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn umount_dir(src: impl AsRef) -> Result<()> { - unmount(src.as_ref(), UnmountFlags::empty()) - .with_context(|| format!("Failed to umount {}", src.as_ref().display()))?; - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_overlayfs( - lower_dirs: &[String], - lowest: &str, - upperdir: Option, - workdir: Option, - dest: impl AsRef, -) -> Result<()> { - let lowerdir_config = lower_dirs - .iter() - .map(|s| s.as_ref()) - .chain(std::iter::once(lowest)) - .collect::>() - .join(":"); - info!( - "mount overlayfs on {:?}, lowerdir={}, upperdir={:?}, workdir={:?}", - dest.as_ref(), - lowerdir_config, - upperdir, - workdir - ); - - let upperdir = upperdir - .filter(|up| up.exists()) - .map(|e| e.display().to_string()); - let workdir = workdir - .filter(|wd| wd.exists()) - .map(|e| e.display().to_string()); - - let result = (|| { - let fs = fsopen("overlay", FsOpenFlags::FSOPEN_CLOEXEC)?; - let fs = fs.as_fd(); - fsconfig_set_string(fs, "lowerdir", &lowerdir_config)?; - if let (Some(upperdir), Some(workdir)) = (&upperdir, &workdir) { - fsconfig_set_string(fs, "upperdir", upperdir)?; - fsconfig_set_string(fs, "workdir", workdir)?; - } - fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - dest.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - ) - })(); - - if let Err(e) = result { - warn!("fsopen mount failed: {:#}, fallback to mount", e); - let mut data = format!("lowerdir={lowerdir_config}"); - if let (Some(upperdir), Some(workdir)) = (upperdir, workdir) { - data = format!("{data},upperdir={upperdir},workdir={workdir}"); - } - mount( - KSU_OVERLAY_SOURCE, - dest.as_ref(), - "overlay", - MountFlags::empty(), - data, - )?; - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_tmpfs(dest: impl AsRef) -> Result<()> { - info!("mount tmpfs on {}", dest.as_ref().display()); - if let Result::Ok(fs) = fsopen("tmpfs", FsOpenFlags::FSOPEN_CLOEXEC) { - let fs = fs.as_fd(); - fsconfig_set_string(fs, "source", KSU_OVERLAY_SOURCE)?; - fsconfig_create(fs)?; - let mount = fsmount(fs, FsMountFlags::FSMOUNT_CLOEXEC, MountAttrFlags::empty())?; - move_mount( - mount.as_fd(), - "", - CWD, - dest.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; - } else { - mount( - KSU_OVERLAY_SOURCE, - dest.as_ref(), - "tmpfs", - MountFlags::empty(), - "", - )?; - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn bind_mount(from: impl AsRef, to: impl AsRef) -> Result<()> { - info!( - "bind mount {} -> {}", - from.as_ref().display(), - to.as_ref().display() - ); - if let Result::Ok(tree) = open_tree( - CWD, - from.as_ref(), - OpenTreeFlags::OPEN_TREE_CLOEXEC - | OpenTreeFlags::OPEN_TREE_CLONE - | OpenTreeFlags::AT_RECURSIVE, - ) { - move_mount( - tree.as_fd(), - "", - CWD, - to.as_ref(), - MoveMountFlags::MOVE_MOUNT_F_EMPTY_PATH, - )?; - } else { - mount( - from.as_ref(), - to.as_ref(), - "", - MountFlags::BIND | MountFlags::REC, - "", - )?; - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -fn mount_overlay_child( - mount_point: &str, - relative: &String, - module_roots: &Vec, - stock_root: &String, -) -> Result<()> { - if !module_roots - .iter() - .any(|lower| Path::new(&format!("{lower}{relative}")).exists()) - { - return bind_mount(stock_root, mount_point); - } - if !Path::new(&stock_root).is_dir() { - return Ok(()); - } - let mut lower_dirs: Vec = vec![]; - for lower in module_roots { - let lower_dir = format!("{lower}{relative}"); - let path = Path::new(&lower_dir); - if path.is_dir() { - lower_dirs.push(lower_dir); - } else if path.exists() { - // stock root has been blocked by this file - return Ok(()); - } - } - if lower_dirs.is_empty() { - return Ok(()); - } - // merge modules and stock - if let Err(e) = mount_overlayfs(&lower_dirs, stock_root, None, None, mount_point) { - warn!("failed: {:#}, fallback to bind mount", e); - bind_mount(stock_root, mount_point)?; - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn mount_overlay( - root: &String, - module_roots: &Vec, - workdir: Option, - upperdir: Option, -) -> Result<()> { - info!("mount overlay for {}", root); - std::env::set_current_dir(root).with_context(|| format!("failed to chdir to {root}"))?; - let stock_root = "."; - - // collect child mounts before mounting the root - let mounts = Process::myself()? - .mountinfo() - .with_context(|| "get mountinfo")?; - let mut mount_seq = mounts - .0 - .iter() - .filter(|m| { - m.mount_point.starts_with(root) && !Path::new(&root).starts_with(&m.mount_point) - }) - .map(|m| m.mount_point.to_str()) - .collect::>(); - mount_seq.sort(); - mount_seq.dedup(); - - mount_overlayfs(module_roots, root, upperdir, workdir, root) - .with_context(|| "mount overlayfs for root failed")?; - for mount_point in mount_seq.iter() { - let Some(mount_point) = mount_point else { - continue; - }; - let relative = mount_point.replacen(root, "", 1); - let stock_root: String = format!("{stock_root}{relative}"); - if !Path::new(&stock_root).exists() { - continue; - } - if let Err(e) = mount_overlay_child(mount_point, &relative, module_roots, &stock_root) { - warn!( - "failed to mount overlay for child {}: {:#}, revert", - mount_point, e - ); - umount_dir(root).with_context(|| format!("failed to revert {root}"))?; - bail!(e); - } - } - Ok(()) -} - -#[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn mount_ext4(_src: &str, _target: &str, _autodrop: bool) -> Result<()> { - unimplemented!() -} - -#[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn umount_dir(_src: &str) -> Result<()> { - unimplemented!() -} - -#[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn mount_overlay( - _root: &String, - _module_roots: &Vec, - _workdir: Option, - _upperdir: Option, -) -> Result<()> { - unimplemented!() -} - -#[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn mount_tmpfs(_dest: impl AsRef) -> Result<()> { - unimplemented!() -} diff --git a/drivers/staging/kernelsu/userspace/ksud/src/restorecon.rs b/drivers/staging/kernelsu/userspace/ksud/src/restorecon.rs index 152a7c5ed529..c396481d90a7 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/restorecon.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/restorecon.rs @@ -61,11 +61,11 @@ pub fn restore_syscon>(dir: P) -> Result<()> { Ok(()) } -fn restore_syscon_if_unlabeled>(dir: P) -> Result<()> { +fn restore_modules_con>(dir: P) -> Result<()> { for dir_entry in WalkDir::new(dir).parallelism(Serial) { if let Some(path) = dir_entry.ok().map(|dir_entry| dir_entry.path()) { - if let anyhow::Result::Ok(con) = lgetfilecon(&path) { - if con == UNLABEL_CON || con.is_empty() { + if let Result::Ok(con) = lgetfilecon(&path) { + if con == ADB_CON || con == UNLABEL_CON || con.is_empty() { lsetfilecon(&path, SYSTEM_CON)?; } } @@ -76,6 +76,6 @@ fn restore_syscon_if_unlabeled>(dir: P) -> Result<()> { pub fn restorecon() -> Result<()> { lsetfilecon(defs::DAEMON_PATH, ADB_CON)?; - restore_syscon_if_unlabeled(defs::MODULE_DIR)?; + restore_modules_con(defs::MODULE_DIR)?; Ok(()) } diff --git a/drivers/staging/kernelsu/userspace/ksud/src/sepolicy.rs b/drivers/staging/kernelsu/userspace/ksud/src/sepolicy.rs index 581c416a8185..b7286a06a769 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/sepolicy.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/sepolicy.rs @@ -11,7 +11,7 @@ use nom::{ sequence::Tuple, IResult, Parser, }; -use std::{path::Path, vec}; +use std::{ffi, path::Path, vec}; type SeObject<'a> = Vec<&'a str>; @@ -352,10 +352,11 @@ where let mut statements = vec![]; for line in input.split(['\n', ';']) { - if line.trim().is_empty() { + let trimmed_line = line.trim(); + if trimmed_line.is_empty() || trimmed_line.starts_with('#') { continue; } - if let Ok((_, statement)) = PolicyStatement::parse(line.trim()) { + if let Ok((_, statement)) = PolicyStatement::parse(trimmed_line) { statements.push(statement); } else if strict { bail!("Failed to parse policy statement: {}", line) @@ -659,19 +660,19 @@ impl<'a> TryFrom<&'a PolicyStatement<'a>> for Vec { struct FfiPolicy { cmd: u32, subcmd: u32, - sepol1: *const libc::c_char, - sepol2: *const libc::c_char, - sepol3: *const libc::c_char, - sepol4: *const libc::c_char, - sepol5: *const libc::c_char, - sepol6: *const libc::c_char, - sepol7: *const libc::c_char, + sepol1: *const ffi::c_char, + sepol2: *const ffi::c_char, + sepol3: *const ffi::c_char, + sepol4: *const ffi::c_char, + sepol5: *const ffi::c_char, + sepol6: *const ffi::c_char, + sepol7: *const ffi::c_char, } -fn to_c_ptr(pol: &PolicyObject) -> *const libc::c_char { +fn to_c_ptr(pol: &PolicyObject) -> *const ffi::c_char { match pol { PolicyObject::None | PolicyObject::All => std::ptr::null(), - PolicyObject::One(s) => s.as_ptr().cast::(), + PolicyObject::One(s) => s.as_ptr().cast::(), } } diff --git a/drivers/staging/kernelsu/userspace/ksud/src/su.rs b/drivers/staging/kernelsu/userspace/ksud/src/su.rs index b19bf7a21ca1..7884137e7ef2 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/su.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/su.rs @@ -19,30 +19,16 @@ use rustix::{ #[cfg(any(target_os = "linux", target_os = "android"))] pub fn grant_root(global_mnt: bool) -> Result<()> { - const KERNEL_SU_OPTION: u32 = 0xDEAD_BEEF; - const CMD_GRANT_ROOT: u64 = 0; + rustix::process::ksu_grant_root()?; - let mut result: u32 = 0; - unsafe { - #[allow(clippy::cast_possible_wrap)] - libc::prctl( - KERNEL_SU_OPTION as i32, // supposed to overflow - CMD_GRANT_ROOT, - 0, - 0, - std::ptr::addr_of_mut!(result).cast::(), - ); - } - - anyhow::ensure!(result == KERNEL_SU_OPTION, "grant root failed"); - let mut command = std::process::Command::new("sh"); + let mut command = Command::new("sh"); let command = unsafe { command.pre_exec(move || { if global_mnt { let _ = utils::switch_mnt_ns(1); let _ = utils::unshare_mnt_ns(); } - std::result::Result::Ok(()) + Result::Ok(()) }) }; // add /data/adb/ksu/bin to PATH @@ -64,7 +50,7 @@ fn print_usage(program: &str, opts: Options) { fn set_identity(uid: u32, gid: u32, groups: &[u32]) { #[cfg(any(target_os = "linux", target_os = "android"))] { - rustix::process::set_groups( + rustix::thread::set_thread_groups( groups .iter() .map(|g| unsafe { Gid::from_raw(*g) }) @@ -89,7 +75,7 @@ pub fn root_shell() -> Result<()> { // we are root now, this was set in kernel! use anyhow::anyhow; - let env_args: Vec = std::env::args().collect(); + let env_args: Vec = env::args().collect(); let program = env_args[0].clone(); let args = env_args .iter() @@ -154,7 +140,7 @@ pub fn root_shell() -> Result<()> { .collect::>(); let matches = match opts.parse(&args[1..]) { - std::result::Result::Ok(m) => m, + Result::Ok(m) => m, Err(f) => { println!("{f}"); print_usage(&program, opts); @@ -282,7 +268,7 @@ pub fn root_shell() -> Result<()> { set_identity(uid, gid, &groups); - std::result::Result::Ok(()) + Result::Ok(()) }) }; diff --git a/drivers/staging/kernelsu/userspace/ksud/src/utils.rs b/drivers/staging/kernelsu/userspace/ksud/src/utils.rs index 9bacfa366496..21033918ab05 100644 --- a/drivers/staging/kernelsu/userspace/ksud/src/utils.rs +++ b/drivers/staging/kernelsu/userspace/ksud/src/utils.rs @@ -1,26 +1,20 @@ use anyhow::{bail, Context, Error, Ok, Result}; use std::{ - fs::{self, create_dir_all, remove_file, write, File, OpenOptions}, + fs::{create_dir_all, remove_file, write, File, OpenOptions}, io::{ ErrorKind::{AlreadyExists, NotFound}, Write, }, path::Path, process::Command, - sync::OnceLock, }; use crate::{assets, boot_patch, defs, ksucalls, module, restorecon}; -use std::fs::metadata; #[allow(unused_imports)] use std::fs::{set_permissions, Permissions}; #[cfg(unix)] use std::os::unix::prelude::PermissionsExt; -use hole_punch::*; -use std::io::{Read, Seek, SeekFrom}; - -use jwalk::WalkDir; use std::path::PathBuf; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -41,7 +35,7 @@ pub fn ensure_clean_dir(dir: impl AsRef) -> Result<()> { pub fn ensure_file_exists>(file: T) -> Result<()> { match File::options().write(true).create_new(true).open(&file) { - std::result::Result::Ok(_) => Ok(()), + Result::Ok(_) => Ok(()), Err(err) => { if err.kind() == AlreadyExists && file.as_ref().is_file() { Ok(()) @@ -189,68 +183,6 @@ pub fn has_magisk() -> bool { which::which("magisk").is_ok() } -fn is_ok_empty(dir: &str) -> bool { - use std::result::Result::Ok; - - match fs::read_dir(dir) { - Ok(mut entries) => entries.next().is_none(), - Err(_) => false, - } -} - -fn find_temp_path() -> String { - use std::result::Result::Ok; - - if is_ok_empty(defs::TEMP_DIR) { - return defs::TEMP_DIR.to_string(); - } - - // Try to create a random directory in /dev/ - let r = tempdir::TempDir::new_in("/dev/", ""); - match r { - Ok(tmp_dir) => { - if let Some(path) = tmp_dir.into_path().to_str() { - return path.to_string(); - } - } - Err(_e) => {} - } - - let dirs = [ - defs::TEMP_DIR, - "/patch_hw", - "/oem", - "/root", - defs::TEMP_DIR_LEGACY, - ]; - - // find empty directory - for dir in dirs { - if is_ok_empty(dir) { - return dir.to_string(); - } - } - - // Fallback to non-empty directory - for dir in dirs { - if metadata(dir).is_ok() { - return dir.to_string(); - } - } - - "".to_string() -} - -pub fn get_tmp_path() -> &'static str { - static CHOSEN_TMP_PATH: OnceLock = OnceLock::new(); - - CHOSEN_TMP_PATH.get_or_init(|| { - let r = find_temp_path(); - log::info!("Chosen temp_path: {}", r); - r - }) -} - #[cfg(target_os = "android")] fn link_ksud_to_bin() -> Result<()> { let ksu_bin = PathBuf::from(defs::DAEMON_PATH); @@ -288,167 +220,15 @@ pub fn uninstall(magiskboot_path: Option) -> Result<()> { println!("- Removing directories.."); std::fs::remove_dir_all(defs::WORKING_DIR).ok(); std::fs::remove_file(defs::DAEMON_PATH).ok(); - crate::mount::umount_dir(defs::MODULE_DIR).ok(); std::fs::remove_dir_all(defs::MODULE_DIR).ok(); - std::fs::remove_dir_all(defs::MODULE_UPDATE_TMP_DIR).ok(); println!("- Restore boot image.."); boot_patch::restore(None, magiskboot_path, true)?; println!("- Uninstall KernelSU manager.."); Command::new("pm") - .args(["uninstall", "me.weishu.kernelsu"]) + .args(["uninstall", "com.rifsxd.ksunext"]) .spawn()?; println!("- Rebooting in 5 seconds.."); std::thread::sleep(std::time::Duration::from_secs(5)); Command::new("reboot").spawn()?; Ok(()) } - -// TODO: use libxcp to improve the speed if cross's MSRV is 1.70 -pub fn copy_sparse_file, Q: AsRef>( - src: P, - dst: Q, - punch_hole: bool, -) -> Result<()> { - let mut src_file = File::open(src.as_ref())?; - let mut dst_file = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(dst.as_ref())?; - - dst_file.set_len(src_file.metadata()?.len())?; - - let segments = src_file.scan_chunks()?; - for segment in segments { - if let SegmentType::Data = segment.segment_type { - let start = segment.start; - let end = segment.end; - - src_file.seek(SeekFrom::Start(start))?; - dst_file.seek(SeekFrom::Start(start))?; - - let mut buffer = [0; 4096]; - let mut total_bytes_copied = 0; - - while total_bytes_copied < end - start { - let bytes_to_read = - std::cmp::min(buffer.len() as u64, end - start - total_bytes_copied); - let bytes_read = src_file.read(&mut buffer[..bytes_to_read as usize])?; - - if bytes_read == 0 { - break; - } - - if punch_hole && buffer[..bytes_read].iter().all(|&x| x == 0) { - // all zero, don't copy it at all! - dst_file.seek(SeekFrom::Current(bytes_read as i64))?; - total_bytes_copied += bytes_read as u64; - continue; - } - dst_file.write_all(&buffer[..bytes_read])?; - total_bytes_copied += bytes_read as u64; - } - } - } - - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -fn copy_xattrs(src_path: impl AsRef, dest_path: impl AsRef) -> Result<()> { - use rustix::path::Arg; - let std::result::Result::Ok(xattrs) = extattr::llistxattr(src_path.as_ref()) else { - return Ok(()); - }; - for xattr in xattrs { - let std::result::Result::Ok(value) = extattr::lgetxattr(src_path.as_ref(), &xattr) else { - continue; - }; - log::info!( - "Set {:?} xattr {} = {}", - dest_path.as_ref(), - xattr.to_string_lossy(), - value.to_string_lossy(), - ); - if let Err(e) = - extattr::lsetxattr(dest_path.as_ref(), &xattr, &value, extattr::Flags::empty()) - { - log::warn!("Failed to set xattr: {}", e); - } - } - Ok(()) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn copy_module_files(source: impl AsRef, destination: impl AsRef) -> Result<()> { - use rustix::fs::FileTypeExt; - use rustix::fs::MetadataExt; - - for entry in WalkDir::new(source.as_ref()).into_iter() { - let entry = entry.context("Failed to access entry")?; - let source_path = entry.path(); - let relative_path = source_path - .strip_prefix(source.as_ref()) - .context("Failed to generate relative path")?; - let dest_path = destination.as_ref().join(relative_path); - - if let Some(parent) = dest_path.parent() { - std::fs::create_dir_all(parent).context("Failed to create directory")?; - } - - if entry.file_type().is_file() { - std::fs::copy(&source_path, &dest_path).with_context(|| { - format!("Failed to copy file from {source_path:?} to {dest_path:?}",) - })?; - copy_xattrs(&source_path, &dest_path)?; - } else if entry.file_type().is_symlink() { - if dest_path.exists() { - std::fs::remove_file(&dest_path).context("Failed to remove file")?; - } - let target = std::fs::read_link(entry.path()).context("Failed to read symlink")?; - log::info!("Symlink: {:?} -> {:?}", dest_path, target); - std::os::unix::fs::symlink(target, &dest_path).context("Failed to create symlink")?; - copy_xattrs(&source_path, &dest_path)?; - } else if entry.file_type().is_dir() { - create_dir_all(&dest_path)?; - let metadata = std::fs::metadata(&source_path).context("Failed to read metadata")?; - std::fs::set_permissions(&dest_path, metadata.permissions()) - .with_context(|| format!("Failed to set permissions for {dest_path:?}"))?; - copy_xattrs(&source_path, &dest_path)?; - } else if entry.file_type().is_char_device() { - if dest_path.exists() { - std::fs::remove_file(&dest_path).context("Failed to remove file")?; - } - let metadata = std::fs::metadata(&source_path).context("Failed to read metadata")?; - let mode = metadata.permissions().mode(); - let dev = metadata.rdev(); - if dev == 0 { - log::info!( - "Found a char device with major 0: {}", - entry.path().display() - ); - rustix::fs::mknodat( - rustix::fs::CWD, - &dest_path, - rustix::fs::FileType::CharacterDevice, - mode.into(), - dev, - ) - .with_context(|| format!("Failed to create device file at {dest_path:?}"))?; - copy_xattrs(&source_path, &dest_path)?; - } - } else { - log::info!( - "Unknown file type: {:?}, {:?},", - entry.file_type(), - entry.path(), - ); - } - } - Ok(()) -} - -#[cfg(not(any(target_os = "linux", target_os = "android")))] -pub fn copy_module_files(_source: impl AsRef, _destination: impl AsRef) -> Result<()> { - unimplemented!() -} diff --git a/drivers/staging/kernelsu/website/docs/.vitepress/locales/zh_TW.ts b/drivers/staging/kernelsu/website/docs/.vitepress/locales/zh_TW.ts index 3a92d45b2cf7..5d6fd9e8f14e 100644 --- a/drivers/staging/kernelsu/website/docs/.vitepress/locales/zh_TW.ts +++ b/drivers/staging/kernelsu/website/docs/.vitepress/locales/zh_TW.ts @@ -6,7 +6,7 @@ const pkg = require('vitepress/package.json') export default defineConfig({ lang: 'zh-TW', - description: '一個以核心為基礎,適用於 Android GKI 的 Root 解決方案。', + description: '一個基於核心,適用於 Android GKI 的 Root 解決方案。', themeConfig: { nav: nav(), diff --git a/drivers/staging/kernelsu/website/docs/guide/how-to-integrate-for-non-gki.md b/drivers/staging/kernelsu/website/docs/guide/how-to-integrate-for-non-gki.md index bca544f4bda3..b4e6c80253f6 100644 --- a/drivers/staging/kernelsu/website/docs/guide/how-to-integrate-for-non-gki.md +++ b/drivers/staging/kernelsu/website/docs/guide/how-to-integrate-for-non-gki.md @@ -18,9 +18,13 @@ KernelSU uses kprobe to do kernel hooks, if the *kprobe* runs well in your kerne First, add KernelSU to your kernel source tree: ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` +:::info +[KernelSU 1.0 and later versions no longer support non-GKI kernels](https://github.com/tiann/KernelSU/issues/1705). The last supported version is `v0.9.5`, please make sure to use the correct version. +::: + Then, you should check if *kprobe* is enabled in your kernel config, if it is not, please add these configs to it: ```txt @@ -51,22 +55,10 @@ If kprobe does not work in your kernel (may be an upstream or kernel bug below 4 First, add KernelSU to your kernel source tree: -::: code-group - -```sh[Latest tag(stable)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +```sh +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` -```sh[ main branch(dev)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main -``` - -```sh[Select tag(Such as v0.5.2)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 -``` - -::: - Keep in mind that on some devices, your defconfig may be in `arch/arm64/configs` or in other cases `arch/arm64/configs/vendor/your_defconfig`. For whichever defconfig you're using, make sure to enable `CONFIG_KSU` with `y` to enable or `n` to disable it. For example, in case you chose to enable it, you defconfig should contain the following string: ```txt diff --git a/drivers/staging/kernelsu/website/docs/id_ID/guide/how-to-integrate-for-non-gki.md b/drivers/staging/kernelsu/website/docs/id_ID/guide/how-to-integrate-for-non-gki.md index 11bd7905e9ba..d26d3c62ceea 100644 --- a/drivers/staging/kernelsu/website/docs/id_ID/guide/how-to-integrate-for-non-gki.md +++ b/drivers/staging/kernelsu/website/docs/id_ID/guide/how-to-integrate-for-non-gki.md @@ -17,23 +17,13 @@ KernelSU menggunakan kprobe untuk melakukan hook kernel, jika *kprobe* berjalan Pertama, tambahkan KernelSU ke dalam berkas kernel source tree: -- Latest tag(stable) - ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` -- main branch(dev) - -```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main -``` - -- Select tag(Such as v0.5.2) - -```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 -``` +:::info +[KernelSU 1.0 dan versi yang lebih baru tidak lagi mendukung kernel non-GKI](https://github.com/tiann/KernelSU/issues/1705). Versi terakhir yang didukung adalah `v0.9.5`, pastikan untuk menggunakan versi yang benar. +::: Kemudian, Anda harus memeriksa apakah *kprobe* diaktifkan dalam konfigurasi kernel Anda, jika tidak, tambahkan konfigurasi ini ke dalamnya: @@ -56,7 +46,7 @@ Jika kprobe tidak dapat bekerja pada kernel Anda (mungkin karena bug di upstream Pertama, tambahkan KernelSU ke dalam direktori kernel source tree: ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` Kemudian, tambahkan panggilan KernelSU ke source kernel, berikut ini adalah patch yang dapat dirujuk: diff --git a/drivers/staging/kernelsu/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md b/drivers/staging/kernelsu/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md index e880f99b1ea2..1652a00d1a72 100644 --- a/drivers/staging/kernelsu/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md +++ b/drivers/staging/kernelsu/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md @@ -18,9 +18,13 @@ O KernelSU usa kprobe para fazer ganchos do kernel, se o kprobe funcionar bem em Primeiro, adicione o KernelSU à árvore de origem do kernel: ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` +:::info INFORMAÇÕES +[KernelSU 1.0 e versões posteriores não suportam mais kernels não GKI](https://github.com/tiann/KernelSU/issues/1705). A última versão suportada é a `v0.9.5`, por favor, certifique-se de usar a versão correta. +::: + Então, você deve verificar se o kprobe está ativado na configuração do seu kernel, se não estiver, adicione estas configurações a ele: ```txt @@ -51,22 +55,10 @@ Se o kprobe não funcionar no seu kernel (pode ser um bug do upstream ou do kern Primeiro, adicione o KernelSU à árvore de origem do kernel: -::: code-group - -```sh[Tag mais recente (estável)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +```sh +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` -```sh[Branch principal (dev)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main -``` - -```sh[Selecionar tag (como v0.5.2)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 -``` - -::: - Tenha em mente que em alguns dispositivos, seu defconfig pode estar em `arch/arm64/configs` ou em outros casos `arch/arm64/configs/vendor/your_defconfig`. Para qualquer defconfig que você estiver usando, certifique-se de ativar `CONFIG_KSU` com `y` para ativa-lo ou `n` para desativa-lo. Por exemplo, caso você opte por ativa-lo, seu defconfig deverá conter a seguinte string: ```txt diff --git a/drivers/staging/kernelsu/website/docs/public/templates/kernelmanager.root b/drivers/staging/kernelsu/website/docs/public/templates/kernelmanager.root index 899e0d64e05d..3973dd1d5972 100644 --- a/drivers/staging/kernelsu/website/docs/public/templates/kernelmanager.root +++ b/drivers/staging/kernelsu/website/docs/public/templates/kernelmanager.root @@ -10,13 +10,10 @@ "READPROC" ], "capabilities":[ - "CAP_SYS_MODULE", - "CAP_SYS_NICE", - "CAP_SYS_RESOURCE", "CAP_KILL", "CAP_SYSLOG", - "CAP_PERFMON", - "CAP_SYS_BOOT" + "CAP_SYS_BOOT", + "CAP_DAC_OVERRIDE" ], "context":"u:r:su:s0", "namespace":"INHERITED", diff --git a/drivers/staging/kernelsu/website/docs/repos.json b/drivers/staging/kernelsu/website/docs/repos.json index 47cae9601d0d..aabacea7420e 100644 --- a/drivers/staging/kernelsu/website/docs/repos.json +++ b/drivers/staging/kernelsu/website/docs/repos.json @@ -54,7 +54,7 @@ "kernel_name": "android_kernel_xiaomi_onc", "kernel_link": "https://github.com/hadadarjt/android_kernel_xiaomi_onc/tree/los21-KSU/local-non-gerrit-review", "devices": "Redmi 7: onclite | Redmi Y3: onc" - }, + }, { "maintainer": "HMTheBoy154", "maintainer_link": "https://github.com/hmtheboy154", @@ -398,20 +398,6 @@ "kernel_link": "https://github.com/tejas101k/Cuh-KerneL", "devices": "Xiaomi Redmi Note 8/8T (ginkgo/willow)" }, - { - "maintainer": "Coconutat", - "maintainer_link": "https://github.com/Coconutat", - "kernel_name": "android_kernel_xiaomi_ruby_exp", - "kernel_link": "https://github.com/Coconutat/android_kernel_xiaomi_ruby_exp", - "devices": "Redmi Note 12 Pro / Pro+ For MIUI 14" - }, - { - "maintainer": "Coconutat", - "maintainer_link": "https://github.com/Coconutat", - "kernel_name": "android_kernel_xiaomi_sdm845_byd_exp", - "kernel_link": "https://github.com/Coconutat/android_kernel_xiaomi_sdm845_byd_exp", - "devices": "Xiaomi Mi 8 Pro(UD)[equuleus]/Explorer Edition[ursa]" - }, { "maintainer": "Abdul Wahid Khan", "maintainer_link": "https://github.com/Wahid7852", @@ -608,13 +594,6 @@ "kernel_link": "https://github.com/Fede2782/android_kernel_samsung_a34x/", "devices": "Samsung Galaxy A34 5G (a34x)" }, - { - "maintainer": "KJ-Network", - "maintainer_link": "https://github.com/KJ-Network", - "kernel_name": "K-Nel-M1721", - "kernel_link": "https://github.com/KJ-Network/K-Nel-M1721/", - "devices": "Meizu M6 Note (M1721)" - }, { "maintainer": "SnowWolf725 ", "maintainer_link": "https://github.com/snowwolf725", @@ -712,5 +691,40 @@ "kernel_name": "kernel_xiaomi_chopin", "kernel_link": "https://github.com/ChopinKernels/kernel_xiaomi_chopin_android_S", "devices": "Redmi Note 10 Pro 5G (chopin) / Poco X3 GT (choping)" + }, + { + "maintainer": "Fede2782", + "maintainer_link": "https://github.com/Fede2782", + "kernel_name": "android_kernel_motorola_sdm632", + "kernel_link": "https://github.com/Fede2782/android_kernel_motorola_sdm632", + "devices": "Motorola Moto G7 (river)" + }, + { + "maintainer": "EmanuelCN", + "maintainer_link": "https://github.com/EmanuelCN", + "kernel_name": "N0Kernel", + "kernel_link": "https://github.com/EmanuelCN/kernel_xiaomi_sm8250", + "devices": "Poco F3 (alioth) | Mi 10T/Pro (apollo) | Poco F4 (munch)" + }, + { + "maintainer": "kvsnr113", + "maintainer_link": "https://github.com/kvsnr113", + "kernel_name": "NOVA Kernel", + "kernel_link": "https://github.com/kvsnr113/xiaomi_sm8250_kernel", + "devices": "Poco F3 (alioth) | Mi 10T/Pro (apollo) | Poco F4 (munch)" + }, + { + "maintainer": "anVzdGFtb25", + "maintainer_link": "https://github.com/anVzdGFtb25", + "kernel_name": "android_kernel_xiaomi_mt6768", + "kernel_link": "https://github.com/anVzdGFtb25/android_kernel_xiaomi_mt6768", + "devices": "Redmi 9 ( lancelot )" + }, + { + "maintainer": "rifsxd", + "maintainer_link": "https://github.com/rifsxd", + "kernel_name": "android_kernel_realme_RMX3511", + "kernel_link": "https://github.com/rifsxd/android_kernel_realme_RMX3511", + "devices": "Realme C35 (RMX3511)" } ] diff --git a/drivers/staging/kernelsu/website/docs/zh_CN/guide/how-to-integrate-for-non-gki.md b/drivers/staging/kernelsu/website/docs/zh_CN/guide/how-to-integrate-for-non-gki.md index 6118756a25f5..5f20068259fd 100644 --- a/drivers/staging/kernelsu/website/docs/zh_CN/guide/how-to-integrate-for-non-gki.md +++ b/drivers/staging/kernelsu/website/docs/zh_CN/guide/how-to-integrate-for-non-gki.md @@ -17,20 +17,12 @@ KernelSU 使用 kprobe 机制来做内核的相关 hook,如果 *kprobe* 可以 首先,把 KernelSU 添加到你的内核源码树,在内核的根目录执行以下命令: -::: code-group - -```sh[最新tag(稳定版本)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - -``` - -```sh[main分支(开发版本)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main -``` - -```sh[指定tag(比如v0.5.2)] -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 +```sh +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` +:::info +[KernelSU 1.0 及更高版本已经不再支持非 GKI 内核](https://github.com/tiann/KernelSU/issues/1705),最后的支持版本为 `v0.9.5`,请注意使用正确的版本。 ::: 然后,你需要检查你的内核是否开启了 *kprobe* 相关的配置,如果没有开启,需要添加以下配置: @@ -59,7 +51,7 @@ CONFIG_KPROBE_EVENTS=y 首先,把 KernelSU 添加到你的内核源码树,在内核的根目录执行以下命令: ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` 请注意,某些设备的defconfig文件可能在`arch/arm64/configs/设备代号_defconfig`或位于`arch/arm64/configs/vendor/设备代号_defconfig`。在您的defconfig文件中,将 `CONFIG_KSU`设置为`y`以启用KernelSU,或设置为`n`以禁用。比如在某个defconfig中: diff --git a/drivers/staging/kernelsu/website/docs/zh_CN/guide/module.md b/drivers/staging/kernelsu/website/docs/zh_CN/guide/module.md index 3690ed02915b..89dcc8e5988a 100644 --- a/drivers/staging/kernelsu/website/docs/zh_CN/guide/module.md +++ b/drivers/staging/kernelsu/website/docs/zh_CN/guide/module.md @@ -72,9 +72,9 @@ KernelSU 模块就是一个放置在 `/data/adb/modules` 内且满足如下结 │ │ │ │ *** 自动生成的目录,不要手动创建或者修改! *** │ │ -│ ├── vendor <--- A symlink to $MODID/system/vendor -│ ├── product <--- A symlink to $MODID/system/product -│ ├── system_ext <--- A symlink to $MODID/system/system_ext +│ ├── vendor <--- 如果 /system/vendor 是符号链接且存在,从 $MODID/system/vendor 移动到模块根目录 +│ ├── product <--- 如果 /system/product 是符号链接且存在,从 $MODID/system/product 移动到模块根目录 +│ ├── system_ext <--- 如果 /system/system_ext 是符号链接且存在,从 $MODID/system/system_ext 移动到模块根目录 │ │ │ │ *** Any additional files / folders are allowed *** │ │ diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/app-profile.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/app-profile.md index 659c5660164b..993857702927 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/app-profile.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/app-profile.md @@ -2,7 +2,8 @@ App Profile 是 KernelSU 提供的一種針對各種應用程式自訂其使用配置的機制。 -對於授予了root 權限(也即可以使用 `su`)的應用程式來說,App Profile 也可以稱為Root Profile,它可以自訂 `su` 的 `uid`, `gid` , `groups` , ` capabilities` 以及 `SELinux context` 規則,從而限制 root 使用者的權限;例如可以針對防火牆應用程式僅授予網路權限,而不授予檔案存取權限,針對凍結類別應用程式僅授予 shell 權限而不是直接給 root ;透過最小化權限原則**把權力關進籠子裡**。 +對於授予了 root 權限(即可以使用 `su`)的應用程式來說,App Profile 也可以稱為 Root Profile,它可以自訂 `su` 的 `uid`、`gid`、`groups`、` capabilities` 以及 `SELinux context` 規則,從而限制 root 使用者的權限。 +例如可以針對防火牆應用程式僅授予網路權限,而不授予檔案存取權限,針對凍結類別應用程式僅授予 shell 權限而不是直接給 root ;透過最小化權限原則**把權力關進籠子裡**。 對於沒有被授予 root 權限的普通應用,App Profile 可以控制核心以及模組系統對此應用的行為;例如是否需要針對此應用程式卸載模組造成的修改等。核心和模組系統可以透過此配置決定是否要做一些類似「隱藏痕跡」類別的操作。 @@ -16,8 +17,8 @@ UID 為 0 的使用者稱為 root 使用者,GID 為 0 的群組稱為 root 群 對於 Android 系統來說,每個應用程式都是一個單獨的使用者(不考慮 share uid 的情況),擁有一個唯一的 UID。例如 `0` 是 root 使用者,`1000` 是 `system`,`2000` 是 ADB shell,10000-19999 的是一般使用者。 -:::info -此處的 UID 跟 Android 系統的多使用者,或者說工作資料(Work Profile),不是概念。工作資料實際上是對 UID 進行分片實現的,例如 10000-19999 是主使用者,110000-119999 是工作資料;他們中的任何一個普通應用都擁有自己獨有的 UID。 +:::info 補充 +此處的 UID 跟 Android 系統的多使用者,或者說工作資料(Work Profile),是不同概念。工作資料實際上是對 UID 進行分片實現的,例如 10000-19999 是主使用者,110000-119999 是工作資料;他們中的任何一個普通應用都擁有自己獨有的 UID。 ::: 每一個應用程式可以有若干個群組,GID 使其主要的群組,通常與 UID 一致;其他的群組稱為補充群組(groups)。某些權限是透過群組控制的,例如網路訪問,藍牙等。 @@ -29,7 +30,7 @@ oriole:/ $ id uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_ww) (ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readreadtracefs:s05: ``` -其中,UID 為`2000`,GID 也即主要組ID 也為`2000`;除此之外它還在許多補充組裡面,例如`inet` 組代表可以創建`AF_INET` 和`AF_INET6` 的socket(存取網路),`sdcard_rw` 代表可以讀寫sdcard 等。 +其中,UID 為`2000`,GID 也即主要組 ID 也為 `2000`;除此之外它還在許多補充組裡面,例如 `inet` 組代表可以創建 `AF_INET` 和 `AF_INET6` 的 socket(存取網路),`sdcard_rw` 代表可以讀寫 sdcard 等。 KernelSU 的 Root Profile 可以自訂執行 `su` 後 root 程式的 UID, GID 和 groups。例如,你可以設定某個 root 應用程式的Root Profile 其UID 為`2000`,這表示此應用程式在使用`su` 的時候,它的實際權限是ADB Shell 等級;你可以去掉groups 中的`inet` ,這樣這個`su` 就無法存取網路。 @@ -43,7 +44,7 @@ App Profile 只是控制 root 應用程式使用 `su` 後的權限,它並非 Capabilities 是 Linux 的一種分權機制。 -傳統的 UNIX 系統為了執行權限檢查,將流程分為兩類:特權程式(其有效使用者 ID 為 0,稱為超級使用者或 root)和非特權程式(其有效 UID 為非零)。特權程式會繞過所有核心權限檢查,而非特權程式則根據其憑證(通常是有效UID、有效GID和補充群組清單)進行完整的權限檢查。 +傳統的 UNIX 系統為了執行權限檢查,將流程分為兩類:特權程式(其等效使用者 ID 為 0,稱為超級使用者或 root)和非特權程式(其等效 UID 為非零)。特權程式會繞過所有核心權限檢查,而非特權程式則根據其憑證(通常是等校 UID、等效 GID 和補充群組清單)進行完整的權限檢查。 從 Linux 2.2開始,Linux 將傳統上與超級使用者關聯的特權分解為獨立的單元,稱為 Capabilities(有的也翻譯為「權能」),它們可以獨立啟用和停用。 @@ -52,7 +53,7 @@ Capabilities 是 Linux 的一種分權機制。 KernelSU 的 Root Profile 可以自訂執行 `su` 後 root 程式的 Capabilities,從而實現只授予「部分 root 權限」。與上面介紹的UID, GID 不同,某些 root 應用就是需要 `su` 後 UID 是 `0`,此時我們可以透過限制這個 UID 為 `0` 的 root 使用者的 Capabilities,就可以限制它能夠執行的操作。 :::tip 強烈建議 -Linux 系統關於 Capability 的[官方文件](https://man7.org/linux/man-pages/man7/capabilities.7.html),解釋了每一項Capability 所代表的能力,寫的非常詳細,如果你想要自訂Capabilities,請務必先閱讀此文件。 +Linux 的 Capability [官方文件](https://man7.org/linux/man-pages/man7/capabilities.7.html)詳細解釋了每一項 Capability 所代表的能力,如果你想要自訂Capabilities,請務必先閱讀此文件。 ::: ### SELinux {#selinux} @@ -76,7 +77,7 @@ SELinux 的完整概念比較複雜,我們這裡不打算講解它的具體運 KernelSU 的 Root Profile 可以自訂執行 `su` 後 root 程式的 SELinux context,並且可以針對這個 context 設定特定的存取控制規則,從而更精細地控制 root 權限。 -通常情況下,應用程式執行 `su` 後,會將進程切換到一個**不受任何限制** 的SELinux 域,例如`u:r:su:s0`,透過 Root Profile,我們可以將它切換到一個自訂的網域,例如 `u:r:app1:s0`,然後為這個網域制定一系列規則: +通常情況下,應用程式執行 `su` 後,會將進程切換到一個**不受任何限制** 的 SELinux 域,例如`u:r:su:s0`,透過 Root Profile,我們可以將它切換到一個自訂的作用域,例如 `u:r:app1:s0`,然後為這個作用域制定一系列規則: ```sh type app1 @@ -85,34 +86,34 @@ typeattribute app1 mlstrustedsubject allow app1 * * * ``` -注意:此處的 `allow app1 * * *` 僅僅作為演示方便而使用,實際過程中不應使用這個規則,因為它跟 permissive 區別不大。 +注意:此處的 `allow app1 * * *` 僅僅作為示範方便而使用,實際過程中不應使用這個規則,因為它跟寬容模式區別不大。 ### 逃逸 {#escalation} 如果 Root Profile 的配置不合理,那麼可能會發生逃逸的情況:Root Profile 的限制會意外失效。 -例如,如果你為ADB shell 使用者設定允許root 權限(這是相當常見的情況);然後你給某個普通應用程式允許root 權限,但是配置它的root profile 中的UID 為2000(ADB shell 使用者的UID);那麼此時,這個App 可以透過執行兩次 `su` 來獲得完整的root 權限: +例如,如果你為ADB shell 使用者設定允許root 權限(這是相當常見的情況);然後你給某個普通應用程式允許 root 權限,但是配置它的 root profile 中的 UID 為 2000(ADB shell 使用者的UID);那麼此時,這個 App 可以透過執行兩次 `su` 來獲得完整的root 權限: -1. 第一次執行 `su`,由於 App Profile 強制生效,會正常切換到 UID 為 `2000(adb shell)` 而非 `0(root)`。 -2. 第二次執行 `su`,由於此時它 UID 是 `2000`,而你給 `2000(adb shell)` 配置了允許 root,它會獲得完整的 root 權限! +1. 第一次執行 `su`,由於 App Profile 強制生效,會正常切換到 UID 為 `2000` (adb shell) 而非 `0` (root)。 +2. 第二次執行 `su`,由於此時它 UID 是 `2000`,而你給 `2000` (adb shell) 配置了允許 root,它會獲得完整的 root 權限! :::warning 注意 這是完全符合預期的行為,並非 BUG!因此我們建議: -如果你的確需要給 adb 授予 root 權限(例如你是開發者),那麼不建議你在配置 Root Profile 的時候將 UID 改成 `2000`,用 `1000(system)` 會更好。 +如果你的確需要給 adb 授予 root 權限(例如你是開發者),那麼不建議你在配置 Root Profile 的時候將 UID 改成 `2000`,用 `1000` (system) 會更好。 ::: ## Non Root Profile {#non-root-profile} ### 卸載模組 {#umount-modules} -KernelSU 提供了一種 systemless 的方式來修改系統分區,這是透過掛載 overlayfs 來實現的。但有些情況下,App 可能會對這種行為比較敏感;因此,我們可以透過設定「卸載模組」來卸載掛載在這些應用程式上的模組。 +KernelSU 提供了一種無須直接修改系統分區的方式 (systemless) 來修改系統分區,這是透過掛載 overlayfs 來實現的。但有些情況下,App 可能會對這種行為比較敏感;因此,我們可以透過設定「卸載模組」來卸載掛載在這些應用程式上的模組。 另外,KernelSU 管理器的設定介面還提供了一個「預設卸載模組」的開關,這個開關預設是**開啟**的,這表示**如果不對應用程式做額外的設定**,預設情況下 KernelSU 或某些模組會對此應用程式執行卸載操作。當然,如果你不喜歡這個設定或這個設定會影響某些 App,你可以有以下選擇: 1. 保持「預設卸載模組」的開關,然後針對不需要「卸載模組」的應用程式進行單獨的設置,在 App Profile 中關閉「卸載模組」;(相當於「白名單」)。 2. 關閉「預設卸載模組」的開關,然後針對需要「卸載模組」的應用程式進行單獨的設置,在 App Profile 中開啟「卸載模組」;(相當於「黑名單」)。 -:::info -KernelSU 在 5.10 及以上內核上,內核無須任何修改就可以卸載模組;但在 5.10 以下的設備上,這個開關僅僅是一個“設定”,KernelSU 本身不會做任何動作,如果你希望在 5.10 以前的內核可以卸載模組,你需要將 `path_unmount` 函數向後移植到 `fs/namespace.c`,您可以在[如何為非 GKI 核心整合 KernelSU](/zh_TW/guide/how-to-integrate-for-non-gki.html)的末尾獲取更多資訊。一些模組(如 ZygiskNext)也會透過這個設定決定是否需要卸載。 +:::info 提示 +KernelSU 在 5.10 及以上內核上,內核無須任何修改就可以卸載模組;但在 5.10 以下的設備上,這個開關僅僅是一個"設定",KernelSU 本身不會做任何動作,如果你希望在 5.10 以前的內核可以卸載模組,你需要將 `path_unmount` 函數向後移植到 `fs/namespace.c`,您可以在[如何為非 GKI 核心整合 KernelSU](how-to-integrate-for-non-gki.md#how-to-backport-path_unpount)獲取更多資訊。一些模組(如 ZygiskNext)也會透過這個設定決定是否需要卸載。 ::: \ No newline at end of file diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/difference-with-magisk.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/difference-with-magisk.md index 6cd291e171de..fdaa5fc9d940 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/difference-with-magisk.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/difference-with-magisk.md @@ -1,4 +1,4 @@ -# KernelSU 與 Magisk 的差異 {#title} +# KernelSU 與 Magisk 的差異 {#difference-with-magisk} 儘管 KernelSU 模組和 Magisk 模組之間有許多相似之處,但由於它們完全不同的實作機制,不可避免地存在一些差異;如果您想讓您的模組同時在 Magisk 和 KernelSU 上運作,那麼您必須瞭解這些差異。 @@ -6,7 +6,7 @@ - 模組檔案格式:都以 Zip 的格式組織模組,並且模組的格式幾乎相同 - 模組安裝目錄:都位於 `/data/adb/modules` -- Systemless:都支援通過模組以無系統修改的方式來更改 `/system` +- 無系統修改:都支援透過模組以無系統修改的方式來更改 `/system` - `post-fs-data.sh`:執行階段和語義完全相同 - `service.sh`:執行階段和語義完全相同 - `system.prop`:完全相同 @@ -19,10 +19,10 @@ 以下是一些不同之處: -1. KernelSU 的模組不支援在 Recovery 中安裝。 +1. KernelSU 的模組無法在 Recovery 中安裝。 2. KernelSU 的模組沒有內建的 Zygisk 支援 (但您可以透過 [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) 來使用 Zygisk 模組)。 3. KernelSU 模組取代或刪除檔案與 Magisk 完全不同。KernelSU 不支援 `.replace` 方法,相反,您需要透過 `mknod filename c 0 0` 建立相同名稱的資料夾以刪除對應檔案。 -4. BusyBox 的目錄不同;KernelSU 內建的 BusyBox 在 `/data/adb/ksu/bin/busybox` 而 Magisk 在 `/data/adb/magisk/busybox`;**注意此為 KernelSU 內部行為,未來可能會變更!** -5. KernelSU 不支援 `.replace` 檔案;但 KernelSU 支援 `REPLACE` 和 `REMOVE` 變數以移除或取代檔案 (資料夾)。 +4. BusyBox 的目錄不同。KernelSU 內建的 BusyBox 在 `/data/adb/ksu/bin/busybox`,而 Magisk 在 `/data/adb/magisk/busybox`。**注意此為 KernelSU 內部行為,未來可能會變更!** +5. KernelSU 不支援 `.replace` 檔案;但 KernelSU 支援 `REPLACE` 和 `REMOVE` 變數以移除或取代檔案與資料夾。 6. KernelSU 新增了 `boot-completed` 階段以在啟動完成時執行一些腳本。 -7. KernelSU 新增了 `post-mount` 階段,以便在掛載 overlayfs 後執行一些腳本 +7. KernelSU 新增了 `post-mount` 階段,以便在掛載 overlayfs 後執行一些腳本。 diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/faq.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/faq.md index 8f1c13400c26..57166b68c4ac 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/faq.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/faq.md @@ -26,7 +26,7 @@ KernelSU 沒有內建 Zygisk 支援,但是您可以用 [ZygiskNext](https://gi KernelSU 的模組系統與 Magisk 的 magic mount 存在衝突,如果在 KernelSU 中啟用了任何模組,那麼整個 Magisk 將無法正常運作。 -但是如果您只使用 KernelSU 的 `su`,那么它會和 Magisk 一同運作:KernelSU 修改 `kernel` 、 Magisk 修改 `ramdisk`,它們可以搭配使用。 +但是如果您只使用 KernelSU 的 `su`,那么它會和 Magisk 一同運作:KernelSU 修改 `kernel`、Magisk 修改 `ramdisk`,它們可以搭配使用。 ## KernelSU 会取代 Magisk 嗎? @@ -49,11 +49,11 @@ KernelSU 的模組系統與 Magisk 的 magic mount 存在衝突,如果在 Kern ## 如何為舊版核心整合 KernelSU? -請參閱[指南](how-to-integrate-for-non-gki) +請參閱[指南](how-to-integrate-for-non-gki.md) ## 為何我的 Android 版本為 13,但核心版本卻是 "android12-5.10"? -核心版本與 Android 版本無關,如果您要刷新 KernelSU,請一律使用**核心版本**而非 Android 版本,如果你為 "android12-5.10" 的裝置刷新 Android 13 的核心,等候您的將會是開機迴圈。 +核心版本與 Android 版本無關,如果您要使用 KernelSU,請一律使用**核心版本**而非 Android 版本,如果你為 "android12-5.10" 的裝置寫入 Android 13 的核心,等候您的將會是開機迴圈。 ## 我是 GKI1.0,能用 KernelSU 嗎? diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-build.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-build.md index 034044945df1..89517c84b0d2 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-build.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-build.md @@ -5,7 +5,7 @@ 1. [建置核心](https://source.android.com/docs/setup/build/building-kernels) 2. [標準核心映像 (GKI) 發行組建](https://source.android.com/docs/core/architecture/kernel/gki-release-builds) -::: warning +::: warning 警告 此文件適用於 GKI 裝置,如果您是舊版核心,請參閱[如何為非 GKI 裝置整合 KernelSU](how-to-integrate-for-non-gki) ::: @@ -20,7 +20,7 @@ repo init -m manifest.xml repo sync ``` -`` 是一個可以唯一確定組建的資訊清單檔案,您可以使用這個資訊清單進行可重新預測的組建。您需要從[標準核心映像 (GKI) 發行組建](https://source.android.com/docs/core/architecture/kernel/gki-release-builds) 下載資訊清單檔案 +`` 是一個可以唯一確定組建的資訊清單,您可以使用這個資訊清單進行可重新預測的組建。您需要從[標準核心映像 (GKI) 發行組建](https://source.android.com/docs/core/architecture/kernel/gki-release-builds)下載資訊清單。 ### 建置 {#build} @@ -34,14 +34,14 @@ LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh 不要忘記新增 `LTO=thin`,否則,如果您的電腦記憶體小於 24GB,建置可能會失敗。 -從 Android 13 開始,核心由 `bazel` 建置: +從 Android 13 開始,核心使用 `bazel` 建置: ```sh tools/bazel build --config=fast //common:kernel_aarch64_dist ``` -:::info -對於某些 Android 14 內核,要使 Wi-Fi/藍牙正常工作,可能需要刪除所有受 GKI 保護的匯出: +:::info 你可能需要知道... +對於某些 Android 14 核心,要使 Wi-Fi/藍牙正常工作,可能需要刪除所有受 GKI 保護的匯出: ```sh rm common/android/abi_gki_protected_exports_* @@ -52,22 +52,20 @@ rm common/android/abi_gki_protected_exports_* 如果您可以成功建置核心,那麼建置 KernelSU 就會非常輕鬆,依自己的需求在核心原始碼根目錄中執行以下任一命令: -- 最新 tag (穩定版本) +::: code-group -```sh +```sh[最新 tag (穩定版本)] curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - ``` -- main 分支 (開發版本) - -```sh +```sh[main 分支 (開發版本)] curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main ``` -- 選取 tag (例如 v0.5.2) - -```sh +```sh[選取 tag (例如 v0.5.2)] curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 ``` +::: + 然後重新建置核心,您將會得到一個帶有 KernelSU 的核心映像! diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-integrate-for-non-gki.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-integrate-for-non-gki.md index 43b4980e9a66..a6c28485f313 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-integrate-for-non-gki.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/how-to-integrate-for-non-gki.md @@ -1,4 +1,4 @@ -# 如何為非 GKI 核心整合 KernelSU {#introduction} +# 如何為非 GKI 核心整合 KernelSU {#how-to-integrate-kernelsu-for-non-gki-kernels} KernelSU 可以被整合到非 GKI 核心中,現在它最低支援到核心 4.14 版本;理論上也可以支援更低的版本。 @@ -11,31 +11,21 @@ KernelSU 可以被整合到非 GKI 核心中,現在它最低支援到核心 4. 1. 藉助 `kprobe` 自動整合 2. 手動修改核心原始碼 -## 使用 kprobe 整合 {#using-kprobes} +## 使用 kprobe 整合 {#integrate-with-kprobe} KernelSU 使用 kprobe 機制來處理核心的相關 hook,如果 *kprobe* 可以在您建置的核心中正常運作,那麼建議使用這個方法進行整合。 首先,把 KernelSU 新增至您的核心來源樹狀結構,再核心的根目錄執行以下命令: -- 最新 tag (稳定版本) - ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 ``` -- main 分支(開發版本) +:::info 公告 +[KernelSU 1.0 及更新版本不再支援非 GKI 核心](https://github.com/tiann/KernelSU/issues/1705)。最後一個支援的版本為 `v0.9.5`,請確保使用的版本正確。 +::: -```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main -``` - -- 選取 tag (例如 v0.5.2) - -```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2 -``` - -然後,您需要檢查您的核心是否啟用 *kprobe* 相關組態,如果未啟用,則需要新增以下組態: +然後,您需要檢查您的核心是否啟用 *kprobe*,如果未啟用,則需要新增以下設定: ``` CONFIG_KPROBES=y @@ -45,33 +35,40 @@ CONFIG_KPROBE_EVENTS=y 最後,重新建置您的核心即可。 -如果您發現 KPROBES 仍未生效,很有可能是因為它的相依性 `CONFIG_MODULES` 並未被啟用 (如果還是未生效請輸入 `make menuconfig` 搜尋 KPROBES 的其他相依性並啟用) +如果您發現 KPROBES 仍未生效,很有可能是因為它依賴的 `CONFIG_MODULES` 並未被啟用,如果還是未生效請輸入 `make menuconfig` 搜尋 KPROBES 的其他相依性並啟用。 如果您在整合 KernelSU 之後手機無法啟動,那麼很可能您的核心中 **kprobe 無法正常運作**,您需要修正這個錯誤,或者使用第二種方法。 :::tip 如何檢查 kprobe 是否損毀? -將 `KernelSU/kernel/ksu.c` 中的 `ksu_enable_sucompat()` 和 `ksu_enable_ksud()` 取消註解,如果正常開機,即 kprobe 已損毀;或者您可以手動嘗試使用 kprobe 功能,如果不正常,手機會直接重新啟動。 +將 `KernelSU/kernel/ksu.c` 中的 `ksu_enable_sucompat()` 和 `ksu_enable_ksud()` 註解掉,如果正常開機,即 kprobe 已損毀;或者您可以手動嘗試使用 kprobe 功能,如果不正常,手機會直接重新啟動。 ::: :::info 如何為非 GKI 核心啟用卸載模組功能 -如果你的內核版本小於 5.10,你應該將 `path_umount` 向後移植至 `fs/namespace.c`。 卸載模組功能依賴於這個函數。 如果你沒有向後移植 `path_umount`,卸載模組功能將無法工作。 你可以在底下查看更多關於 `path_unmount` 的資料。 +如果你的內核版本小於 5.10,你應該將 `path_umount` 向後移植至 `fs/namespace.c`。卸載模組功能依賴於這個函數。如果你沒有向後移植 `path_umount`,卸載模組功能將無法工作。你可以在[這裡查看更多關於 `path_unmount` 的資料](#how-to-backport-path_unpount)。 ::: -## 手動修改核心原始碼 {#modify-kernel-source-code} +## 手動修改核心原始碼 {#manually-modify-the-kernel-source} -如果 kprobe 無法正常運作 (可能是上游的錯誤或核心版本過低),那您可以嘗試這種方法: +如果 kprobe 無法正常運作 (在4.8之前可能是上游或核心的錯誤),那您可以嘗試這種方法: -首先,將 KernelSU 新增至您的原始碼樹狀結構,再核心的根目錄執行以下命令: +首先,將 KernelSU 新增至您的原始碼樹狀結構,在核心的根目錄執行以下命令: ```sh -curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - +curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5 +``` +請記住,在某些裝置上,您的 `defconfig` 可能位於 `arch/arm64/configs` 中,或在其他情況下位於 `arch/arm64/configs/vendor/你的defconfig` 中。無論您使用哪個 `defconfig`,請確保使用 `CONFIG_KSU=y` 啟用KernelSU,或使用 `n` 停用它。例如,如果您選擇啟用它,則 `defconfig` 應包含以下字串: +```conf +# KernelSU +CONFIG_KSU=y ``` 然後,手動修改核心原始碼,您可以參閱下方的 patch: -```diff +::: code-group + +```diff[exec.c] diff --git a/fs/exec.c b/fs/exec.c index ac59664eaecf..bdd585e1d2cc 100644 --- a/fs/exec.c @@ -97,7 +94,7 @@ index ac59664eaecf..bdd585e1d2cc 100644 return __do_execve_file(fd, filename, argv, envp, flags, NULL); } ``` -```diff +```diff[open.c] diff --git a/fs/open.c b/fs/open.c index 05036d819197..965b84d486b8 100644 --- a/fs/open.c @@ -128,7 +125,7 @@ index 05036d819197..965b84d486b8 100644 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; ``` -```diff +```diff[read_write.c] diff --git a/fs/read_write.c b/fs/read_write.c index 650fc7e0f3a6..55be193913b6 100644 --- a/fs/read_write.c @@ -151,7 +148,7 @@ index 650fc7e0f3a6..55be193913b6 100644 return -EBADF; if (!(file->f_mode & FMODE_CAN_READ)) ``` -```diff +```diff[stat.c] diff --git a/fs/stat.c b/fs/stat.c index 376543199b5a..82adcef03ecc 100644 --- a/fs/stat.c @@ -175,6 +172,8 @@ index 376543199b5a..82adcef03ecc 100644 return -EINVAL; ``` +::: + 主要修改四個項目: 1. do_faccessat,通常位於 `fs/open.c` @@ -236,9 +235,11 @@ index 2ff887661237..e758d7db7663 100644 return -EINVAL; ``` +### 安全模式 {#safe-mode} + 若要啟用 KernelSU 內建的安全模式,您還需要修改 `drivers/input/input.c` 中的 `input_handle_event` 方法: -:::tip +:::tip 小建議 強烈建議啟用此功能,如果遇到開機迴圈,這將會非常有用! ::: @@ -266,9 +267,45 @@ index 45306f9ef247..815091ebfca4 100755 add_input_randomness(type, code, value); ``` +:::info 不小心進入安全模式? +如果您使用手動整合且不停用 `CONFIG_KPROBES`,那麼您將可能會在啟動後透過按下音量來減少按鈕來觸發安全模式!因此,如果使用手動集成,您需要停用 `CONFIG_KPROBES` ! +::: + +### 無法在終端中執行 `pm` ? {#failed-to-execute-pm-in-terminal} + +你應該修改 `fs/devpts/inode.c`,參考: + +```diff +diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c +index 32f6f1c68..d69d8eca2 100644 +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + return dentry; + } + ++#ifdef CONFIG_KSU ++extern int ksu_handle_devpts(struct inode*); ++#endif ++ + /** + * devpts_get_priv -- get private data for a slave + * @pts_inode: inode of the slave +@@ -610,6 +612,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + */ + void *devpts_get_priv(struct dentry *dentry) + { ++ #ifdef CONFIG_KSU ++ ksu_handle_devpts(dentry->d_inode); ++ #endif + if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC) + return NULL; + return dentry->d_fsdata; +``` + ### 如何向後移植 path_umount {#how-to-backport-path_unpount} -你可以透過向後移植 `path_umount` 來讓卸載模組功能在小於 5.10 的非 GKI 核心上運作. 你可以參考這個修改: +你可以透過向後移植 `path_umount` 來讓卸載模組功能在低於 5.10 的非 GKI 核心上運作。你可以參考這個修改: ```diff --- a/fs/namespace.c @@ -315,5 +352,4 @@ index 45306f9ef247..815091ebfca4 100755 * This is important for filesystems which use unnamed block devices. ``` - 最後,再次建置您的核心,KernelSU 將會如期運作。 diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/installation.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/installation.md index c0e0f32d3d6e..1d2e7a3d852f 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/installation.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/installation.md @@ -1,25 +1,25 @@ # 安裝 {#title} -## 檢查您的裝置是否受支援 {#check-if-supported} +## 檢查您的裝置是否受支援 {#check-if-your-device-is-supported} -從 [GitHub Releases](https://github.com/tiann/KernelSU/releases) 下載 KernelSU 管理器應用程式,然後將應用程式安裝至裝置並開啟: +從 [GitHub Releases](https://github.com/tiann/KernelSU/releases) 下載 KernelSU 管理器,然後安裝至裝置並開啟: -- 如果應用程式顯示「不支援」,則表示您的裝置不支援 KernelSU,您需要自行編譯核心才能繼續使用,,KernelSU 官方也永遠不會為您提供一個可以刷新的 Boot 映像。 -- 如果應用程式顯示「未安裝」,那麼 KernelSU 支援您的裝置;可以進行下一步作業。 +- 如果顯示「不支援」,則表示您的裝置不支援 KernelSU,您需要自行編譯核心才能繼續使用,KernelSU 官方也永遠不會提供一個您可以寫入的 Boot 映像。 +- 如果顯示「未安裝」,那麼 KernelSU 支援您的裝置。 -:::info +::: info 提示 對於顯示「不支援」的裝置,這裡有一個[非官方支援裝置清單](unofficially-support-devices.md),您可以使用這個清單裡的核心自行編譯。 ::: -## 備份您的原廠 boot.img {#backup-boot-image} +## 備份您的原廠 boot.img {#backup-stock-boot-img} -在進行刷新作業前,您必須預先備份您的原廠 boot.img。如果您在後續刷新作業中出現了任何問題,您都可以透過使用 Fastboot 刷新回到原廠 Boot 以還原系統。 +在寫入核心映像前,您必須預先備份您的原廠 boot.img。如果您在後續寫入中出現了任何問題,您都可以透過使用 Fastboot 寫回原廠 Boot 以還原系統。 -::: warning -刷新作業可能會造成資料遺失,請確保做好這一步再繼續進行下一步作業!!必要時您還可以備份您手機的所有資料。 +::: warning 警告 +寫入核心映像可能會造成資料遺失,請確保做好這一步再繼續進行下一步作業!!必要時您還可以備份您手機的所有資料。 ::: -## 必要知識 {#acknowage} +## 必要知識 {#necessary-knowledge} ### ADB 和 Fastboot {#adb-and-fastboot} @@ -27,9 +27,9 @@ ### KMI -KMI 全稱 Kernel Module Interface,相同 KMI 的核心版本是**相容的** 這也是 GKI 中「標準」的涵義所在;反之,如果 KMI 不同,那麼這些核心之間無法彼此相容,刷新與您裝置 KMI 不同的核心映像可能會導致開機迴圈。 +KMI 全稱 Kernel Module Interface,相同 KMI 的核心版本是**相容的**,這也是 GKI 中「標準」的涵義所在。反之,如果 KMI 不同,那麼這些核心之間無法彼此相容,寫入與您裝置 KMI 不同的核心映像可能會導致無法開機。 -具體來講,對 GKI 的裝置,其核心版本格式應該如下: +具體來講,對於 GKI 的裝置,其核心版本格式應該如下: ```txt KernelRelease := @@ -37,21 +37,27 @@ Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix w .x .y -zzz -k -something ``` -其中,`w.x-zzz-k` 為 KMI 版本。例如,一部裝置核心版本為 `5.10.101-android12-9-g30979850fc20`,那麼它的 KMI 為 `5.10-android12-9`;理論上刷新其他這個 KMI 的核心也能正常開機。 +其中,`w.x-zzz-k` 為 KMI 版本。例如,一部裝置核心版本為 `5.10.101-android12-9-g30979850fc20`,那麼它的 KMI 為 `5.10-android12-9`,理論上寫入其他這個 KMI 的核心也能正常開機。 -::: tip +::: tip 補充 請注意,核心版本中的 SubLevel 並非 KMI 的一部分!也就是說 `5.10.101-android12-9-g30979850fc20` 與 `5.10.137-android12-9-g30979850fc20` 的 KMI 相同! ::: +### 安全性修補程式等級 {#security-patch-level} + +較新的 Android 裝置可能具有防回滾機制,不允許寫入具有較舊安全性修補程式等級的啟動映像。例如,如果您的裝置核心為 `5.10.101-android12-9-g30979850fc20`,則其安全修補程式等級為 `2023-11`;即使寫入了 KMI 對應的核心,如果安全修補程式等級早於 `2023-11`(例如 `2023-06`),也可能會導致無法開機。 + +因此,最好使用具有最新安全性修補程式等級的核心來維護與 KMI 的對應關係。 + ### 核心版本與 Android 版本 {#kernel-version-vs-android-version} 請注意:**核心版本與 Android 版本並不一定相同!** -如果您發現您的核心版本是 `android12-5.10.101`,然而您 Android 系統的版本為 Android 13 或者其他;請不要覺得奇怪,因為 Android 系統的版本與 Linux 核心的版本號碼並非一致;Linux 核心的版本號碼一般與**裝置出廠時隨附的 Android 系統的版本一致**,如果後續 Android 系統更新,核心版本一般不會發生變化。如果您需要刷新,**請以核心版本為準!!** +如果您發現您的核心版本是 `android12-5.10.101`,然而您 Android 系統的版本為 Android 13 或更高,請不要覺得奇怪,因為 Android 系統的版本與 Linux 核心的版本號碼並非一致。Linux 核心的版本號碼一般與**裝置出廠時隨附的 Android 系統的版本一致**,如果後續 Android 系統更新,核心版本一般不會發生變化。如果您需要寫入,**請以核心版本為準!!** ## 安裝簡介 {#introduction} -自 `0.9.0` 版本以後,在 GKI 裝置中,KernelSU 支援兩種運行模式: +自 `0.9.0` 版本以後,在 GKI 裝置上,KernelSU 支援兩種運作模式: 1. `GKI`:使用**通用核心鏡像**(GKI)取代掉裝置原有的核心。 2. `LKM`:使用**可載入核心模組**(LKM)的方式載入到裝置核心中,不會替換掉裝置原有的核心。 @@ -60,55 +66,56 @@ w .x .y -zzz -k -something ### GKI 模式 {#gki-mode} -GKI 模式會替換掉裝置原有的內核,使用 KernelSU 提供的通用內核鏡像。 GKI 模式的優點是: +GKI 模式會替換掉裝置原有的核心,使用 KernelSU 提供的通用核心鏡像。 GKI 模式的優點是: -1. 通用型強,適用於大多數裝置;例如三星開啟了 KNOX 的裝置,LKM 模式無法運作。還有一些冷門的魔改裝置,也只能使用 GKI 模式; -2. 不依賴官方韌體即可使用;不需要等待官方韌體更新,只要 KMI 一致,就可以使用; +1. 通用型高,適用於大多數裝置;例如開啟了 KNOX 的三星裝置、或是 LKM 模式無法運作的裝置。還有一些冷門的魔改裝置,也只能使用 GKI 模式。 +2. 不依賴官方韌體即可使用;不需要等待官方韌體更新,只要 KMI 一致,就可以使用。 ### LKM 模式 {#lkm-mode} -LKM 模式不會替換掉裝置原有的內核,而是使用可載入內核模組的方式載入到裝置內核中。 LKM 模式的優點是: +LKM 模式不會替換掉裝置原有的核心,而是使用可載入核心模組的方式載入到裝置核心中。 LKM 模式的優點是: -1. 不會取代裝置原有的核心;如果你對裝置原有的核心有特殊需求,或是你希望在使用第三方核心的同時使用 KernelSU,可以使用 LKM 模式; -2. 升級和 OTA 較為方便;升級 KernelSU 時,可以直接在管理器內部安裝,無需再手動刷寫;系統 OTA 後,可以直接安裝到第二個槽位,也無需再手動刷寫; -3. 適用於一些特殊場景;例如使用臨時 ROOT 權限也可以載入 LKM,由於不需要替換 boot 分區,因此不會觸發 avb,不會使裝置意外變磚; -4. LKM 可以被暫時卸載;如果你暫時想取消 root,可以卸載 LKM,這個過程不需要刷寫分區,甚至也不用重啟裝置;如果你想再次 root,只需要重啟裝置即可; +1. 不會取代裝置原有的核心:如果你對裝置原有的核心有特殊需求,或是你希望在使用第三方核心的同時使用 KernelSU,可以使用 LKM 模式。 +2. 升級和 OTA 較為方便:升級 KernelSU 時,可以直接在管理器內部安裝,無需再手動寫入;系統 OTA 後,可以直接安裝到第二個槽位,也無需再手動寫入。 +3. 適用於一些特殊場景:例如使用臨時 root 權限也可以載入 LKM,由於不需要替換 boot 分區,因此不會觸發 avb,不會使裝置意外變磚。 +4. LKM 可以被暫時卸載:如果你暫時想取消 root,可以卸載 LKM,這個過程不需要寫入分區,甚至也不用重啟裝置。如果你想重新取得 root,只需要重啟裝置即可。 :::tip 兩種模式共存 -打開管理器後,你可以在首頁看到裝置目前運行的模式;注意 GKI 模式的優先級高於 LKM ,如你你既使用 GKI 內核替換掉了原有的內核,又使用 LKM 的方式修補了 GKI 內核,那麼 LKM 會被忽略,裝置將永遠以 GKI 的模式運作。 +打開管理器後,你可以在首頁看到裝置目前運行的模式。注意 GKI 模式的優先級高於 LKM ,如你既使用 GKI 核心替換掉了原有的核心,又使用 LKM 的方式修補了 GKI 核心,那麼 LKM 會被忽略,裝置將永遠以 GKI 的模式運作。 ::: ### 選哪個? {#which-one} -如果你的裝置是手機,我們建議您優先考慮 LKM 模式;如果你的裝置是模擬器、WSA 或 Waydroid 等,我們建議您優先考慮 GKI 模式。 +如果你的裝置是手機,我們建議您優先考慮 LKM 模式。 +如果你的裝置是模擬器、WSA 或 Waydroid 等,我們建議您優先考慮 GKI 模式。 ## LKM 安裝 {#lkm-installation} ### 取得官方韌體 {#get-the-official-firmware} -使用 LKM 的模式,需要取得官方韌體,然後在官方韌體的基礎上修補;如果你使用的是第三方內核,可以把第三方內核的 boot.img 作為官方韌體。 +使用 LKM 的模式,需要取得官方韌體,然後在官方韌體的基礎上修補;如果你使用的是第三方核心,可以把第三方核心的 boot.img 作為官方韌體。 -取得官方韌體的方法有很多,如果你的裝置支援 `fastboot boot`,那麼我們最推薦以及最簡單的方法是使用 `fastboot boot` 臨時啟動 KernelSU 提供的 GKI 內核,然後安裝管理器,最後在管理器中直接安裝;這種方法不需要你手動下載官方韌體,也不需要你手動提取 boot。 +取得官方韌體的方法有很多,如果你的裝置支援 `fastboot boot`,那麼我們最推薦以及最簡單的方法是使用 `fastboot boot` 臨時啟動 KernelSU 提供的 GKI 核心,並參考[使用管理器](#use-the-manager)安裝。 如果你的裝置不支援 `fastboot boot`,那麼你可能需要手動去下載官方韌體包,然後從中提取 boot。 -與 GKI 模式不同,LKM 模式會修改 `ramdisk`,因此在出廠 Android 13 的裝置上,它需要修補的是 `init_boot` 分區而非 `boot` 分區;而 GKI 模式則永遠是操作 `boot` 分區。 +與 GKI 模式不同,LKM 模式會修改 `ramdisk`,因此在出廠 Android 13 的裝置上,通常它需要修補的是 `init_boot` 分區而非 `boot` 分區;而 GKI 模式則永遠是修改 `boot` 分區。 ### 使用管理器 {#use-the-manager} 開啟管理器,點選右上角的安裝圖標,會出現若干個選項: -1. 選擇並修補一個文件:如果你手機目前沒有 root 權限,你可以選擇這個選項,然後選擇你的官方韌體,管理器會自動修補它;你只需要刷入這個修補後的文件,即可永久取得 root 權限; -2. 直接安裝:如果你手機已經 root,你可以選擇這個選項,管理器會自動獲取你的裝置資訊,然後自動修補官方韌體,然後刷入;你可以考慮使用`fastboot boot` KernelSU 的 GKI 內核來取得臨時 root 安裝管理器,然後再使用這個選項;這種方式也是 KernelSU 升級最主要的方式; -3. 安裝到另一個分割區:如果你的裝置支援 A/B 分割區,你可以選擇這個選項,管理器會自動修補官方韌體,然後安裝到另一個分割區;這種方式適用於 OTA 後的裝置,你可以在 OTA 後直接安裝到另一個分割區,然後重新啟動裝置即可; +1. 選擇並修補一個文件:如果你手機目前沒有 root 權限,你可以選擇這個選項,然後選擇你的官方韌體,管理器會自動修補它。你只需要寫入這個修補後的文件,即可永久取得 root 權限。 +2. 直接安裝:如果你手機已經 root,你可以選擇這個選項,管理器會自動獲取你的裝置資訊,然後自動修補官方韌體,然後寫入。你可以考慮使用 `fastboot boot` KernelSU 的 GKI 核心來取得臨時 root 安裝管理器,然後再使用這個選項。**這種方式也是 KernelSU 升級最主要的方式**。 +3. 安裝到另一個分割區:如果你的裝置支援 A/B 分區,你可以選擇這個選項,管理器會自動修補官方韌體,然後安裝到另一個分區。這種方式適用於 OTA 後的裝置,你可以在 OTA 後直接安裝到另一個分割區,然後重新啟動裝置即可。 -### 使用命令列 +### 使用命令列{#use-the-command-line} -如果你不想使用管理器,你也可以使用命令列來安裝 LKM;KernelSU 提供的 `ksud` 工具可以幫助你快速修補官方韌體,然後刷入。 +如果你不想使用管理器,你也可以使用命令列來安裝 LKM。KernelSU 提供的 `ksud` 可以幫助你快速修補官方韌體,然後寫入。 這個工具支援 macOS、Linux 和 Windows,你可以在 [GitHub Release](https://github.com/tiann/KernelSU/releases) 下載對應的版本。 -使用方法:`ksud boot-patch` 具體的使用方法你可以查看命令列幫助。 +使用方法:`ksud boot-patch`。 你可以查看命令列的提示了解具體的使用方法。 ```sh husky:/ # ksud boot-patch -h @@ -129,126 +136,130 @@ Options: -h, --help Print help ``` 需要說明的幾個選項: -1. `--magiskboot` 選項可以指定 magiskboot 的路徑,如果不指定,ksud 會在環境變數中尋找;如果你不知道如何取得 magiskboot,可以參考[這裡](#patch-boot-image); -2. `--kmi` 選項可以指定 `KMI` 版本,如果你的裝置核心名字沒有遵循 KMI 規範,你可以透過這個選項來指定; +1. `--magiskboot` 選項可以指定 magiskboot 的路徑,如果不指定,ksud 會在環境變數中尋找。如果你不知道如何取得 magiskboot,可以參考[這裡](#patch-boot-image)。 +2. `--kmi` 選項可以指定 `KMI` 版本,如果你的裝置核心名字沒有遵循 KMI 規範,你可以透過這個選項來指定。 + 最常見的使用方法為: ```sh ksud boot-patch -b --kmi android13-5.10 ``` -## GKI 安裝 +## GKI 安裝{#gki-mode-installation} GKI 的安裝方式有以下幾種,各自適用於不同的場景,請依需求選擇: -1. 使用自訂 Recovery (如 TWRP) 安裝 -2. 使用核心刷新應用程式 (例如 Franco Kernel Manager) 安裝 -3. 使用 KernelSU 提供的 boot.img 透過 Fastboot 安裝 +1. 使用 KernelSU 提供的 boot.img 透過 Fastboot 安裝 +2. 使用核心寫入程式 (例如 KernelFlasher) 安裝 +3. 使用自訂 Recovery (例如 TWRP) 安裝 4. 手動修補 boot.img 並安裝 -## 使用自訂 Recovery 安裝 {#install-by-recovery} - -先決條件:您的裝置必須有自訂的 Recovery,例如 TWRP;如果沒有或者只有官方 Recovery,請使用其他方法。 - -步驟: - -1. 在 KernelSU 的 [Release 頁面](https://github.com/tiann/KernelSU/releases) 下載與您手機版本相符的以 AnyKernel3 開頭的 Zip 套件;例如,手機核心版本為 `android12-5.10.66`,那麼您應該下載 `AnyKernel3-android12-5.10.66_yyyy-MM.zip` 這個檔案 (其中 `yyyy` 為年份,`MM` 為月份)。 -2. 重新開機手機至 TWRP。 -3. 使用 Adb 將 AnyKernel3-*.zip 放置到手機 /sdcard 然後在 TWRP 圖形使用者介面選擇並安裝;或者您也可以直接 `adb sideload AnyKernel-*.zip` 安裝。 - -PS. 這種方法適用於任何狀況下的安裝 (不限於初次安裝或後續更新),只要您用 TWRP 就可以進行作業。 - -## 使用核心刷新應用程式安裝 {#install-by-kernel-flasher} - -先決條件:您的裝置必須已經 Root。例如您已經安裝了 Magisk 並取得 Root 存取權,或者您已經安裝了舊版本的 KernelSU 需升級到其他版本的 KernelSU;如果您的裝置並未 Root,請嘗試其他方法。 - -步驟: - -1. 下載 AnyKernel3 的 Zip 檔案;請參閱 *使用自訂 Recovery 安裝* 章節的内容。 -2. 開啟核心刷新應用程式提供的 AnyKernel3 Zip 檔案進行刷新。 - -如果您先前並未使用過核心刷新應用程式,可以嘗試下面幾個方法: - -1. [Kernel Flasher](https://github.com/capntrips/KernelFlasher/releases) -2. [Franco Kernel Manager](https://play.google.com/store/apps/details?id=com.franco.kernel) -3. [Ex Kernel Manager](https://play.google.com/store/apps/details?id=flar2.exkernelmanager) - -PS. 這種方法在更新 KernelSU 時比較方便,無需電腦即可完成 (注意備份!)。 - ## 使用 KernelSU 提供的 boot.img 安裝 {#install-with-boot-img-provided-by-kernelsu} -這種方法無需您有 TWRP,也無需您的手機有 Root 權限;適用於您初次安裝 KernelSU。 +如果你的裝置的 `boot.img` 使用常見的壓縮格式,你可以直接寫入 KernelSU 提供的 GKI 核心映像,這種方法無需 TWRP,也無需您的手機有 Root 權限;適用於您初次安裝 KernelSU。 ### 找到合適的 boot.img {#find-proper-boot-img} -KernelSU 為 GKI 裝置提供了標準 boot.img,您需要將 boot.img 刷新至裝置的 Boot 分割區。 +KernelSU 為 GKI 裝置提供了標準 boot.img,您需要將 boot.img 寫入至裝置的 Boot 分區。 -您可以從 [GitHub Release](https://github.com/tiann/KernelSU/releases) 下載 boot.img,請注意,您應該使用正確版本的 boot.img。例如,如果您的裝置顯示核心是 `android12-5.10.101`,需要下載 `android-5.10.101_yyyy-MM.boot-.img`. +您可以從 [GitHub Release](https://github.com/tiann/KernelSU/releases) 下載 boot.img,請注意,您應該使用正確版本的 boot.img。如果你不知道你該下載哪個檔案,請詳細閱讀文檔中的 [KMI](#kmi) 與[安全性修補程式等級](#security-patch-level)。 -其中 `` 指的是您的官方 boot.img 的核心壓縮格式,請檢查您原有 boot.img 的核心壓縮格式,您應該使用正確的格式,例如 `lz4`、`gz`;如果使用不正確的壓縮格式,刷新 Boot 後可能無法開機。 +通常,在相同的 KMI 和安全性修補程式等級下,會存在三種不同格式的啟動檔案。除了核心壓縮格式之外,它們都是相同的。請檢查您原來的 boot.img 的核心壓縮格式。您應該使用正確的格式,例如 `lz4` 、 `gz`,如果你使用了不正確的壓縮格式,你可能會在寫入後無法開機。 -::: info -1. 您可以透過 magiskboot 以取得您的原始 Boot 的壓縮格式;當然,您也可以詢問與您相同型號的其他更有經驗的使用者。另外,核心的壓縮格式通常部會出現變更,如果您使用的某個壓縮格式成功開機,後續可以優先嘗試這個格式。 +::: info 關於 boot.img 的壓縮格式 +1. 您可以透過 magiskboot 以取得您的原始 Boot 的壓縮格式。當然,您也可以詢問與您相同型號的其他更有經驗的使用者。另外,核心的壓縮格式通常不會出現變更,如果您使用的某個壓縮格式成功開機,後續可以優先嘗試這個格式。 2. 小米裝置通常 `gz` 或者 **不壓縮**。 3. Pixel 裝置有些特殊,請遵循下方的指示。 ::: -### 將 boot.img 刷新至裝置 {#flash-boot-img-to-device} +### 將 boot.img 寫入至裝置 {#flash-boot-img-to-device} -使用 `adb` 連接您的裝置,然後執行 `adb reboot bootloader` 進入 fastboot 模式,然後使用此命令刷新 KernelSU: +使用 `adb` 連接您的裝置,然後執行 `adb reboot bootloader` 進入 fastboot 模式,然後使用此命令寫入 KernelSU: ```sh fastboot flash boot boot.img ``` -::: info -如果您的裝置支援 `fastboot boot`,可以先使用 `fastboot boot boot.img` 來先嘗試使用 boot.img 開機進入系統,如果出現意外,重新啟動即可開機。 +::: info 提示 +如果您的裝置支援 `fastboot boot`,可以先使用 `fastboot boot boot.img` 來嘗試使用 boot.img 開機進入系統,如果出現意外,重新啟動即可開機。 ::: ### 重新開機 {#reboot} -刷新完成後,您應該重新啟動您的裝置: +寫入完成後,您應該重新啟動您的裝置: ```sh fastboot reboot ``` +## 使用核心寫入程式安裝 {#install-with-kernel-flasher} + +先決條件:您的裝置必須已經 Root。例如您已經安裝了 Magisk 並取得 Root 存取權,或者您已經安裝了舊版本的 KernelSU 需升級到其他版本的 KernelSU;如果您的裝置並未 Root,請嘗試其他方法。 + +步驟: + +1. 下載 AnyKernel3 的 Zip 檔。如果你不知道你該下載哪個檔案,請詳細閱讀文檔中的 [KMI](#kmi) 與[安全性修補程式等級](#security-patch-level)。 +2. 開啟核心寫入程式提供的 AnyKernel3 Zip 檔案並寫入核心。 + +如果您先前並未使用過核心寫入應用程式,可以嘗試下面幾個: + +1. [Kernel Flasher](https://github.com/capntrips/KernelFlasher/releases) +2. [Franco Kernel Manager](https://play.google.com/store/apps/details?id=com.franco.kernel) +3. [Ex Kernel Manager](https://play.google.com/store/apps/details?id=flar2.exkernelmanager) + +P.S. 這種方法在更新 KernelSU 時比較方便,無需電腦即可完成 (注意備份!)。 + ## 手動修補 boot.img {#patch-boot-image} -對於某些裝置來說,其 boot.img 格式並不是很常見,比如 `lz4`,`gz` 和未壓縮;最典型的就是 Pixel,它的 boot.img 格式是 `lz4_legacy` 壓縮,ramdisk 可能是 `gz` 也可能是 `lz4_legacy` 壓縮;此時如果您直接刷新 KernelSU 提供的 boot.img,手機可能無法開機;這時,您可以透過手動修補 boot.img 來完成。 +對於某些裝置來說,其 boot.img 格式並不是很常見,不屬於 `lz4`,`gz` 和未壓縮;最典型的就是 Pixel,它的 boot.img 格式是 `lz4_legacy` 壓縮,ramdisk 可能是 `gz` 也可能是 `lz4_legacy` 壓縮;此時如果您直接寫入 KernelSU 提供的 boot.img,手機可能無法開機。這時,您可以透過手動修補 boot.img 來完成。 -一般有兩種修補方法: +永遠建議使用 `magiskboot` 來修補映像,一般有兩種修補方法: -1. [Android-Image-Kitchen](https://forum.xda-developers.com/t/tool-android-image-kitchen-unpack-repack-kernel-ramdisk-win-android-linux-mac.2073775/) -2. [magiskboot](https://github.com/topjohnwu/Magisk/releases) +1. [magiskboot](https://github.com/topjohnwu/Magisk/releases) +2. [magiskboot_build](https://github.com/ookiineko/magiskboot_build/releases/tag/last-ci) -其中,Android-Image-Kitchen 適用於在電腦上作業,magiskboot 需要手機協作。 +其中,官方的 `magiskboot` 僅能在 Android 上使用,若您想在電腦上完成,可以嘗試第二個選項。 -### 準備 {#patch-preparation} +### 準備 {#preparation} -1. 取得您手機的原廠 boot.img;您可以聯絡您的裝置製造商,您也可能需要[payload-dumper-go](https://github.com/ssut/payload-dumper-go) -2. 下載 KernelSU 提供的與您的裝置 KMI 一致地 AnyKernel3 Zip 檔案 (可參閱 *使用自訂 Recovery 安裝*)。 -3. 解壓縮 AnyKernel3 Zip 檔案,取得其中的 `Image` 檔案,此檔案為 KernelSU 的核心檔案。 +1. 取得您手機的原廠 boot.img,您可以從您的裝置製造商取得,您也可能需要 [payload-dumper-go](https://github.com/ssut/payload-dumper-go)。 +2. 下載 KernelSU 提供的與您的裝置 KMI 一致的 AnyKernel3 Zip 檔 (可參閱[使用自訂 Recovery 安裝](#install-with-custom-recovery))。 +3. 解壓縮 AnyKernel3 Zip 檔,取得其中的 `Image` 檔,此檔案為具有 KernelSU 的核心。 -### 使用 Android-Image-Kitchen {#using-android-image-kitchen} +### 在 Android 上使用 magiskboot {#using-magiskboot-on-Android-devices} -1. 下載 Android-Image-Kitchen 至您的電腦。 -2. 將手機原廠 boot.img 放置於 Android-Image-Kitchen 根目錄。 -3. 在 Android-Image-Kitchen 根目錄執行 `./unpackimg.sh boot.img`;此命令會將 boot.img 解除封裝,您會得到一些檔案。 -4. 將 `split_img` 目錄中的 `boot.img-kernel` 取代為您從 AnyKernel3 解壓縮出來的 `Image` (注意名稱變更為 boot.img-kernel)。 -5. 在 Android-Image-Kitchecn 根目錄執行 `./repackimg.sh`;此時您會得到一個 `image-new.img` 檔案;使用此 boot.img 透過 fastboot 刷新即可 (刷新方法請參閱上一章節)。 - -### 使用 magiskboot {#using magiskboot} - -1. 在 Magisk 的 [Release 頁面](https://github.com/topjohnwu/Magisk/releases) 下載最新的 Magisk 安裝套件。 -2. 將 `Magisk-*(version).apk` 重新命名為 `Magisk-*.zip` 然後解壓縮。 -3. 將解壓縮後的 `Magisk-*/lib/arm64-v8a/libmagiskboot.so` 檔案,使用 Adb 推入至手機:`adb push Magisk-*/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot` +1. 在 Magisk 的 [Release 頁面](https://github.com/topjohnwu/Magisk/releases) 下載最新的 Magisk。 +2. 將 `Magisk-*(version).apk` 重新命名為 `Magisk-*.zip` 並解壓縮。 +3. 使用 Adb 將 magiskboot 推入至手機:`adb push Magisk-*/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot`。 4. 使用 Adb 將原廠 boot.img 和 AnyKernel3 中的 Image 推入至手機。 -5. adb shell 進入 /data/local/tmp/ 目錄,然後賦予先前推入檔案的可執行權限 `chmod +x magiskboot` +5. adb shell 進入 /data/local/tmp/ 目錄,然後賦予先前推入的檔案可執行權限 `chmod +x magiskboot`。 6. adb shell 進入 /data/local/tmp/ 目錄,執行 `./magiskboot unpack boot.img` 此時會將 `boot.img` 解除封裝,得到一個名為 `kernel` 的檔案,這個檔案是您的原廠核心。 7. 使用 `Image` 取代 `kernel`: `mv -f Image kernel` -8. 執行 `./magiskboot repack boot.img` 重新封裝 img,此時您會得到一個 `new-boot.img` 檔案,透過 Fastboot 將這個檔案刷新至裝置即可。 +8. 執行 `./magiskboot repack boot.img` 重新封裝映像,此時您會得到一個 `new-boot.img` 檔案,透過 Fastboot 將這個檔案寫入至裝置即可。 + +### 在 Windows/macOS/Linux PC 上使用 magiskboot {#using-magiskboot-on-PC} + +1. 在 [magiskboot_build](https://github.com/ookiineko/magiskboot_build/releases/tag/last-ci) 下載對應的 magiskboot。 +2. (僅linux)賦予檔案可執行權限 `chmod +x magiskboot`。 +3. 執行 `./magiskboot unpack boot.img` 此時會將 `boot.img` 解除封裝,得到一個名為 `kernel` 的檔案,這個檔案是您的原廠核心。 +4. 使用 `Image` 取代 `kernel`: `mv -f Image kernel` +5. 執行 `./magiskboot repack boot.img` 重新封裝映像,此時您會得到一個 `new-boot.img` 檔案,透過 Fastboot 將這個檔案寫入至裝置即可。 + +## 使用自訂 Recovery 安裝 {#install-with-custom-recovery} + +先決條件:您的裝置必須有自訂的 Recovery,例如 TWRP。如果沒有或者只有官方 Recovery,請使用其他方法。 + +步驟: + +1. 在 KernelSU 的 [Release 頁面](https://github.com/tiann/KernelSU/releases) 下載與您手機版本相符的以 AnyKernel3 開頭的 Zip 檔;例如,手機核心版本為 `android12-5.10.66`,那麼您應該下載 `AnyKernel3-android12-5.10.66_yyyy-MM.zip` 這個檔案 (其中 `yyyy` 為年份,`MM` 為月份)。 +2. 重新開機手機至 TWRP。 +3. 使用 Adb 將 AnyKernel3-*.zip 放置到手機 `/sdcard` 然後在 TWRP 圖形使用者介面選擇並安裝;或者您也可以直接 `adb sideload AnyKernel-*.zip` 安裝。 + +PS. 這種方法適用於任何狀況下的安裝 (不限於初次安裝或後續更新),只要您用 TWRP 就可以進行作業。 ## GKI的其他替代方法 {#other-methods} -其實所有這些安裝方法的主旨只有一個,那就是**將原廠核心取代為 KernelSU 提供的核心**;只要能實現這個目的,就可以安裝;比如以下是其他可行的方法: +其實所有這些安裝方法的主旨只有一個,那就是**將原廠核心取代為 KernelSU 提供的核心**。只要能實現這個目的,就可以安裝,比如以下是其他可行的方法: + +1. 首先安裝 Magisk,透過 Magisk 取得 Root 權限後使用核心寫入程式寫入 KernelSU 的 AnyKernel Zip。 +2. 使用某些 PC 上的寫入工具組寫入 KernelSU 提供的核心。 + +但是,如果不起作用,請嘗試 Magiskboot 方法。 -1. 首先安裝 Magisk,透過 Magisk 取得 Root 權限後使用核心刷新程式刷新 KernelSU 的 AnyKernel Zip。 -2. 使用某些 PC 上的刷新工具組刷新 KernelSU 提供的核心。 diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/module-webui.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/module-webui.md index 5dbdaf7826f2..671faad7a153 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/module-webui.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/module-webui.md @@ -2,11 +2,11 @@ KernelSU 的模組除了執行啟動腳本和修改系統檔案之外,還支援顯示 UI 介面和與使用者互動。 -該模組可以透過任何 Web 技術編寫HTML + CSS + JavaScript頁面。 KernelSU的管理器將透過 WebView 顯示這些頁面。它還提供了一些用於與系統互動的JavaScript API,例如執行shell命令。 +該模組可以透過任何 Web 技術編寫 HTML + CSS + JavaScript 頁面。 KernelSU的管理器將透過 WebView 顯示這些頁面。它還提供了一些用於與系統互動的 JavaScript API,例如執行 shell 命令。 ## WebUI 根目錄 {#webroot-directory} -Web資源應放置在模組根目錄的`webroot`子目錄中,並且其中**必須**有一個名為`index.html`的文件,該檔案是模組頁面入口。 +Web資源應放置在模組根目錄的 `webroot` 子目錄中,並且其中**必須**有一個名為 `index.html` 的文件,該檔案是模組頁面入口。 包含Web介面的最簡單的模組結構如下: @@ -18,7 +18,7 @@ Web資源應放置在模組根目錄的`webroot`子目錄中,並且其中**必 `-- index.html ``` -:::warning +:::warning 提醒 安裝模組時,KernelSU 將自動設定`webroot`的權限和 SELinux context。如果您不知道自己在做什麼,請不要自行設定該目錄的權限! ::: @@ -28,7 +28,7 @@ Web資源應放置在模組根目錄的`webroot`子目錄中,並且其中**必 如果只是一個顯示頁面,那和一般網頁沒有什麼不同。更重要的是,KernelSU 提供了一系列的系統 API,讓您可以實現模組獨特的功能。 -KernelSU 提供了一個 JavaScript 庫並[在 npm 上發布](https://www.npmjs.com/package/kernelsu),您可以在網頁的 JavaScript 程式碼中使用它。 +KernelSU [在 npm 上發布](https://www.npmjs.com/package/kernelsu)了一個 JavaScript 庫,您可以在網頁的 JavaScript 程式碼中使用它。 例如,您可以執行 shell 命令來取得特定配置或修改屬性: @@ -42,8 +42,9 @@ const { errno, stdout } = exec("getprop ro.product.model"); [API 文檔](https://www.npmjs.com/package/kernelsu) -如果您發現現有的API無法滿足您的需求或使用不方便,歡迎您在[這裡](https://github.com/tiann/KernelSU/issues)給我們建議! -## 一些技巧 +如果您發現現有的 API 無法滿足您的需求或使用不方便,歡迎您在[這裡](https://github.com/tiann/KernelSU/issues)給我們建議! -1. 您可以正常使用`localStorage`來儲存一些數據,但卸載管理器後,這些數據將會遺失。如果需要持久保存,可以自行將資料寫入某個目錄。 -2. 對於簡單的頁面,我建議您使用[parceljs](https://parceljs.org/)進行打包。它無須設定,使用非常方便。不過,如果你是前端高手或有自己的喜好,那就選擇你喜歡的吧! +## 一些技巧 {#some-tips} + +1. 您可以正常使用 `localStorage` 來儲存一些數據,但解除安裝管理器後,這些數據將會遺失。如果需要持久保存,可以自行將資料寫入某個目錄。 +2. 對於簡單的頁面,我建議您使用 [parceljs](https://parceljs.org/) 進行打包。它無須設定,使用非常方便。不過,如果你是前端高手或有自己的喜好,那就選擇你喜歡的吧! diff --git a/drivers/staging/kernelsu/website/docs/zh_TW/guide/module.md b/drivers/staging/kernelsu/website/docs/zh_TW/guide/module.md index 717c862890ec..dac0fec6c3ee 100644 --- a/drivers/staging/kernelsu/website/docs/zh_TW/guide/module.md +++ b/drivers/staging/kernelsu/website/docs/zh_TW/guide/module.md @@ -1,8 +1,8 @@ -# 模組指南 {#introduction} +# 模組指南 {#module-guide} -KernelSU 提供了一個模組機制,它可以在保持系統分割區完整性的同時達到修改系統分割區的效果;這種機制一般被稱為 systemless。 +KernelSU 提供了一個模組機制,它可以在保持系統分割區完整性的同時達到修改系統分割區的效果;這種機制一般被稱為 systemless (無系統修改)。 -KernelSU 的模組運作機制與 Magisk 幾乎相同,如果您熟悉 Magisk 模組的開發,那麼開發 KernelSU 的模組大同小異,您可以跳過下列有關模組的介紹,只需要瞭解 [KernelSU 模組與 Magisk 模組的異同](difference-with-magisk.md)。 +KernelSU 的模組運作機制與 Magisk 幾乎相同,如果您熟悉 Magisk 模組的開發,那麼開發 KernelSU 的模組大同小異,您可以跳過下列有關模組的介紹,只需要瞭解 [KernelSU 模組與 Magisk 模組的差異](difference-with-magisk.md)。 ## WebUI @@ -11,20 +11,20 @@ KernelSU 的模組支援顯示互動介面,請參閱 [WebUI 文檔](module-web ## Busybox KernelSU 提供了一個完備的 BusyBox 二進位檔案 (包括完整的 SELinux 支援)。可執行檔位於 `/data/adb/ksu/bin/busybox`。 -KernelSU 的 BusyBox 支援同時執行時可切換的 "ASH Standalone Shell Mode"。 -這種讀了模式意味著在執行 BusyBox 的 ash shell 時,每個命令都會直接使用 BusyBox 中內建的應用程式,而不論 PATH 的設定為何。 -例如,`ls`、`rm`、`chmod` 等命令將不會使用 PATH 中設定的命令 (在 Android 的狀況下,預設狀況下分別為 `/system/bin/ls`、`/system/bin/rm` 和 `/system/bin/chmod`),而是直接呼叫 BusyBox 內建的應用程式。 +KernelSU 的 BusyBox 支援執行時可切換的 "ASH 獨立模式"。 +ASH 獨立模式在執行 BusyBox 時,每個命令都會直接使用 BusyBox 中內建的應用程式,而不論 `PATH` 的設定為何。 +例如,`ls`、`rm`、`chmod` 等命令將不會使用 `PATH` 中設定的命令 (在 Android 的狀況下,預設狀況下分別為 `/system/bin/ls`、`/system/bin/rm` 和 `/system/bin/chmod`),而是直接呼叫 BusyBox 內建的應用程式。 這確保了腳本始終在可預測的環境中執行,並始終具有完整的命令套件,不論它執行在哪個 Android 版本上。 要強制下一個命令不使用 BusyBox,您必須使用完整路徑呼叫可執行檔。 -在 KernelSU 上下文中執行的每個 shell 腳本都將在 BusyBox 的 ash shell 中以獨立模式執行。對於第三方開發人員相關的內容,包括所有開機腳本和模組安裝腳本。 +每個基於 KernelSU 上下文的腳本都將在 BusyBox 的獨立模式執行。對於第三方開發人員而言,這包括所有開機腳本和模組安裝腳本。 對於想要在 KernelSU 之外使用這個「獨立模式」功能的使用者,有兩種啟用方法: 1. 將環境變數 `ASH_STANDALONE` 設為 `1`。例如:`ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh