85 Commits

Author SHA1 Message Date
ShirkNeko
5ba4f73eeb manager: Update to version 3.1.8 and rename the relevant version checking functions 2025-07-21 21:22:07 +08:00
ShirkNeko
139899d05d [skip ci]manager: Add SUS loop path function 2025-07-21 21:14:09 +08:00
awkoo
d2ab325e18 优化setup.sh (#288) 2025-07-21 20:23:08 +08:00
ShirkNeko
be393ddb7c manager: Updating susfs binaries 2025-07-21 16:28:50 +08:00
WenHao2130
467d6e0838 ksud: Add KSU_SUKISU to env
This will help module authors determine which root implementation the module is running on.

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-20 23:31:29 +08:00
米凛MiRin
46fcf97be3 readme: add chinese translation (#290) 2025-07-20 12:56:03 +05:30
Juno Bủh
72ed1bc4a2 Update Vietnamese Translation (#284) 2025-07-19 17:41:34 +08:00
ShirkNeko
b8544b4f53 manager: Adding a separate status to the update module
fix duplicate installations of update modules due to status confusion. fix #287

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-07-19 16:59:36 +08:00
Cloud_Yun
60f0a721ce script: Simplify repository cloning logic (#283)
Rather than cloning to SukiSU-Ultra and renaming it KernelSU, it would be better to clone it directly as KernelSU.

Signed-off-by: Cloud_Yun <1770669041@qq.com>
2025-07-17 19:37:31 +09:00
ShirkNeko
c62676d643 New Crowdin updates (#280)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Vietnamese)
2025-07-17 14:32:35 +08:00
米凛MiRin
dd2b2e995a docs: fix wrong infomation (#282)
* docs: fix wrong infomation

* docs: fix wrong infomation
2025-07-17 14:32:20 +08:00
MiRinChan
86456a4d95 README & docs: Revise the README and documentation. Thanks to lama's help. 2025-07-16 17:18:31 +05:30
Prslc
11e9e37f43 manager: fix typo in hide_zygisk_implement string and summary (#279)
Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 18:16:34 +08:00
Prslc
a8a2aef4b5 manager: Display Zygisk implementation method with rezygisk support (#278)
* manager: Display Zygisk implementation method with rezygisk support

Signed-off-by: prslc <prslc113@gmail.com>

* manager: Fix incorrect display of Zygisk implementation when module is disabled

Signed-off-by: prslc <prslc113@gmail.com>

---------

Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 15:08:20 +08:00
Prslc
77ac0d70fd [skip ci]manager: Add switch to hide Zygisk implementation status information (#277)
Signed-off-by: prslc <prslc113@gmail.com>
2025-07-16 15:08:08 +08:00
wxxsfxyzm
2a00ef96c2 UPSTREAM: manager: improve predictive back animations
This pull request introduces custom screen transition animations to
enhance the overall user experience during navigation.

The key change is the implementation of a custom slide/fade effect for
navigating from main screens (i.e., screens hosted in the bottom
navigation bar) to detail screens. Transitions between the bottom
navigation bar tabs themselves retain a simple, clean cross-fade effect
to ensure a fast and smooth user interaction.

This PR also addresses the root cause of an issue where custom
animations were being overridden by the navigation library's defaults.

During implementation, it was discovered that custom transition
animations defined in the `defaultTransitions` parameter of the
`DestinationsNavHost` in `MainActivity` were not being applied. Instead,
a default fade-in/fade-out animation was always present.

The root cause was traced to the `compose-destinations` KSP (Kotlin
Symbol Processing) code generator. By default, the generator creates a
`NavGraphSpec` (e.g., `RootNavGraph.kt`) that includes its own
`defaultTransitions` property. This property, defined at compile-time
within the generated graph object, has a higher precedence than the
`defaultTransitions` parameter supplied to the `DestinationsNavHost`
composable at runtime.

As a result, our intended custom animations were being ignored and
overridden by the generated default.

To resolve this precedence issue permanently, this PR adopts the
official configuration method recommended by the `compose-destinations`
library.

- The following KSP argument has been added to the
`app/build.gradle.kts` file:

```kotlin
ksp {
    arg("compose-destinations.defaultTransitions", "none")
}
```

- This argument instructs the code generator to omit the
`defaultTransitions` property from the generated `NavGraphSpec`.

- By removing the higher-priority, generated default, the
`defaultTransitions` parameter on `DestinationsNavHost` now functions as
the effective default, allowing our custom animation logic to execute as
intended.

The new animation logic is conditional and defined within
`MainActivity`. It distinguishes between two primary navigation types:

- Main Screen → Detail Screen:

   - Enter: The new detail screen slides in from the right.

   - Exit: The old main screen slides out to the left while fading out.

- Detail Screen → Main Screen (on Pop):

- Pop Enter: The main screen slides back in from the left while fading
in.

   - Pop Exit: The detail screen slides out to the right.

- Between Bottom Navigation Tabs:

- A simple cross-fade (`fadeIn`/`fadeOut`) is maintained for these
transitions to provide a quick and non-disruptive experience when
switching between primary sections of the app.
2025-07-15 09:02:06 +08:00
YangQi0408
39ee1cc41d kernel: core_hook: add support for KernelNoSU (#270)
reorder ksu_handle_prctl checks a bit to allow non-manager to use CMD 15
this allows us to piggyback a small su to KernelSU's permission system after
disabling kernel sucompat

from:
Relax prctl perm check
- 95125c32f9
Allow prctl only for root or manager or su binary
- fa7af67d94
Refine prctl access check, allow /product/bin/su
- dd466dc1b6
Refine prctl check a little bit more
- e7c5b24efa

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: nampud <nampud@users.noreply.github.com>
2025-07-14 15:24:48 +08:00
米凛MiRin
51556d1253 strings: add copyright infomation (#275)
* copyright: Correct copyright owner information

* string: add copyright infomation
2025-07-14 15:21:48 +08:00
米凛MiRin
94df64f234 copyright: Correct copyright owner information (#273) 2025-07-14 00:08:00 +08:00
WenHao2130
02f545b3fb [skip ci] Revert "Redirect the Feature Requests issue template tab (#1788)"
This reverts commit 3695435c3f.

Allow feature requests

Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-13 10:50:28 +08:00
ShirkNeko
62c7aac75b Merge branch 'main' of https://github.com/SukiSU-Ultra/SukiSU-Ultra 2025-07-12 11:43:23 +08:00
ShirkNeko
755d454960 manager:Add flag bits to module installations to prevent repeated installations
- Modify the time and location of the susfs self-startup scripts
2025-07-12 11:41:58 +08:00
Marat Budkevich
9717fa0de6 fix(manager): add extraspace after "UID:" for Home screen (#268) 2025-07-11 19:18:03 +08:00
ShirkNeko
bd6eb7fddd manager: Update agp version
- Fix bug caused by SuSFS configuration screen returning too quickly
2025-07-11 10:56:30 +08:00
ShirkNeko
9f706873f2 manager: Fixed susfs binary naming scheme 2025-07-09 18:54:27 +08:00
ShirkNeko
c424d5bab4 kernel: simplified signature verification 2025-07-09 12:12:12 +08:00
WenHao2130
e795387c30 manager: Reformat zh-rCN strings
Change-Id: I9880ac9c4e6f74d30110cccfbd774ddfebf89ac0
Signed-off-by: WenHao2130 <wenhao2130@outlook.com>
2025-07-09 11:07:54 +08:00
ShirkNeko
044dd9471f manager: Refactor the way information is fetched in the home screen to avoid null pointers
- add an auto-refresh cache feature
2025-07-09 01:33:00 +08:00
YangQi0408
213a15cdb6 manager: 显示 Zygisk 实现方式 (#264)
* manager: Add display of Zygisk Implement feature and formatting code

* manager: Change the method of detecting Zygisk Implement
Signed-off-by: YangQi0408 <a123er3643@163.com>
Co-authored-by: WenHao2130 <WenHao2130@outlook.com>
2025-07-08 22:34:34 +08:00
ShirkNeko
a255ea9d56 [skip ci]New Crowdin updates (#263)
* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Vietnamese)
2025-07-07 17:49:24 +08:00
ShirkNeko
6cbe13dafc Assets: Add susfs executable binary v1.5.9 2025-07-06 14:49:54 +08:00
ShirkNeko
fb5c7c2f9d manager: Updated dependency library version
- Add JNI macros to simplify field setup and object creation
2025-07-06 14:44:36 +08:00
ShirkNeko
b8f2d15bd1 manager: Modify the separator for information cards from a semicolon to a vertical line 2025-07-06 00:56:15 +08:00
ShirkNeko
2bd6929d24 manager: Add the ability to get a list of active managers 2025-07-06 00:26:42 +08:00
ShirkNeko
42b883240e kernel: add multi-manager support 2025-07-05 22:27:39 +08:00
ShirkNeko
4840540038 manager: Modify Dynamic Signature Configuration Input Verification
- Allow sizes beginning with 0x
2025-07-05 17:39:24 +08:00
Juno Bủh
7bfb37a11e [skip ci]Update Vietnamese Translation (#257)
* Update Vietnamese Translation

* Update strings.xml

* Update strings.xml
2025-07-05 16:37:48 +08:00
ShirkNeko
dd6d695020 kernel:Add Dynamic Signature Configuration 2025-07-05 16:21:29 +08:00
ShirkNeko
6a60b72e21 manager: Reorganizing the backup and restore functionality of SuSFS configurations
- Add checking for the existence of a data catalog for applications in SUS Path

- Modify the loading and caching mechanism of the application information class to avoid repeated refreshes,Finish loading with SuperUser.
2025-07-04 17:57:54 +08:00
ShirkNeko
ea3a0cf73b manager: Update the name in the webui description to “SukiSU-Ultra” 2025-07-03 21:09:37 +08:00
ShirkNeko
1816d15ce8 manager: Refactor show SuSFS features
- need to update the kernel
2025-07-03 19:25:52 +08:00
ShirkNeko
79c8f7a709 New Crowdin updates (#247)
* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Japanese)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Russian)

* New translations strings.xml (Vietnamese)
2025-07-03 14:00:45 +08:00
ShirkNeko
b0cc0e6f6d kernel: Update CMD_GET_FULL_VERSION to a new constant value 2025-07-03 00:08:54 +08:00
ShirkNeko
eccc70c0c9 manager: Improve loading and empty state handling in SuperUserScreen 2025-07-03 00:03:59 +08:00
Juno Bủh
fc828ff3aa [skip ci]: Update Vietnamese Translation (#248)
* Update Vietnamese Translation

* Update Vietnamese Translation
2025-07-02 23:34:48 +08:00
ShirkNeko
acb7cfff1b Revert: Rollback some of the changes in "Add option to use WebUI X" and refactor the KsuService
- Solve the problem that SuperUser is not available when opening SU compatibility.
2025-07-02 01:37:37 +08:00
nanLianQing
3729c22dd0 fix: Fix application crashes caused by improper handling of coroutine exceptions (#249) 2025-07-01 23:26:36 +08:00
ShirkNeko
a84cf70730 manager:Fixed the issue of not getting the corresponding app name and icon in SuSFS paths 2025-07-01 20:00:26 +08:00
ShirkNeko
2278fe49d2 manager: Adding optional additions to SUS paths applies functionality corresponding to the package name as well as categorization 2025-07-01 17:29:45 +08:00
ShirkNeko
be14da387e manager: replace Runtime.exec with getRootShell for command execution 2025-07-01 02:48:09 +08:00
ShirkNeko
1fd13d9d8d docs: Updated documentation to introduce SuSFS Configuration Manager and introduction of advanced features 2025-06-30 16:57:56 +08:00
NkBe
4205db6870 [skip ci]Update Traditional Chinese (Taiwan) (#242) 2025-06-30 16:43:32 +08:00
ShirkNeko
70f03081a4 [skip ci]New Crowdin updates (#240)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Turkish)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-30 15:51:32 +08:00
Kitty
5ccb779b6a [skip ci] Update Ukrainian translation (#236) 2025-06-30 15:35:34 +08:00
Juno Bủh
b07bc408ce [skip ci] Update Vietnamese Translation (#238)
* Update Vietnamese Translation

* Update Vietnamese Translation

* Update Vietnam
2025-06-30 15:35:12 +08:00
ShirkNeko
7ee1fd63f1 manager: Add Zygote isolation service uninstallation to susfs feature 2025-06-30 15:32:47 +08:00
ShirkNeko
3551441e42 manager: Provides re-editable functionality for all SuSFS path configurations 2025-06-29 20:36:45 +08:00
ShirkNeko
4a1ab76322 manager: Optimize the logical order of Susfs self boot scripts 2025-06-29 19:06:20 +08:00
ShirkNeko
2fedb051b8 manager: Add Hide Bootloader Scripts and Cleanup Tool Residue feature and switch 2025-06-29 17:50:39 +08:00
Juno Bủh
10c35f4baa Update Vietnamese Translation (#229)
* Update Vietnamese Translation

* Update Vietnamese Translation
2025-06-29 12:32:05 +08:00
科家
4f82eda003 manager: Only display slotinformation on AB devices (#233)
还是有人在用 A-Only 分区设备的
2025-06-29 12:31:50 +08:00
Prslc
80f89c0241 [skip ci] manager: Fix unintended LKM dialog when selecting AnyKernel3 install method (#234)
This fixes a logic issue where the KMI selection dialog would still appear
even when the user selected the AnyKernel3 install method.

Signed-off-by: prslc <prslc113@gmail.com>
2025-06-29 12:30:34 +08:00
ShirkNeko
8399f14fad manager: Add SuSFS configuration backup and restore feature
- Optimize susfs self-boot scripts
- Solve some invalid issues where startup duration does not match or is too fast.

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-28 23:19:18 +08:00
YC酱luyancib
c49a66d1af Update Kconfig (#224)
make sure kpm config requrement was enabled
2025-06-28 10:19:53 +05:30
Juno Bủh
d66b390361 Update Vietnamese Translation (#223) 2025-06-27 18:47:02 +08:00
ShirkNeko
9c290a8080 [skip ci]: New Crowdin updates (#222)
* New translations strings.xml (Japanese)

* New translations strings.xml (Russian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-27 18:46:45 +08:00
Saksham Singla
48efc28e8f Update Funding.yml (#221)
* Update FUNDING.yml

* add sukisu donation

---------

Co-authored-by: weishu <twsxtd@gmail.com>
2025-06-27 16:55:22 +08:00
ShirkNeko
634adad15c ksud: fmt 2025-06-27 11:15:19 +08:00
古塵
4532bab230 kernel: refactor CMD_GET_FULL_VERSION to safely initialize version string (#220)
Use strscpy()/strlcpy() to populate the version buffer in CMD_GET_FULL_VERSION
instead of relying on uninitialized memory. This ensures the returned string
is null-terminated and avoids exposing garbage data to user space.

Signed-off-by: schqiushui <orochi9999@gmail.com>
2025-06-27 10:42:38 +08:00
ShirkNeko
d3c9b6e739 ksud: handle errors and non compatible ramdisk
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-06-26 14:22:42 +08:00
ShirkNeko
8e4f980db0 ksud: third test properly check if vendor is already patched or not for lkm restoration and also handle magisk patched vendor boot
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
2025-06-26 14:15:49 +08:00
ShirkNeko
cfee357ed1 manager: Optimize susfs management,
- solve some problems caused by new versions not taking effect
2025-06-26 14:10:50 +08:00
ShirkNeko
9393459b27 manager: Improvements to susfs functionality status fetch exceptions
- Show false if unable to fetch
2025-06-26 00:24:33 +08:00
ShirkNeko
60af173a7e manager:Optimize the path configuration to automatically configure the corresponding value as long as the self-boot is enabled 2025-06-25 23:39:04 +08:00
NkBe
23e2377f87 [skip ci]Update README.md (#218)
就单纯怎么看怎么怪,所以手欠改一改
2025-06-25 20:13:06 +08:00
NkBe
d45ba31849 manger: fix lkm detection (#217)
* manger: Rollback crowdin Update (Traditional Chinese Taiwan)

* manger: Try to modify the lkm detection

改了下判斷方式,現在只要核心返回的 version_flags最後一位是 1,is_lkm就會被正確地設成 true
2025-06-25 19:26:54 +08:00
Saksham Singla
c5705c2d5d Bump agp and Gradle to latest (#216)
* Bump AGP

* Bump Gradle

* update gradle to 14.2
2025-06-25 19:15:17 +08:00
ShirkNeko
dfae83cf58 New Crowdin updates (#215)
* New translations strings.xml (Russian)

* New translations strings.xml (Chinese Simplified)

* New translations strings.xml (Chinese Traditional)

* New translations strings.xml (Vietnamese)

* New translations strings.xml (Indonesian)

* New translations strings.xml (Chinese Traditional, Hong Kong)
2025-06-25 16:33:07 +08:00
NkBe
cd5ba3ac3c [skip ci] manger: Update Traditional Chinese (Taiwan) (#214) 2025-06-25 16:26:24 +08:00
ShirkNeko
2c2698f6bc kernel: Rewrite kernle version code management
Co-authored-by: lamadaemon <i@lama.icu>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-24 23:16:16 +08:00
NkBe
f57fe79c5d manager: Update LKM select file prompt, optimize “init_boot / vendor_boot” text (#211)
* Update Install.kt

* Update Install.kt

* Update strings.xml

* Update strings-rCN.xml

* Update strings-rTW.xml

* manger: Add a space to ensure pangu

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-24 15:50:48 +08:00
ShirkNeko
91ae4c9650 manager: Update LKM select file prompt, support “init_boot / vendor_boot” option 2025-06-24 15:03:14 +08:00
ShirkNeko
01f44dc1d9 ksud: Adding LKM patch support for vendor_boot images
- And improve the OTA update mechanism
- Updating the magiskboot library

Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-06-24 12:52:22 +08:00
Prslc
6e35b88041 Kernel: use main branch commit count for consistent versioning (#209) 2025-06-23 18:59:30 +08:00
Re*Index. (ot_inc)
c9c122d79b skip ci :Update & Fix Japanese (#208)
* Update README-ja.md

* Update README-ja.md

* Update README-ja.md

* Update strings.xml

* Update strings.xml

* Update strings.xml
2025-06-23 18:58:03 +08:00
117 changed files with 8126 additions and 2538 deletions

5
.github/FUNDING.yml vendored
View File

@@ -1,5 +1,4 @@
# These are supported funding model platforms
github: tiann github: tiann
patreon: weishu patreon: weishu
custom: https://vxposed.com/donate.html open_collective: sukisu-ultra

View File

@@ -1,5 +0,0 @@
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."

View File

@@ -0,0 +1,39 @@
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."

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.idea .idea
.vscode .vscode
.DS_Store

View File

@@ -1,157 +0,0 @@
# SukiSU Ultra
**English** | [简体中文](README.md) | [日本語](README-ja.md) | [Türkçe](README-tr.md)
Android device root solution based on [KernelSU](https://github.com/tiann/KernelSU)
**Experimental! Use at your own risk!** This solution is based on [KernelSU](https://github.com/tiann/KernelSU) and is experimental!
> This is an unofficial fork. All rights are reserved to [@tiann](https://github.com/tiann)
>
> However, we will be a separately maintained branch of KSU in the future
## How to add
Using main branching (non-GKI device builds are not supported) (requires manual integration of susfs)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
Using branches that support non-GKI devices (requires manual integration of susfs)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## How to use integrated susfs
1. Use susfs-main or other susfs-\* branches directly, no need to integrate susfs again (supports non-GKI device builds)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## Hook method
- This method references the hook [method by rsuntk](https://github.com/rsuntk/KernelSU)
1. **KPROBES hook:**
- Also used for Loadable Kernel Module (LKM)
- Default hook method on GKI kernels.
- Need `CONFIG_KPROBES=y`
2. **Manual hook:**
- Standard KernelSU hook: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5
- Default hook method on Non-GKI kernels.
- Need `CONFIG_KSU_MANUAL_HOOK=y`
## KPM Support
- Based on KernelPatch, we have removed duplicates of KSU and kept only KPM support.
- We will introduce more APatch-compatible functions to ensure the integrity of KPM functionality.
Repository address: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM templates: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
>
> 1. `CONFIG_KPM=y` needs to be added.
> 2. Non-GKI devices need to add `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y` as well.
> 3. Some kernel source code below `4.19` also needs to be backport from `4.19` to the header file `set_memory.h`.
## How to do a system update to retain ROOT
- After OTA, don't reboot first, go to the manager flashing/patching kernel interface, find `GKI/non_GKI install` and select the Anykernel3 kernel zip file that needs to be flashed, select the slot that is opposite to the current running slot of the system for flashing, and then reboot to retain the GKI mode update This method is not supported for all non-GKI devices, so please try it yourself. It is the safest way to use TWRP for non-GKI devices.
- Or use LKM mode to install to the unused slot (after OTA).
## Compatibility Status
- KernelSU (versions prior to v1.0.0) officially supports Android GKI 2.0 devices (kernel 5.10+)
- Older kernels (4.4+) are also compatible, but the kernel must be built manually
- KernelSU can support 3.x kernels (3.4-3.18) through additional reverse ports
- Currently supports `arm64-v8a`, `armeabi-v7a (bare)` and some `X86_64`
## More links
**If you need to submit a translation for the manager go to** https://crowdin.com/project/SukiSU-Ultra
Projects compiled based on Sukisu and susfs
- [More patched GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) including ZRAM patches, KPM, susfs...
- [Less patched GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases) only susfs
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## Usage
### Universal GKI
Please **all** refer to https://kernelsu.org/zh_CN/guide/installation.html
> [!Note]
>
> 1. for devices with GKI 2.0 such as Xiaomi, Redmi, Samsung, etc. (excludes kernel-modified manufacturers such as Meizu, OnePlus, Zenith, and oppo)
> 2. Find the GKI build in [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5). Find the device kernel version. Then download it and use TWRP or kernel flashing tool to flash the zip file with AnyKernel3 suffix. Pixel user need use _Less patched GKI_.
> 3. The .zip archive without suffix is uncompressed, the gz suffix is the compression used by Tenguet models.
### OnePlus
1. Use the link mentioned in the 'More Links' section to create a customized build with your device information, and then flash the zip file with the AnyKernel3 suffix.
> [!Note]
>
> - You only need to fill in the first two parts of kernel versions, such as 5.10, 5.15, 6.1, or 6.6.
> - Please search for the processor codename by yourself, usually it is all English without numbers.
> - You can find the branch and configuration files from the OnePlus open-source kernel repository.
## Features
1. Kernel-based `su` and root access management.
2. Not based on [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) module system, but based on [Magic Mount](https://github.com/5ec1cff/KernelSU) from 5ec1cff
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock root privileges in a cage.
4. Bringing back non-GKI/GKI 1.0 support
5. More customization
6. Support for KPM kernel modules
## Troubleshooting
1. Uninstalling the KernelSU Manager device is stuck. → Uninstall the application with package name com.sony.playmemories.mobile.
## License
- The file in the “kernel” directory is under [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) license.
- The images of the files `ic_launcher(?!.*alt.*).*` with anime character emoticons are copyrighted by [五十根大虾仁](https://space.bilibili.com/370927), the Brand Intellectual Property in the images is owned by [明风 OuO](https://space.bilibili.com/274939213), and the vectorization is done by @MiRinChan. Before using these files, in addition to complying with [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt), you also need to comply with the authorization of the two authors to use these artistic contents.
- Except for the files or directories mentioned above, all other parts are under [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) license.
## Afdian link
- https://afdian.com/a/shirkneko
## Sponsorship list
- [Ktouls](https://github.com/Ktouls) Thanks so much for bringing me support
- [zaoqi123](https://github.com/zaoqi123) It's not a bad idea to buy me a milk tea
- [wswzgdg](https://github.com/wswzgdg) Many thanks for supporting this project
- [yspbwx2010](https://github.com/yspbwx2010) Many thanks
- [DARKWWEE](https://github.com/DARKWWEE) Thanks for the 100 USDT Lao
- [Saksham Singla](https://github.com/TypeFlu) Website provision as well as maintenance
- [OukaroMF](https://github.com/OukaroMF) Donation of website domain name
## Contributions
- [KernelSU](https://github.com/tiann/KernelSU): original project
- [MKSU](https://github.com/5ec1cff/KernelSU): Used project
- [RKSU](https://github.com/rsuntk/KernelsU): Reintroduced the support of non-GKI devices using the kernel of this project
- [susfs](https://gitlab.com/simonpunk/susfs4ksu)Used susfs file system
- [KernelSU](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU conceptualization
- [Magisk](https://github.com/topjohnwu/Magisk): Powerful root utility
- [genuine](https://github.com/brevent/genuine/): APK v2 Signature Verification
- [Diamorphine](https://github.com/m0nad/Diamorphine): Some rootkit utilities.
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch is a key part of the APatch implementation of the kernel module

View File

@@ -1,142 +0,0 @@
# SukiSU Ultra
**日本語** | [简体中文](README.md) | [English](README-en.md) | [Türkçe](README-tr.md)
[KernelSU](https://github.com/tiann/KernelSU) をベースとした Android デバイスの root ソリューション
**試験中なビルドです!自己責任で使用してください!**<br>
このソリューションは [KernelSU](https://github.com/tiann/KernelSU) に基づいていますが、試験中なビルドです。
> これは非公式なフォークです。すべての権利は [@tiann](https://github.com/tiann) に帰属します。
>
> ただし、将来的には KSU とは別に管理されるブランチとなる予定です。
## 追加方法
メイン分岐の使用GKI デバイス以外のビルドはサポートされていません。) (手動によるサスフ統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
GKI以外のデバイスをサポートするブランチを使用する (手動によるサスフ統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 統合された susfs の使い方
1. susfs-mainまたは他のsusfs-*ブランチを直接使用し、susfsを再度統合する必要はありません
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## KPM に対応
- KernelPatch に基づいて重複した KSU の機能を削除、KPM の対応を維持させています。
- KPM 機能の整合性を確保するために、APatch の互換機能を更に向上させる予定です。
オープンソースアドレス: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM テンプレートのアドレス: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
> 1. `CONFIG_KPM=y` が必要である。
> 2.非 GKI デバイスには `CONFIG_KALLSYMS=y` と `CONFIG_KALLSYMS_ALL=y` も必要です。
> 3.いくつかのカーネル `4.19` およびそれ以降のソースコードでは、 `4.19` からバックポートされた `set_memory.h` ヘッダーファイルも必要です。
## ROOT を保持するシステムアップデートの方法
- OTAの後、最初に再起動せず、マネージャのフラッシュ/パッチカーネルインターフェイスに移動し、`GKI/non_GKI 取り付け`を見つけ、フラッシュする必要があるAnykernel3カーネルzipファイルを選択し、フラッシュするためにシステムの現在の実行スロットと反対のスロットを選択し、GKIモードアップデートを保持するために再起動しますこの方法は、現時点ではすべてのnon_GKIデバイスでサポートされていませんので、各自でお試しください。 (この方法は、すべての非GKIデバイスでサポートされていませんので、ご自身でお試しください)。
- または、LKMモードを使用して未使用のスロットにインストールします(OTA後)。
## 互換性ステータス
- KernelSUv1.0.0より前のバージョンはAndroid GKI 2.0デバイスカーネル5.10以上)を公式にサポートしています。
- 古いカーネル4.4+)も互換性がありますが、カーネルは手動でビルドする必要があります。
- KernelSU は追加のリバースポートを通じて 3.x カーネル (3.4-3.18) をサポートしています。
- 現在は `arm64-v8a``armeabi-v7a (bare)`、いくつかの `X86_64` をサポートしています。
## その他のリンク
**監督に翻訳を提出する必要がある場合は、https://crowdin.com/project/SukiSU-Ultra。
- [GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## フックの方式
- この方式は (https://github.com/rsuntk/KernelSU) のフック方式を参照してください。
1. **KPROBES フック:**
- 読み込み可能なカーネルモジュールの場合 (LKM)
- GKI カーネルのデフォルトとなるフック方式
- `CONFIG_KPROBES=y` が必要です
2. **手動でフック:**
- 標準の KernelSU フック: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx syscall フック: https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI カーネル用のデフォルトフッキングメソッド
- `CONFIG_KSU_MANUAL_HOOK=y` が必要です
## 使い方
### ユニバーサルGKI
https://kernelsu.org/zh_CN/guide/installation.html をご参照ください。
> [!Note]
> 1.Xiaomi、Redmi、Samsung などの GKI 2.0 を搭載したデバイス用 (Meizu、Yiga、Zenith、oppo などのマジックカーネルを搭載したメーカーは除く)。
> 2. [more links](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5) で GKI ビルドを検索します。 デバイスのカーネルバージョンを検索します。 次に、それをダウンロードし、TWRPまたはカーネルフラッシングツールを使用して、AnyKernel3の接尾辞が付いたzipファイルをフラッシュします。
> 接尾辞なしの.zipアーカイブは非圧縮で、接尾辞gzはTenguetモデルで使用されている圧縮方法です。
### OnePlus
1. `その他のリンク`の項目に記載されているリンクを開き、デバイス情報を使用してカスタマイズされたカーネルをビルドし、AnyKernel3 の接頭辞を持つ .zip ファイルをフラッシュします。
> [!Note]
> - 5.10、5.15、6.1、6.6 などのカーネルバージョンの最初の 2 文字のみを入力する必要があります。
> - SoC のコードネームは自分で検索してください。通常は、数字がなく英語表記のみです。
> - ブランチと構成ファイルは、OnePlus オープンソースカーネルリポジトリから見つけることができます。
## 機能
1. カーネルベースな `su` および root アクセスの管理。
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) モジュールシステムではなく、 5ec1cff 氏の [Magic Mount](https://github.com/5ec1cff/KernelSU) に基づいています。
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージ内にロックします。
4. 非 GKI / GKI 1.0 の対応を復活
5. その他のカスタマイズ
6. KPM カーネルモジュールに対応
## トラブルシューティング
1.KernelSU Managerのアンインストールができない。 →パッケージ名com.sony.playmemories.mobile.KernelSU Managerのアプリケーションをアンインストールする。
## ライセンス
- `kernel` ディレクトリ以下のファイルは[GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)です。
- アニメキャラクターの絵文字を含むファイル `ic_launcher(?!.*alt.*).*` の画像は[五十根大虾仁](https://space.bilibili.com/370927)が著作権を所有しており、画像内のブランド知的財産権は[明风OuO](https://space.bilibili.com/274939213)が所有しています。ベクトル化は @MiRinChan が行っています。これらのファイルを使用する前に、[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt)に準拠することに加えて、これらの芸術コンテンツを使用するには、2人の著者の許可にも従う必要があります。
- 上記のファイルまたはディレクトリを除き、その他のすべての部分は[GPL-3.0以降](https://www.gnu.org/licenses/gpl-3.0.html)です。
## スポンサーシップの一覧
- [Ktouls](https://github.com/Ktouls) 応援をしてくれたことに感謝。
- [zaoqi123](https://github.com/zaoqi123) ミルクティーを買ってあげるのも良い考えですね。
- [wswzgdg](https://github.com/wswzgdg) このプロジェクトを支援していただき、ありがとうございます。
- [yspbwx2010](https://github.com/yspbwx2010) どうもありがとう。
- [DARKWWEE](https://github.com/DARKWWEE) ラオウ100USDTありがとう
- [Saksham Singla](https://github.com/TypeFlu) ウェブサイトの提供およびメンテナンス
- [OukaroMF](https://github.com/OukaroMF) ウェブサイトドメイン名の寄付
## 貢献者
- [KernelSU](https://github.com/tiann/KernelSU): オリジナルのプロジェクトです。
- [MKSU](https://github.com/5ec1cff/KernelSU): 使用しているプロジェクトです。
- [RKSU](https://github.com/rsuntk/KernelsU): このプロジェクトのカーネルを使用して非 GKI デバイスのサポートを追加しています。
- [susfs](https://gitlab.com/simonpunk/susfs4ksu):使用している susfs ファイルシステムです。
- [KernelSU](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 ユーティリティを使用しています。
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch はカーネルモジュールの APatch 実装での重要な部分となります。

View File

@@ -1,158 +1,101 @@
<img align='right' src='zakomonochrome-128.svg' width='100px' alt="logo">
# SukiSU Ultra # SukiSU Ultra
**简体中文** | [English](README-en.md) | [日本語](README-ja.md) | [Türkçe](README-tr.md) **English** | [简体中文](./zh/README.md) | [日本語](./ja/README.md) | [Türkçe](./tr/README.md)
基于 [KernelSU](https://github.com/tiann/KernelSU) 的安卓设备 root 解决方案 A kernel-based root solution for Android devices, forked from [`tiann/KernelSU`](https://github.com/tiann/KernelSU), and added some interesting changes.
**实验性! 使用风险自负!** [![Latest release](https://img.shields.io/github/v/release/SukiSU-Ultra/SukiSU-Ultra?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest)
[![Channel](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/Sukiksu)
[![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)
> 这是非官方分支,保留所有权利 [@tiann](https://github.com/tiann) ## Features
>
> 但是,我们将会在未来成为一个单独维护的 KSU 分支
## 如何添加 1. Kernel-based `su` and root access management
2. Module system based on [Magic Mount](https://github.com/5ec1cff/KernelSU)
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Lock up the root power in a cage
4. Support non-GKI and GKI 1.0
5. KPM Support
6. Tweaks to the manager theme and the built-in susfs management tool.
在内核源码的根目录下执行以下命令: ## Compatibility Status
使用 main 分支 (不支持非 GKI 设备构建) (需要手动集成 susfs) - KernelSU (before v1.0.0) officially supports Android GKI 2.0 devices (kernel 5.10+).
``` - Older kernels (4.4+) are also compatible, but the kernel will have to be built manually.
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
使用支持非 GKI 设备的分支 (需要手动集成 susfs) - With more backports, KernelSU can supports 3.x kernel (3.4-3.18).
``` - Currently, only `arm64-v8a`, `armeabi-v7a (bare)` and `X86_64`(some) are supported.
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 如何集成 susfs ## Installation
1. 直接使用 susfs-main 或者其他 susfs-\* 分支,不需要再集成 susfs (支持非 GKI 设备构建) See [`guide/installation.md`](guide/installation.md)
``` ## Integration
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## 钩子方法 See [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
- 此部分引用自 [rsuntk 的钩子方法](https://github.com/rsuntk/KernelSU) ## Translation
1. **KPROBES 钩子:** If you need to submit a translation for the manager, please go to [Crowdin](https://crowdin.com/project/SukiSU-Ultra).
- 用于可加载内核模块 (LKM) ## KPM Support
- GKI 2.0 内核的默认钩子方法
- 需要 `CONFIG_KPROBES=y`
2. **手动钩子:** - Based on KernelPatch, we removed features redundant with KSU and retained only KPM support.
- 标准的 KernelSU 钩子https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source - Work in Progress: Expanding APatch compatibility by integrating additional functions to ensure compatibility across different implementations.
- backslashxx 的 syscall 手动钩子https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI 内核的默认挂钩方法
- 需要 `CONFIG_KSU_MANUAL_HOOK=y`
## KPM 支持 **Open-source repository**: [https://github.com/ShirkNeko/SukiSU_KernelPatch_patch](https://github.com/ShirkNeko/SukiSU_KernelPatch_patch)
- 我们基于 KernelPatch 去掉了和 KSU 重复的功能,仅保留了 KPM 支持 **KPM template**: [https://github.com/udochina/KPM-Build-Anywhere](https://github.com/udochina/KPM-Build-Anywhere)
- 我们将会引入更多的兼容 APatch 的函数来确保 KPM 功能的完整性
开源地址: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM 模板地址: https://github.com/udochina/KPM-Build-Anywhere
> [!Note] > [!Note]
> >
> 1. 需要 `CONFIG_KPM=y` > 1. Requires `CONFIG_KPM=y`
> 2. 非 GKI 设备还需要 `CONFIG_KALLSYMS=y` `CONFIG_KALLSYMS_ALL=y` > 2. Non-GKI devices requires `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y`
> 3. 部分内核 `4.19` 以下源码还需要从 `4.19` 向后移植头文件 `set_memory.h` > 3. For kernels below `4.19`, backporting from `set_memory.h` from `4.19` is required.
## 如何进行系统更新保留 ROOT ## Troubleshooting
- OTA 后先不要重启,进入管理器刷写/修补内核界面,找到 `GKI/non_GKI安装` 选择需要刷写的 Anykernel3 内核压缩文件,选择与现在系统运行槽位相反的槽位进行刷写并重启即可保留 GKI 模式更新(暂不支持所有非 GKI 设备使用这种方法,请自行尝试。非 GKI 设备使用 TWRP 刷写是最稳妥的) 1. Device stuck upon manager app uninstallation?
- 或者使用 LKM 模式的安装到未使用的槽位OTA 后) Uninstall _com.sony.playmemories.mobile_
## 兼容状态 ## Sponsor
- KernelSUv1.0.0 之前版本)正式支持 Android GKI 2.0 设备(内核 5.10+ - [ShirkNeko](https://afdian.com/a/shirkneko) (maintainer of SukiSU)
- [weishu](https://github.com/sponsors/tiann) (author of KernelSU)
- 旧内核4.4+)也兼容,但必须手动构建内核 ## ShirkNeko's sponsorship list
- 通过更多的反向移植KernelSU 可以支持 3.x 内核3.4-3.18 - [Ktouls](https://github.com/Ktouls) Thanks so much for bringing me support.
- [zaoqi123](https://github.com/zaoqi123) Thanks for the milk tea.
- [wswzgdg](https://github.com/wswzgdg) Many thanks for supporting this project.
- [yspbwx2010](https://github.com/yspbwx2010) Many thanks.
- [DARKWWEE](https://github.com/DARKWWEE) 100 USDT
- [Saksham Singla](https://github.com/TypeFlu) Provide and maintain the website
- [OukaroMF](https://github.com/OukaroMF) Donation of website domain name
- 目前支持 `arm64-v8a` `armeabi-v7a (bare)` 和部分 `X86_64` ## License
## 更多链接 - The file in the “kernel” directory is under [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) license.
- The images of the files `ic_launcher(?!.*alt.*).*` with anime character sticker are copyrighted by [怡子曰曰](https://space.bilibili.com/10545509), the Brand Intellectual Property in the images is owned by [明风 OuO](https://space.bilibili.com/274939213), and the vectorization is done by @MiRinChan. Before using these files, in addition to complying with [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt), you also need to comply with the authorization of the two authors to use these artistic contents.
- Except for the files or directories mentioned above, all other parts are under [GPL-3.0 or later](https://www.gnu.org/licenses/gpl-3.0.html) license.
**如果你需要为管理器提交翻译请前往** https://crowdin.com/project/SukiSU-Ultra ## Credit
基于 SukiSU 和 susfs 编译的项目 - [KernelSU](https://github.com/tiann/KernelSU): upstream
- [MKSU](https://github.com/5ec1cff/KernelSU): Magic Mount
- [RKSU](https://github.com/rsuntk/KernelsU): support non-GKI
- [susfs](https://gitlab.com/simonpunk/susfs4ksu): An addon root hiding kernel patches and userspace module for KernelSU.
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch is a key part of the APatch implementation of the kernel module
- [增强 GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)(包括 ZRAM 算法等补丁、KPM、susfs 等) <details>
- [GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases)(若增强 GKI boot 失败再尝试这份,这份没有 KPM 等修改,只有 susfs <summary>KernelSU's credit</summary>
- [一加](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## 使用方法 - [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): The KernelSU idea.
- [Magisk](https://github.com/topjohnwu/Magisk): The powerful root tool.
### 普适的 GKI - [genuine](https://github.com/brevent/genuine/): APK v2 signature validation.
- [Diamorphine](https://github.com/m0nad/Diamorphine): Some rootkit skills.
请**全部**参考 https://kernelsu.org/zh_CN/guide/installation.html </details>
> [!Note]
>
> 1. 适用于如小米、红米、三星等的 GKI 2.0 的设备 (不包含魔改内核的厂商如魅族、一加、真我和 oppo)
> 2. 找到[更多链接](#%E6%9B%B4%E5%A4%9A%E9%93%BE%E6%8E%A5)里的 GKI 构建的项目。找到设备内核版本。然后下载下来,用 TWRP 或者内核刷写工具刷入带 AnyKernel3 后缀的压缩包即可。Pixel 请使用不是增强的 GKI。
> 3. 一般不带后缀的 .zip 压缩包是未压缩的gz 后缀的为天玑机型所使用的压缩方式
### 一加
1.找到更多链接里的一加项目进行自行填写,然后云编译构建,最后刷入带 AnyKernel3 后缀的压缩包即可
> [!Note]
>
> - 内核版本只需要填写前两位即可,如 5.105.156.16.6
> - 处理器代号请自行搜索,一般为全英文不带数字的代号
> - 分支和配置文件请自行到一加内核开源地址进行填写
## 特点
1. 基于内核的 `su` 和 root 访问管理
2. 基于 5ec1cff 的 [Magic Mount](https://github.com/5ec1cff/KernelSU) 的模块系统
3. [App Profile](https://kernelsu.org/guide/app-profile.html):将 root 权限锁在笼子里
4. 恢复对非 GKI 2.0 内核的支持
5. 更多自定义功能
6. 对 KPM 内核模块的支持
## 疑难解答
1. 卸载 KernelSU 管理器设备卡死。→ 卸载包名为 com.sony.playmemories.mobile 的应用。
## 许可证
- `kernel` 目录下的文件是 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
- 有动漫人物图片表情包的这些文件 `ic_launcher(?!.*alt.*).*` 的图像版权为[五十根大虾仁](https://space.bilibili.com/370927)所有,图像中的 Brand Intellectual Property 由[明风 OuO](https://space.bilibili.com/274939213)所有,矢量化由 @MiRinChan 完成,在使用这些文件之前,除了必须遵守 [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 以外,还需要遵守向前两者索要使用这些艺术内容的授权。
- 除了以上所述的文件或目录外,所有其他部分均为 [GPL-3.0 或更高版本](https://www.gnu.org/licenses/gpl-3.0.html)。
## 爱发电链接
- https://afdian.com/a/shirkneko
## 赞助名单
- [Ktouls](https://github.com/Ktouls) 非常感谢你给我带来的支持
- [zaoqi123](https://github.com/zaoqi123) 请我喝奶茶也不错
- [wswzgdg](https://github.com/wswzgdg) 非常感谢对此项目的支持
- [yspbwx2010](https://github.com/yspbwx2010) 非常感谢
- [DARKWWEE](https://github.com/DARKWWEE) 感谢老哥的 100 USDT
- [Saksham Singla](https://github.com/TypeFlu) 网站的提供以及维护
- [OukaroMF](https://github.com/OukaroMF) 网站域名捐赠
## 贡献
- [KernelSU](https://github.com/tiann/KernelSU):原始项目
- [MKSU](https://github.com/5ec1cff/KernelSU):使用的项目
- [RKSU](https://github.com/rsuntk/KernelsU):使用该项目的 kernel 对非 GKI 设备重新进行支持
- [susfs4ksu](https://gitlab.com/simonpunk/susfs4ksu):使用的 susfs 文件系统
- [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 技能
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch 是 APatch 实现内核模块的关键部分

View File

@@ -0,0 +1,91 @@
# Integrate
SukiSU can be integrated into both _GKI_ and _non-GKI_ kernels and has been backported to _4.14_.
<!-- It should be 3.4, but backslashxx's syscall manual hook cannot use in SukiSU-->
Some OEMs' customization could result in as much as 50% of kernel code being out-of-tree code and not from upstream Linux kernels or ACKs. Due to this, the custom nature of _non-GKI_ kernels resulted in significant kernel fragmentation, and we lacked a universal method for building them. Therefore, we cannot provide boot images of _non-GKI_ kernels.
Prerequisites: open source bootable kernel.
### Hook method
1. **KPROBES hook:**
- Default hook method on GKI kernels.
- Requires `# CONFIG_KSU_MANUAL_HOOK is not set` & `CONFIG_KPROBES=y`
- Used for Loadable Kernel Module (LKM).
2. **Manual hook:**
<!-- - backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5 (v1.5 version is not available at the moment, if you want to use it, please use v1.4 version, or standard KernelSU hooks)-->
- Requires `CONFIG_KSU_MANUAL_HOOK=y`
- Requires [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
- Requires [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source)
<!-- This part refer to [rsuntk/KernelSU](https://github.com/rsuntk/KernelSU). -->
If you're able to build a bootable kernel, there are two ways to integrate KernelSU into the kernel source code:
1. Automatically with `kprobe`
2. Manually
## Integrate with kprobe
Applicable:
- _GKI_ kernel
Not applicable:
- _non-GKI_ kernel
KernelSU uses kprobe to do kernel hooks. If kprobe runs well in your kernel, it's recommended to use it this way.
Please refer to this document [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#integrate-with-kprobe). Although it is titled “for _non-GKI_,” it only applies to _GKI_.
The execution command for the step that adds KernelSU to your kernel source tree is replaced with:
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
## Manually modify the kernel source
Applicable:
- GKI kernel
- non-GKI kernel
Please refer to this document [https://github.com/~ (Integrate for non-GKI)](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) and [https://github.com/~ (Build for GKI)](https://kernelsu.org/zh_CN/guide/how-to-build.html) to integrate manually, although first link is titled “for non-GKI,” it also applies to GKI. It can work on them both.
There is another way to integrate but still work in the process.
<!-- It is backslashxx's syscall manual hook, but it cannot be used now. -->
Run command for the step that adds KernelSU(SukiSU) to your kernel source tree is replaced with:
### GKI kernel
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
### non-GKI kernel
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
### GKI / non-GKI kernel with susfs (experiment)
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-{{branch}}
```
Branch:
- `main` (susfs-main)
- `test` (susfs-test)
- version (for example: susfs-1.5.7, you should check the [branches](https://github.com/SukiSU-Ultra/SukiSU-Ultra/branches))

View File

@@ -0,0 +1,34 @@
# Installation
You can go to [KernelSU Documentation - Installation](https://kernelsu.org/guide/installation.html) for a reference on how to install it, here are just additional instructions.
## Installation by loading the Loadable Kernel Module(LKM)
See [KernelSU Documentation - LKM Installation](https://kernelsu.org/guide/installation.html#lkm-installation)
Beginning with **Android™** (trademark meaning licensed Google Mobile Services) 12, devices shipping with kernel version 5.10 or higher must ship with the GKI kernel. You may be able to use LKM mode.
## Installation by installing the kernel
See [KernelSU Documentation - GKI mode Installation](https://kernelsu.org/guide/installation.html#gki-mode-installation)
We provide pre-built kernels for you to use:
- [ShirkNeko flavor kernel](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) (add ZRAM compression algorithm patch, susfs, KPM. Works on many devices.)
- [MiRinFork flavored kernel](https://github.com/MiRinFork/GKI_SukiSU_SUSFS) (adds susfs, KPM. Closest kernel to GKI, works on most devices.)
Although some devices can be installed using LKM mode, they cannot be installed on the device by using the GKI kernel; therefore, the kernel needs to be modified manually to compile it. For example:
- OPPO(OnePlus, REALME)
- Meizu
Also, we provide pre-built kernels for your OnePlus device to use:
- [ShirkNeko/Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS) (add ZRAM compression algorithm patch, susfs, KPM.)
Using the link above, Fork into GitHub Action, fill in the build parameters, compile, and finally flush in the zip with the AnyKernel3 suffix.
> [!Note]
>
> - You only need to fill in the first two parts of the version number, e.g. `5.10`, `6.1`...
> - Make sure you know the processor designation, kernel version, etc. before you use it.

151
docs/ja/README.md Normal file
View File

@@ -0,0 +1,151 @@
# SukiSU Ultra
[English](../README.md) | [简体中文](../zh/README.md) | **日本語** | [Türkçe](../tr/README.md)
[KernelSU](https://github.com/tiann/KernelSU) をベースとした Android デバイスの root ソリューション
**試験中なビルドです!自己責任で使用してください!**<br>
このソリューションは [KernelSU](https://github.com/tiann/KernelSU) に基づいていますが、試験中なビルドです。
> これは非公式なフォークです。すべての権利は [@tiann](https://github.com/tiann) に帰属します。
>
> ただし、将来的には KSU とは別に管理されるブランチとなる予定です。
## 追加する方法
メインブランチを使用 (非 GKI のデバイスのビルドは非対応) (susfs を手動で統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
非 GKI のデバイスに対応するブランチを使用 (susfs を手動で統合が必要)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
## 統合された susfs の使い方
1. susfs-main または他の susfs-\* ブランチを直接で使用、susfs の統合は不要 (非 GKI デバイスのビルドに対応)
```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
```
## フックの方式
- この方式は (https://github.com/rsuntk/KernelSU) のフック方式を参照してください。
1. **KPROBES でフック:**
- 読み込み可能なカーネルモジュールの場合 (LKM)
- GKI カーネルのデフォルトとなるフック方式
- `CONFIG_KPROBES=y` が必要です
2. **手動でフック:**
- 標準の KernelSU フック: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#manually-modify-the-kernel-source
- backslashxx syscall フック: https://github.com/backslashxx/KernelSU/issues/5
- 非 GKI カーネル用のデフォルトフック方式
- `CONFIG_KSU_MANUAL_HOOK=y` が必要です
## KPM に対応
- KernelPatch に基づいて重複した KSU の機能を削除、KPM の対応を維持させています。
- KPM 機能の整合性を確保するために、APatch の互換機能を更に向上させる予定です。
オープンソースアドレス: https://github.com/ShirkNeko/SukiSU_KernelPatch_patch
KPM テンプレートのアドレス: https://github.com/udochina/KPM-Build-Anywhere
> [!Note]
>
> 1. `CONFIG_KPM=y` が必要です。
> 2. 非 GKI デバイスには `CONFIG_KALLSYMS=y` と `CONFIG_KALLSYMS_ALL=y` も必要です。
> 3. いくつかのカーネル `4.19` およびそれ以降のソースコードでは、 `4.19` からバックポートされた `set_memory.h` ヘッダーファイルも必要です。
## ROOT を保持した状態でのシステムアップデートの方法
- 始めに OTA 後すぐに再起動せずにマネージャーのカーネルのフラッシュ、パッチのインターフェースを開いて`GKI/非 GKI のインストール`を見つけます。フラッシュする AnyKernel3 の zip ファイルを選択し、フラッシュする実行中のスロットと逆のスロットを選択後に再起動をして GKI モードの更新が保持できます (この方法はすべての非 GKI のデバイスが対応している訳ではないので、自分でお試しください。これは非 GKI のデバイスで TWRP を使用する最も安全な方法です)。
- または LKM モードを使用して未使用のスロットにインストールします (OTA 後)。
## 互換性の状態
- KernelSU (v1.0.0 より前) は Android GKI 2.0 のデバイス (カーネル 5.10 以降) を公式に対応しています。
- 古いカーネル (4.4 以降) も互換性がありますが、カーネルを手動で再ビルドする必要があります。
- KernelSU は追加のリバースポートを通じて 3.x カーネル (3.4-3.18) で対応可能です。
- 現在 `arm64-v8a`, `armeabi-v7a (bare)` および一部の `X86_64` に対応しています。
## その他のリンク
**マネージャーの翻訳を行う場合** https://crowdin.com/project/SukiSU-Ultra
- [その他パッチ済み GKI](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS) ZRAM パッチ、KPM、susfs が含まれています...
- [パッチの少ない GKI](https://github.com/MiRinFork/GKI_SukiSU_SUSFS/releases) susfs のみ
- [OnePlus](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)
## 使い方
### Universal GKI
**すべて**参照してください https://kernelsu.org/ja_JP/guide/installation.html
> [!Note]
>
> 1. Xiaomi、Redmi、Samsung などの GKI 2.0 を搭載したデバイス向け (Meizu、OnePlus、Zenith、Oppo などカーネルが変更されているメーカーを除く)
> 2. GKI のビルドは[その他のリンク](#その他のリンク)から入手できます。デバイスのカーネルバージョンを確認してください。ダウンロード後に TWRP またはカーネルフラッシュツールを使用して AnyKernel3 の接頭辞を持つ zip ファイルをフラッシュしてください。Pixel のユーザーは、パッチの少ない GKI を使用する必要があります。
> 3. 接頭辞のない .zip アーカイブは圧縮されていません。.gz の接頭辞は Tenguet モデルで使用される圧縮になります。
### OnePlus
1. `その他のリンク`の項目に記載されているリンクを開き、デバイス情報を使用してカスタマイズされたカーネルをビルドし、AnyKernel3 の接頭辞を持つ .zip ファイルをフラッシュします。
> [!Note]
>
> - 5.10、5.15、6.1、6.6 などのカーネルバージョンの最初の 2 文字のみを入力する必要があります。
> - SoC のコードネームは自分で検索してください。通常は、数字がなく英語表記のみです。
> - ブランチと構成ファイルは、OnePlus オープンソースカーネルリポジトリから見つけることができます。
## 機能
1. カーネルベースな `su` および root アクセスの管理。
2. [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) モジュールシステムではなく、 5ec1cff 氏の [Magic Mount](https://github.com/5ec1cff/KernelSU) に基づいています。
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージ内にロックします。
4. 非 GKI / GKI 1.0 の対応を復活
5. その他のカスタマイズ
6. KPM カーネルモジュールに対応
## トラブルシューティング
1. KernelSU Manager のアンインストールが停止してしまう → com.sony.playmemories.mobile のアプリをアンインストールしてください。
## ライセンス
- 「kernel」のディレクトリ内のファイルは [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) のライセンスに基づいています。
- アニメキャラクター画像とスタンプを含むこれらのファイルの `ic_launcher(?!.*alt.*).*` は[怡子曰曰](https://space.bilibili.com/10545509)によって著作権保護されており、画像の Brand Intellectual Property は[明风 OuO](https://space.bilibili.com/274939213)によって所有され、ベクター化は @MiRinChan によって行われています。 これらのファイルを使用する前に、[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt)を遵守することに加えて、アートコンテンツを使用するために前の 2 人の作者から許可を得る必要があります。
- 上記のファイルまたはディレクトリを除き、その他のすべての部分は[GPL-3.0 以降](https://www.gnu.org/licenses/gpl-3.0.html)です。
## スポンサーシップの一覧
- [Ktouls](https://github.com/Ktouls) 応援してくれてありがとう
- [zaoqi123](https://github.com/zaoqi123) ミルクティーを買ってあげるのも良い考えですね
- [wswzgdg](https://github.com/wswzgdg) このプロジェクトにご支援いただき、ありがとうございます
- [yspbwx2010](https://github.com/yspbwx2010) ありがとうございます
- [DARKWWEE](https://github.com/DARKWWEE) ラオスから 100 USDT の支援に感謝します
- [Saksham Singla](https://github.com/TypeFlu) ウェブサイトの提供とメンテナンス
- [OukaroMF](https://github.com/OukaroMF) ウェブサイトのドメインと寄付
## 貢献者
- [KernelSU](https://github.com/tiann/KernelSU): オリジナルのプロジェクト
- [MKSU](https://github.com/5ec1cff/KernelSU): 使用しているプロジェクト
- [RKSU](https://github.com/rsuntk/KernelsU): このプロジェクトのカーネルを使用した非 GKI デバイスのサポートの再導入
- [susfs](https://gitlab.com/simonpunk/susfs4ksu): susfs ファイルシステムの使用
- [KernelSU](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): いくつかの root キットユーティリティ
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch はカーネルモジュールの APatch 実装の重要な部分での活用

View File

@@ -1,6 +1,6 @@
# SukiSU Ultra # SukiSU Ultra
**Türkçe** | [简体中文](README.md) | [English](README-en.md) | [日本語](README-ja.md) [English](../README.md) | [简体中文](../zh/README.md) | [日本語](../ja/README.md) | **Türkçe**
[KernelSU](https://github.com/tiann/KernelSU) tabanlı Android cihaz root çözümü [KernelSU](https://github.com/tiann/KernelSU) tabanlı Android cihaz root çözümü
@@ -28,7 +28,7 @@ curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kern
## susfs Nasıl Entegre Edilir ## susfs Nasıl Entegre Edilir
1. Doğrudan susfs-main veya susfs-* dalını kullanın, susfs entegrasyonuna gerek yok 1. Doğrudan susfs-main veya susfs-\* dalını kullanın, susfs entegrasyonuna gerek yok
``` ```
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-main
@@ -121,7 +121,7 @@ Lütfen **tümünü** https://kernelsu.org/zh_CN/guide/installation.html adresin
## Lisans ## Lisans
- `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır. - `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansı altındadır.
- Anime karakter ifadeleri içeren `ic_launcher(?!.*alt.*).*` dosyalarının görüntüleri [五十根大虾仁](https://space.bilibili.com/370927) tarafından telif hakkıyla korunmaktadır, görüntülerdeki Marka Fikri Mülkiyeti [明风 OuO](https://space.bilibili.com/274939213)'ye aittir ve vektörleştirme @MiRinChan tarafından yapılmıştır. Bu dosyaları kullanmadan önce, [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) ile uyumlu olmanın yanı sıra, bu sanatsal içerikleri kullanmak için iki yazarın yetkilendirmesine de uymanız gerekir. - Anime karakter ifadeleri içeren `ic_launcher(?!.*alt.*).*` dosyalarının görüntüleri [怡子曰曰](https://space.bilibili.com/10545509) tarafından telif hakkıyla korunmaktadır, görüntülerdeki Marka Fikri Mülkiyeti [明风 OuO](https://space.bilibili.com/274939213)'ye aittir ve vektörleştirme @MiRinChan tarafından yapılmıştır. Bu dosyaları kullanmadan önce, [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) ile uyumlu olmanın yanı sıra, bu sanatsal içerikleri kullanmak için iki yazarın yetkilendirmesine de uymanız gerekir.
- Yukarıda belirtilen dosyalar veya dizinler hariç, diğer tüm parçalar [GPL-3.0 veya üzeri](https://www.gnu.org/licenses/gpl-3.0.html)'dir. - Yukarıda belirtilen dosyalar veya dizinler hariç, diğer tüm parçalar [GPL-3.0 veya üzeri](https://www.gnu.org/licenses/gpl-3.0.html)'dir.
## Afdian Bağlantısı ## Afdian Bağlantısı

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="128"
height="128"
viewBox="0 0 128 128"
version="1.1"
id="svg1"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="zakomonochrome-128.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="2.6185048"
inkscape:cx="59.957881"
inkscape:cy="71.032903"
inkscape:window-width="1280"
inkscape:window-height="696"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="图层 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;paint-order:fill markers stroke;fill-opacity:1"
id="rect1"
width="128"
height="128"
x="0"
y="0"
rx="7.772471"
ry="7.772471" />
<path
id="path101"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:4.27504;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="m 42.510282,81.796052 c 0,0 -7.224141,-5.638356 -10.043315,-9.338525 M 14.847106,81.97224 25.41902,71.576535 m 0.17619,-6.695549 2.819179,19.910444 M 11.675534,73.338532 38.281518,71.047931 M 43.567475,62.7666 34.40515,62.942814 M 34.22896,62.590425 33.524162,48.494537 m -18.500855,1.58577 17.972249,-1.409582 m -11.8053,-5.462154 0.352397,18.853251"
inkscape:label="杂" />
<path
id="path111"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:3.94824;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="M 55.912937,82.876745 79.671596,81.412163 M 59.330273,75.391135 74.952411,74.089291 m -9.43837,-14.157553 1.139102,14.645756 m -8.299247,-7.160159 16.273048,-1.464569 m 0.650926,8.136525 0.325472,-14.808482 m -0.162747,0.162739 -17.900363,0.976379 m 0,-0.162738 1.952774,14.645756 m 12.042061,-21.154974 1.464576,-6.346492 m 0,-0.650928 -12.042063,0.650928 m -0.650918,6.509218 0.325459,-8.787441"
inkscape:label="鱼" />
<path
d="m 95.08569,51.121163 c -1.90515,0.116064 -3.64694,0.97349 -4.86738,2.391307 -1.34538,1.56738 -1.91476,3.733159 -1.59523,6.070852 0.40842,2.982962 2.1502,6.17135 5.13887,9.411078 0.63424,0.68546 1.08109,1.129773 1.98202,1.967071 1.58321,1.469144 3.01507,2.634638 4.9875,4.052454 0.70392,0.50905 2.09253,1.453525 2.61627,1.781734 l 0.15133,0.09594 0.22103,-0.140663 c 0.80481,-0.515755 2.23909,-1.504852 3.08956,-2.130057 3.21689,-2.364488 5.79232,-4.737902 7.70228,-7.100167 3.09676,-3.831409 4.4133,-7.562359 3.80549,-10.773058 -0.42043,-2.210414 -1.82588,-4.039057 -3.81992,-4.967887 -0.85767,-0.399664 -1.69132,-0.607312 -2.6355,-0.656431 -1.22285,-0.0647 -2.42648,0.178619 -3.57485,0.721182 -1.95561,0.922124 -3.58927,2.719503 -4.61752,5.081755 -0.072,0.165235 -0.1394,0.310355 -0.14895,0.319295 -0.0312,0.02902 -0.0648,-0.02679 -0.19458,-0.330457 -0.30752,-0.714476 -0.91055,-1.752718 -1.38382,-2.377871 -0.4853,-0.645282 -1.2661,-1.431214 -1.84749,-1.862143 -1.50155,-1.114153 -3.26013,-1.658924 -5.00914,-1.553996 z"
id="path1-4"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.00231605" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

101
docs/zh/README.md Normal file
View File

@@ -0,0 +1,101 @@
<img align='right' src='zakomonochrome-128.svg' width='100px' alt="logo">
# SukiSU Ultra
[English](../README.md) | **简体中文** | [日本語](../ja/README.md) | [Türkçe](../tr/README.md)
一个 Android 上基于内核的 root 方案,由 [`tiann/KernelSU`](https://github.com/tiann/KernelSU) 分叉而来,添加了一些有趣的变更。
[![最新发行](https://img.shields.io/github/v/release/SukiSU-Ultra/SukiSU-Ultra?label=Release&logo=github)](https://github.com/tiann/KernelSU/releases/latest)
[![频道](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/Sukiksu)
[![协议: 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 协议](https://img.shields.io/github/license/tiann/KernelSU?logo=gnu)](/LICENSE)
## 特性
1. 基于内核的 `su` 和权限管理。
2. 基于 [Magic Mount](https://github.com/5ec1cff/KernelSU) 的模块系统。
3. [App Profile](https://kernelsu.org/zh_CN/guide/app-profile.html): 把 Root 权限关进笼子里。
4. 支持 non-GKI 与 GKI 1.0。
5. KPM 支持
6. 可调整管理器外观,可自定义 susfs 配置。
## 兼容状态
- KernelSU 官方支持 GKI 2.0 的设备(内核版本 5.10 以上)。
- 旧内核也是兼容的(最低 4.14+),不过需要自己编译内核。
- 通过更多的反向移植KernelSU 可以支持 3.x 内核3.4-3.18)。
- 目前支持架构 : `arm64-v8a``armeabi-v7a (bare)``X86_64`
## 安装指导
查看 [`guide/installation.md`](guide/installation.md)
## 集成指导
查看 [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
## 参与翻译
要将 SukiSU 翻译成您的语言,或完善现有的翻译,请使用 [Crowdin](https://crowdin.com/project/SukiSU-Ultra).
## KPM 支持
- 基于 KernelPatch 开发,移除了与 KernelSU 重复的功能。
- 正在进行WIP通过集成附加功能来扩展 APatch 兼容性,以确保跨不同实现的兼容性。
**开源仓库**: [https://github.com/ShirkNeko/SukiSU_KernelPatch_patch](https://github.com/ShirkNeko/SukiSU_KernelPatch_patch)
**KPM 模板**: [https://github.com/udochina/KPM-Build-Anywhere](https://github.com/udochina/KPM-Build-Anywhere)
> [!Note]
>
> 1. 需要 `CONFIG_KPM=y`
> 2. Non-GKI 设备需要 `CONFIG_KALLSYMS=y` and `CONFIG_KALLSYMS_ALL=y`
> 3. 对于低于 `4.19` 的内核,需要从 `4.19` 的 `set_memory.h` 进行反向移植。
## 故障排除
1. 卸载管理器后系统卡住?
卸载 _com.sony.playmemories.mobile_
## 许可证
- 目录 `kernel` 下所有文件为 [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)。
- 有动漫人物图片表情包的这些文件 `ic_launcher(?!.*alt.*).*` 的图像版权为[怡子曰曰](https://space.bilibili.com/10545509)所有,图像中的知识产权由[明风 OuO](https://space.bilibili.com/274939213)所有,矢量化由 @MiRinChan 完成,在使用这些文件之前,除了必须遵守 [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt) 以外,还需要遵守向前两者索要使用这些艺术内容的授权。
- 除上述文件及目录的其他部分均为 [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html)。
## 赞助
- [ShirkNeko](https://afdian.com/a/shirkneko) (SukiSU 主要维护者)
- [weishu](https://github.com/sponsors/tiann) (KernelSU 作者)
## ShirkNeko 的赞助列表
- [Ktouls](https://github.com/Ktouls) 非常感谢你给我带来的支持
- [zaoqi123](https://github.com/zaoqi123) 请我喝奶茶也不错
- [wswzgdg](https://github.com/wswzgdg) 非常感谢对此项目的支持
- [yspbwx2010](https://github.com/yspbwx2010) 非常感谢
- [DARKWWEE](https://github.com/DARKWWEE) 感谢老哥的 100 USDT
- [Saksham Singla](https://github.com/TypeFlu) 网站的提供以及维护
- [OukaroMF](https://github.com/OukaroMF) 网站域名捐赠
## 鸣谢
- [KernelSU](https://github.com/tiann/KernelSU): 上游
- [MKSU](https://github.com/5ec1cff/KernelSU): 魔法坐骑支持
- [RKSU](https://github.com/rsuntk/KernelsU): non-GKI 支持
- [susfs](https://gitlab.com/simonpunk/susfs4ksu): 隐藏内核补丁以及用户空间模组的 KernelSU 附件
- [KernelPatch](https://github.com/bmax121/KernelPatch): KernelPatch 是内核模块 APatch 实现的关键部分
<details>
<summary>KernelSU 的鸣谢</summary>
- [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 技巧。
</details>

View File

@@ -0,0 +1,91 @@
# 集成指导
SukiSU 可以集成到 GKI 和 non-GKI 内核中,并且已反向移植到 4.14 版本。
<!-- 应该是 3.4 版本,但 backslashxx 的 syscall manual hook 无法在 SukiSU 中使用-->
有些 OEM 定制可能导致多达 50% 的内核代码超出内核树代码,而非来自上游 Linux 内核或 ACK。因此non-GKI 内核的定制特性导致了严重的内核碎片化,而且我们缺乏构建它们的通用方法。因此,我们无法提供 non-GKI 内核的启动映像。
前提条件:开源的、可启动的内核。
## Hook 方法
1. **KPROBES hook:**
- GKI kernels 的默认 hook 方法。
- 需要 `# CONFIG_KSU_MANUAL_HOOK is not set`(未设定) & `CONFIG_KPROBES=y`
- 用作可加载的内核模块 (LKM).
2. **Manual hook:**
<!-- - backslashxx's syscall manual hook: https://github.com/backslashxx/KernelSU/issues/5 (v1.5 version is not available at the moment, if you want to use it, please use v1.4 version, or standard KernelSU hooks)-->
- 需要 `CONFIG_KSU_MANUAL_HOOK=y`
- 需要 [`guide/how-to-integrate.md`](guide/how-to-integrate.md)
- 需要 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source)
<!-- This part refer to [rsuntk/KernelSU](https://github.com/rsuntk/KernelSU). -->
如果您能够构建可启动内核,有两种方法可以将 KernelSU 集成到内核源代码中:
1. 使用 `kprobe` 自动集成
2. 手动集成
## 与 kprobe 集成
适用:
- GKI 内核
不适用:
- non-GKI 内核
KernelSU 使用 kprobe 机制来做内核的相关 hook如果 _kprobe_ 可以在你编译的内核中正常运行,那么推荐用这个方法来集成。
请参阅此文档 [https://github.com/~](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#integrate-with-kprobe)。虽然标题为“适用于 non-GKI”但仅适用于 GKI。
替换 KernelSU 添加到内核源代码树的步骤的执行命令为:
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
## 手动修改内核源代码
适用:
- GKI 内核
- non-GKI 内核
请参考此文档 [https://github.com/~ (non-GKI 内核集成)](https://github.com/tiann/KernelSU/blob/main/website/docs/guide/how-to-integrate-for-non-gki.md#manually-modify-the-kernel-source) 和 [https://github.com/~ (GKI 内核构建)](https://kernelsu.org/zh_CN/guide/how-to-build.html) 进行手动集成。虽然第一个链接的标题是“适用于 non-GKI”但它也适用于 GKI。两者都可以正常工作。
还有另一种集成方法,但是仍在开发中。
<!-- 这是 backslashxx 的syscall manual hook但目前无法使用。 -->
将 KernelSUSukiSU添加到内核源代码树的步骤的运行命令将被替换为
### GKI 内核
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s main
```
### non-GKI 内核
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s nongki
```
### 带有 susfs 的 GKI / non-GKI 内核(实验)
```sh
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s susfs-{{branch}}
```
分支:
- `main` (susfs-main)
- `test` (susfs-test)
- 版本号 (例如: susfs-1.5.7, 你需要在 [分支](https://github.com/SukiSU-Ultra/SukiSU-Ultra/branches) 里找到它)

View File

@@ -0,0 +1,34 @@
# 安装指导
您可以前往 [KernelSU 文档 - 安装](https://kernelsu.org/guide/installation.html) 获取有关如何安装的参考,这里只是额外的说明。
## 通过加载可加载内核模块 (LKM) 进行安装
请参阅 [KernelSU 文档 - LKM 安装](https://kernelsu.org/guide/installation.html#lkm-installation)
**Android™**(商标,意为获得 Google 移动服务的许可12 开始,搭载内核版本 5.10 或更高版本的设备必须搭载 GKI 内核。因此你或许可以使用 LKM 模式。
## 通过安装内核进行安装
请参阅 [KernelSU 文档 - GKI 模式安装](https://kernelsu.org/guide/installation.html#gki-mode-installation)
我们提供预编译的内核供您使用:
- [ShirkNeko 内核](https://github.com/ShirkNeko/GKI_KernelSU_SUSFS)(添加了 ZRAM 压缩算法补丁、susfs 文件和 KPM 文件。适用于很多设备。)
- [MiRinFork 内核](https://github.com/MiRinFork/GKI_SukiSU_SUSFS)(添加了 susfs 文件和 KPM 文件。最接近 GKI 的内核,适用于大多数设备。)
虽然某些设备可以使用 LKM 模式安装,但无法使用 GKI 内核将其安装到设备上;因此,需要手动修改内核进行编译。例如:
- 欧珀(一加、真我)
- 魅族
此外,我们还为您的 OnePlus 设备提供预编译的内核:
- [ShirkNeko/Action_OnePlus_MKSU_SUSFS](https://github.com/ShirkNeko/Action_OnePlus_MKSU_SUSFS)(添加 ZRAM 压缩算法补丁、susfs 和 KPM。
使用上面的链接Fork 到 GitHub Action填写构建参数进行编译最后将 zip 文件以 AnyKernel3 后缀上传到 GitHub Action。
> [!Note]
>
> - 使用时,您只需填写版本号的前两部分,例如 `5.10`、`6.1`...
> - 使用前请确保您了解处理器名称、内核版本等信息。

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="128"
height="128"
viewBox="0 0 128 128"
version="1.1"
id="svg1"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="zakomonochrome-128.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
inkscape:zoom="2.6185048"
inkscape:cx="59.957881"
inkscape:cy="71.032903"
inkscape:window-width="1280"
inkscape:window-height="696"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="图层 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;paint-order:fill markers stroke;fill-opacity:1"
id="rect1"
width="128"
height="128"
x="0"
y="0"
rx="7.772471"
ry="7.772471" />
<path
id="path101"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:4.27504;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="m 42.510282,81.796052 c 0,0 -7.224141,-5.638356 -10.043315,-9.338525 M 14.847106,81.97224 25.41902,71.576535 m 0.17619,-6.695549 2.819179,19.910444 M 11.675534,73.338532 38.281518,71.047931 M 43.567475,62.7666 34.40515,62.942814 M 34.22896,62.590425 33.524162,48.494537 m -18.500855,1.58577 17.972249,-1.409582 m -11.8053,-5.462154 0.352397,18.853251"
inkscape:label="杂" />
<path
id="path111"
style="fill:#ffffff;fill-opacity:0.734285;stroke:#000000;stroke-width:3.94824;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.3;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
d="M 55.912937,82.876745 79.671596,81.412163 M 59.330273,75.391135 74.952411,74.089291 m -9.43837,-14.157553 1.139102,14.645756 m -8.299247,-7.160159 16.273048,-1.464569 m 0.650926,8.136525 0.325472,-14.808482 m -0.162747,0.162739 -17.900363,0.976379 m 0,-0.162738 1.952774,14.645756 m 12.042061,-21.154974 1.464576,-6.346492 m 0,-0.650928 -12.042063,0.650928 m -0.650918,6.509218 0.325459,-8.787441"
inkscape:label="鱼" />
<path
d="m 95.08569,51.121163 c -1.90515,0.116064 -3.64694,0.97349 -4.86738,2.391307 -1.34538,1.56738 -1.91476,3.733159 -1.59523,6.070852 0.40842,2.982962 2.1502,6.17135 5.13887,9.411078 0.63424,0.68546 1.08109,1.129773 1.98202,1.967071 1.58321,1.469144 3.01507,2.634638 4.9875,4.052454 0.70392,0.50905 2.09253,1.453525 2.61627,1.781734 l 0.15133,0.09594 0.22103,-0.140663 c 0.80481,-0.515755 2.23909,-1.504852 3.08956,-2.130057 3.21689,-2.364488 5.79232,-4.737902 7.70228,-7.100167 3.09676,-3.831409 4.4133,-7.562359 3.80549,-10.773058 -0.42043,-2.210414 -1.82588,-4.039057 -3.81992,-4.967887 -0.85767,-0.399664 -1.69132,-0.607312 -2.6355,-0.656431 -1.22285,-0.0647 -2.42648,0.178619 -3.57485,0.721182 -1.95561,0.922124 -3.58927,2.719503 -4.61752,5.081755 -0.072,0.165235 -0.1394,0.310355 -0.14895,0.319295 -0.0312,0.02902 -0.0648,-0.02679 -0.19458,-0.330457 -0.30752,-0.714476 -0.91055,-1.752718 -1.38382,-2.377871 -0.4853,-0.645282 -1.2661,-1.431214 -1.84749,-1.862143 -1.50155,-1.114153 -3.26013,-1.658924 -5.00914,-1.553996 z"
id="path1-4"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.00231605" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -24,5 +24,6 @@ config KPM
Enabling this option will activate the KPM feature of SukiSU. Enabling this option will activate the KPM feature of SukiSU.
This option is suitable for scenarios where you need to force KPM to be enabled. This option is suitable for scenarios where you need to force KPM to be enabled.
but it may affect system stability. but it may affect system stability.
select KALLSYMS
select KALLSYMS_ALL
endmenu endmenu

View File

@@ -22,29 +22,53 @@ obj-$(CONFIG_KPM) += kpm/
REPO_OWNER := SukiSU-Ultra REPO_OWNER := SukiSU-Ultra
REPO_NAME := SukiSU-Ultra REPO_NAME := SukiSU-Ultra
REPO_BRANCH := main REPO_BRANCH := main
KSU_VERSION_API := 3.1.8
GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git
CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl
KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p') KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -s "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
KSU_GITHUB_VERSION_COMMIT := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p')
ifeq ($(KSU_GITHUB_VERSION),) LOCAL_GIT_EXISTS := $(shell test -e $(srctree)/$(src)/../.git && echo 1 || echo 0)
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
define get_ksu_version_full
v$1-$(shell cd $(srctree)/$(src); $(GIT_BIN) rev-parse --short=8 HEAD)@$(shell cd $(srctree)/$(src); $(GIT_BIN) rev-parse --abbrev-ref HEAD)
endef
ifeq ($(KSU_GITHUB_VERSION_COMMIT),)
ifeq ($(LOCAL_GIT_EXISTS),1)
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow) $(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_LOCAL_VERSION := $(shell cd $(srctree)/$(src); $(GIT_BIN) rev-list --count HEAD) KSU_LOCAL_VERSION := $(shell cd $(srctree)/$(src); $(GIT_BIN) rev-list --count $(REPO_BRANCH))
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_LOCAL_VERSION) + 700)) KSU_VERSION := $(shell expr 10000 + $(KSU_LOCAL_VERSION) + 700)
$(info -- SukiSU-Ultra version (local .git): $(KSU_VERSION)) $(info -- $(REPO_NAME) version (local .git): $(KSU_VERSION))
else else
$(eval KSU_VERSION := 13000) KSU_VERSION := 13000
$(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION)) $(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION))
endif endif
else else
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_GITHUB_VERSION) + 700)) KSU_VERSION := $(shell expr 10000 + $(KSU_GITHUB_VERSION_COMMIT) + 700)
$(info -- SukiSU-Ultra version (GitHub): $(KSU_VERSION)) $(info -- $(REPO_NAME) version (GitHub): $(KSU_VERSION))
endif
ifeq ($(KSU_GITHUB_VERSION),)
ifeq ($(LOCAL_GIT_EXISTS),1)
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_VERSION_FULL := $(call get_ksu_version_full,$(KSU_VERSION_API))
$(info -- $(REPO_NAME) version (local .git): $(KSU_VERSION_FULL))
$(info -- $(REPO_NAME) Formatted version (local .git): $(KSU_VERSION))
else
KSU_VERSION_FULL := v$(KSU_VERSION_API)-$(REPO_NAME)-unknown@unknown
$(warning -- $(REPO_NAME) version: $(KSU_VERSION_FULL))
endif
else
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_VERSION_FULL := $(call get_ksu_version_full,$(KSU_GITHUB_VERSION))
$(info -- $(REPO_NAME) version (Github): $(KSU_VERSION_FULL))
endif endif
$(info -- SukiSU-Ultra version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\"
ifndef KSU_EXPECTED_SIZE ifndef KSU_EXPECTED_SIZE
KSU_EXPECTED_SIZE := 0x35c KSU_EXPECTED_SIZE := 0x35c

View File

@@ -4,6 +4,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/workqueue.h>
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#endif #endif
@@ -17,13 +18,483 @@
#include "apk_sign.h" #include "apk_sign.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "kernel_compat.h" #include "kernel_compat.h"
#include "manager_sign.h"
// Expected sizes and hashes for various APK signatures
#define DYNAMIC_SIGN_FILE_MAGIC 0x7f445347 // 'DSG', u32
#define DYNAMIC_SIGN_FILE_VERSION 1 // u32
#define KERNEL_SU_DYNAMIC_SIGN "/data/adb/ksu/.dynamic_sign"
#define MAX_MANAGERS 2
static struct manager_info active_managers[MAX_MANAGERS];
static DEFINE_SPINLOCK(managers_lock);
static struct dynamic_sign_config dynamic_sign = {
.size = 0x300,
.hash = "0000000000000000000000000000000000000000000000000000000000000000",
.is_set = 0
};
static DEFINE_SPINLOCK(dynamic_sign_lock);
static struct work_struct ksu_save_dynamic_sign_work;
static struct work_struct ksu_load_dynamic_sign_work;
static struct work_struct ksu_clear_dynamic_sign_work;
static inline bool is_dynamic_sign_enabled(void)
{
unsigned long flags;
bool enabled;
spin_lock_irqsave(&dynamic_sign_lock, flags);
enabled = dynamic_sign.is_set;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
return enabled;
}
void ksu_add_manager(uid_t uid, int signature_index)
{
unsigned long flags;
int i;
if (!is_dynamic_sign_enabled()) {
pr_info("Dynamic sign not enabled, skipping multi-manager add\n");
return;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
active_managers[i].signature_index = signature_index;
spin_unlock_irqrestore(&managers_lock, flags);
pr_info("Updated manager uid=%d, signature_index=%d\n", uid, signature_index);
return;
}
}
for (i = 0; i < MAX_MANAGERS; i++) {
if (!active_managers[i].is_active) {
active_managers[i].uid = uid;
active_managers[i].signature_index = signature_index;
active_managers[i].is_active = true;
spin_unlock_irqrestore(&managers_lock, flags);
pr_info("Added manager uid=%d, signature_index=%d\n", uid, signature_index);
return;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
pr_warn("Failed to add manager, no free slots\n");
}
void ksu_remove_manager(uid_t uid)
{
unsigned long flags;
int i;
if (!is_dynamic_sign_enabled()) {
return;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
active_managers[i].is_active = false;
pr_info("Removed manager uid=%d\n", uid);
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
bool ksu_is_any_manager(uid_t uid)
{
unsigned long flags;
bool is_manager = false;
int i;
if (!is_dynamic_sign_enabled()) {
return false;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
is_manager = true;
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
return is_manager;
}
int ksu_get_manager_signature_index(uid_t uid)
{
unsigned long flags;
int signature_index = -1;
int i;
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
return 1;
}
if (!is_dynamic_sign_enabled()) {
return -1;
}
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active && active_managers[i].uid == uid) {
signature_index = active_managers[i].signature_index;
break;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
return signature_index;
}
static void clear_all_managers(void)
{
unsigned long flags;
int i;
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS; i++) {
if (active_managers[i].is_active) {
pr_info("Clearing manager uid=%d due to dynamic_sign disable\n",
active_managers[i].uid);
active_managers[i].is_active = false;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
static void do_save_dynamic_sign(struct work_struct *work)
{
u32 magic = DYNAMIC_SIGN_FILE_MAGIC;
u32 version = DYNAMIC_SIGN_FILE_VERSION;
struct dynamic_sign_config config_to_save;
loff_t off = 0;
unsigned long flags;
struct file *fp;
spin_lock_irqsave(&dynamic_sign_lock, flags);
config_to_save = dynamic_sign;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
if (!config_to_save.is_set) {
pr_info("Dynamic sign config not set, skipping save\n");
return;
}
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) {
pr_err("save_dynamic_sign create file failed: %ld\n", PTR_ERR(fp));
return;
}
if (ksu_kernel_write_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic)) {
pr_err("save_dynamic_sign write magic failed.\n");
goto exit;
}
if (ksu_kernel_write_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("save_dynamic_sign write version failed.\n");
goto exit;
}
if (ksu_kernel_write_compat(fp, &config_to_save, sizeof(config_to_save), &off) != sizeof(config_to_save)) {
pr_err("save_dynamic_sign write config failed.\n");
goto exit;
}
pr_info("Dynamic sign config saved successfully\n");
exit:
filp_close(fp, 0);
}
// Loading dynamic signatures from persistent storage
static void do_load_dynamic_sign(struct work_struct *work)
{
loff_t off = 0;
ssize_t ret = 0;
struct file *fp = NULL;
u32 magic;
u32 version;
struct dynamic_sign_config loaded_config;
unsigned long flags;
int i;
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_RDONLY, 0);
if (IS_ERR(fp)) {
if (PTR_ERR(fp) == -ENOENT) {
pr_info("No saved dynamic sign config found\n");
} else {
pr_err("load_dynamic_sign open file failed: %ld\n", PTR_ERR(fp));
}
return;
}
if (ksu_kernel_read_compat(fp, &magic, sizeof(magic), &off) != sizeof(magic) ||
magic != DYNAMIC_SIGN_FILE_MAGIC) {
pr_err("dynamic sign file invalid magic: %x!\n", magic);
goto exit;
}
if (ksu_kernel_read_compat(fp, &version, sizeof(version), &off) != sizeof(version)) {
pr_err("dynamic sign read version failed\n");
goto exit;
}
pr_info("dynamic sign file version: %d\n", version);
ret = ksu_kernel_read_compat(fp, &loaded_config, sizeof(loaded_config), &off);
if (ret <= 0) {
pr_info("load_dynamic_sign read err: %zd\n", ret);
goto exit;
}
if (ret != sizeof(loaded_config)) {
pr_err("load_dynamic_sign read incomplete config: %zd/%zu\n", ret, sizeof(loaded_config));
goto exit;
}
if (loaded_config.size < 0x100 || loaded_config.size > 0x1000) {
pr_err("Invalid saved config size: 0x%x\n", loaded_config.size);
goto exit;
}
if (strlen(loaded_config.hash) != 64) {
pr_err("Invalid saved config hash length: %zu\n", strlen(loaded_config.hash));
goto exit;
}
for (i = 0; i < 64; i++) {
char c = loaded_config.hash[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
pr_err("Invalid saved config hash character at position %d: %c\n", i, c);
goto exit;
}
}
spin_lock_irqsave(&dynamic_sign_lock, flags);
dynamic_sign = loaded_config;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
pr_info("Dynamic sign config loaded: size=0x%x, hash=%.16s...\n",
loaded_config.size, loaded_config.hash);
exit:
filp_close(fp, 0);
}
static bool persistent_dynamic_sign(void)
{
return ksu_queue_work(&ksu_save_dynamic_sign_work);
}
// Clear dynamic sign config file using the same method as do_save_dynamic_sign
static void do_clear_dynamic_sign_file(struct work_struct *work)
{
loff_t off = 0;
struct file *fp;
char zero_buffer[512];
memset(zero_buffer, 0, sizeof(zero_buffer));
fp = ksu_filp_open_compat(KERNEL_SU_DYNAMIC_SIGN, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (IS_ERR(fp)) {
pr_err("clear_dynamic_sign create file failed: %ld\n", PTR_ERR(fp));
return;
}
// Write null bytes to overwrite the file content
if (ksu_kernel_write_compat(fp, zero_buffer, sizeof(zero_buffer), &off) != sizeof(zero_buffer)) {
pr_err("clear_dynamic_sign write null bytes failed.\n");
} else {
pr_info("Dynamic sign config file cleared successfully\n");
}
filp_close(fp, 0);
}
static bool clear_dynamic_sign_file(void)
{
return ksu_queue_work(&ksu_clear_dynamic_sign_work);
}
int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config)
{
unsigned long flags;
int ret = 0;
int i;
if (!config) {
return -EINVAL;
}
switch (config->operation) {
case DYNAMIC_SIGN_OP_SET:
if (config->size < 0x100 || config->size > 0x1000) {
pr_err("invalid size: 0x%x\n", config->size);
return -EINVAL;
}
if (strlen(config->hash) != 64) {
pr_err("invalid hash length: %zu\n", strlen(config->hash));
return -EINVAL;
}
for (i = 0; i < 64; i++) {
char c = config->hash[i];
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))) {
pr_err("invalid hash character at position %d: %c\n", i, c);
return -EINVAL;
}
}
spin_lock_irqsave(&dynamic_sign_lock, flags);
dynamic_sign.size = config->size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash));
#else
strlcpy(dynamic_sign.hash, config->hash, sizeof(dynamic_sign.hash));
#endif
dynamic_sign.is_set = 1;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
persistent_dynamic_sign();
pr_info("dynamic sign updated: size=0x%x, hash=%.16s... (multi-manager enabled)\n",
config->size, config->hash);
break;
case DYNAMIC_SIGN_OP_GET:
// Getting Dynamic Signatures
spin_lock_irqsave(&dynamic_sign_lock, flags);
if (dynamic_sign.is_set) {
config->size = dynamic_sign.size;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(config->hash, dynamic_sign.hash, sizeof(config->hash));
#else
strlcpy(config->hash, dynamic_sign.hash, sizeof(config->hash));
#endif
ret = 0;
} else {
ret = -ENODATA;
}
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
break;
case DYNAMIC_SIGN_OP_CLEAR:
// Clearing dynamic signatures
spin_lock_irqsave(&dynamic_sign_lock, flags);
dynamic_sign.size = 0x300;
strcpy(dynamic_sign.hash, "0000000000000000000000000000000000000000000000000000000000000000");
dynamic_sign.is_set = 0;
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
clear_all_managers();
// Clear file using the same method as save
clear_dynamic_sign_file();
pr_info("Dynamic sign config cleared (multi-manager disabled)\n");
break;
default:
pr_err("Invalid dynamic sign operation: %d\n", config->operation);
return -EINVAL;
}
return ret;
}
bool ksu_load_dynamic_sign(void)
{
return ksu_queue_work(&ksu_load_dynamic_sign_work);
}
void ksu_dynamic_sign_init(void)
{
int i;
INIT_WORK(&ksu_save_dynamic_sign_work, do_save_dynamic_sign);
INIT_WORK(&ksu_load_dynamic_sign_work, do_load_dynamic_sign);
INIT_WORK(&ksu_clear_dynamic_sign_work, do_clear_dynamic_sign_file);
for (i = 0; i < MAX_MANAGERS; i++) {
active_managers[i].is_active = false;
}
pr_info("Dynamic sign initialized with conditional multi-manager support\n");
}
void ksu_dynamic_sign_exit(void)
{
clear_all_managers();
do_save_dynamic_sign(NULL);
pr_info("Dynamic sign exited with persistent storage\n");
}
// Get active managers for multi-manager APKs
int ksu_get_active_managers(struct manager_list_info *info)
{
unsigned long flags;
int i, count = 0;
if (!info) {
return -EINVAL;
}
if (ksu_manager_uid != KSU_INVALID_UID && count < 2) {
info->managers[count].uid = ksu_manager_uid;
info->managers[count].signature_index = 1;
count++;
}
if (is_dynamic_sign_enabled()) {
spin_lock_irqsave(&managers_lock, flags);
for (i = 0; i < MAX_MANAGERS && count < 2; i++) {
if (active_managers[i].is_active) {
info->managers[count].uid = active_managers[i].uid;
info->managers[count].signature_index = active_managers[i].signature_index;
count++;
}
}
spin_unlock_irqrestore(&managers_lock, flags);
}
info->count = count;
return 0;
}
struct sdesc { struct sdesc {
struct shash_desc shash; struct shash_desc shash;
char ctx[]; char ctx[];
}; };
static struct apk_sign_key {
unsigned size;
const char *sha256;
} apk_sign_keys[] = {
{EXPECTED_SIZE, EXPECTED_HASH},
{EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // ShirkNeko/SukiSU
{EXPECTED_SIZE_OTHER, EXPECTED_HASH_OTHER}, // Dynamic Sign
};
static struct sdesc *init_sdesc(struct crypto_shash *alg) static struct sdesc *init_sdesc(struct crypto_shash *alg)
{ {
struct sdesc *sdesc; struct sdesc *sdesc;
@@ -71,53 +542,6 @@ static int ksu_sha256(const unsigned char *data, unsigned int datalen,
return ret; return ret;
} }
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset,
unsigned expected_size, const char *expected_sha256)
{
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length
*offset += 0x4 * 3;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length
*pos += *size4;
*offset += 0x4 + *size4;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
*offset += 0x4 * 2;
if (*size4 == expected_size) {
*offset += *size4;
#define CERT_MAX_LENGTH 1024
char cert[CERT_MAX_LENGTH];
if (*size4 > CERT_MAX_LENGTH) {
pr_info("cert length overlimit\n");
return false;
}
ksu_kernel_read_compat(fp, cert, *size4, pos);
unsigned char digest[SHA256_DIGEST_SIZE];
if (IS_ERR(ksu_sha256(cert, *size4, digest))) {
pr_info("sha256 error\n");
return false;
}
char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
pr_info("sha256: %s, expected: %s\n", hash_str,
expected_sha256);
if (strcmp(expected_sha256, hash_str) == 0) {
return true;
}
}
return false;
}
struct zip_entry_header { struct zip_entry_header {
uint32_t signature; uint32_t signature;
uint16_t version; uint16_t version;
@@ -171,26 +595,103 @@ static bool has_v1_signature_file(struct file *fp)
return false; return false;
} }
static __always_inline bool check_v2_signature(char *path, // Generic Signature Block Verification
unsigned expected_size, static int verify_signature_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index)
const char *expected_sha256) {
int i;
struct apk_sign_key sign_key;
bool signature_valid = false;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length
*offset += 0x4 * 3;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length
*pos += *size4;
*offset += 0x4 + *size4;
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
*offset += 0x4 * 2;
for (i = 0; i < ARRAY_SIZE(apk_sign_keys); i++) {
sign_key = apk_sign_keys[i];
if (i == 2) {
unsigned long flags;
spin_lock_irqsave(&dynamic_sign_lock, flags);
if (dynamic_sign.is_set) {
sign_key.size = dynamic_sign.size;
sign_key.sha256 = dynamic_sign.hash;
}
spin_unlock_irqrestore(&dynamic_sign_lock, flags);
}
if (*size4 != sign_key.size)
continue;
#define CERT_MAX_LENGTH 1024
char cert[CERT_MAX_LENGTH];
if (*size4 > CERT_MAX_LENGTH) {
pr_info("cert length overlimit\n");
continue;
}
loff_t cert_pos = *pos;
ksu_kernel_read_compat(fp, cert, *size4, &cert_pos);
unsigned char digest[SHA256_DIGEST_SIZE];
if (IS_ERR(ksu_sha256(cert, *size4, digest))) {
pr_info("sha256 error\n");
continue;
}
char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
pr_info("sha256: %s, expected: %s, index: %d\n", hash_str, sign_key.sha256, i);
if (strcmp(sign_key.sha256, hash_str) == 0) {
signature_valid = true;
if (matched_index) {
*matched_index = i;
}
break;
}
}
*offset += *size4;
*pos += *size4;
return signature_valid ? 1 : 0;
}
// Generic APK signature parsing
static int parse_apk_signature(char *path, bool check_multi_manager, int *signature_index)
{ {
unsigned char buffer[0x11] = { 0 }; unsigned char buffer[0x11] = { 0 };
u32 size4; u32 size4;
u64 size8, size_of_block; u64 size8, size_of_block;
loff_t pos; loff_t pos;
bool v2_signing_valid = false; bool v2_signing_valid = false;
int v2_signing_blocks = 0; int v2_signing_blocks = 0;
bool v3_signing_exist = false; bool v3_signing_exist = false;
bool v3_1_signing_exist = false; bool v3_1_signing_exist = false;
int matched_index = -1;
int i; int i;
struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0); struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("open %s error.\n", path); pr_err("open %s error.\n", path);
return false; return -1;
}
// If you want to check for multi-manager APK signing, but dynamic signing is not enabled, skip the
if (check_multi_manager && !is_dynamic_sign_enabled()) {
filp_close(fp, 0);
return 0;
} }
// disable inotify for this file // disable inotify for this file
@@ -231,12 +732,12 @@ static __always_inline bool check_v2_signature(char *path,
goto clean; goto clean;
} }
// Parsing the signature block
int loop_count = 0; int loop_count = 0;
while (loop_count++ < 10) { while (loop_count++ < 10) {
uint32_t id; uint32_t id;
uint32_t offset; uint32_t offset;
ksu_kernel_read_compat(fp, &size8, 0x8, ksu_kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length
&pos); // sequence length
if (size8 == size_of_block) { if (size8 == size_of_block) {
break; break;
} }
@@ -244,9 +745,10 @@ static __always_inline bool check_v2_signature(char *path,
offset = 4; offset = 4;
if (id == 0x7109871au) { if (id == 0x7109871au) {
v2_signing_blocks++; v2_signing_blocks++;
v2_signing_valid = int result = verify_signature_block(fp, &size4, &pos, &offset, &matched_index);
check_block(fp, &size4, &pos, &offset, if (result == 1) {
expected_size, expected_sha256); v2_signing_valid = true;
}
} else if (id == 0xf05368c0u) { } else if (id == 0xf05368c0u) {
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73 // http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73
v3_signing_exist = true; v3_signing_exist = true;
@@ -263,20 +765,21 @@ static __always_inline bool check_v2_signature(char *path,
if (v2_signing_blocks != 1) { if (v2_signing_blocks != 1) {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_err("Unexpected v2 signature count: %d\n", pr_err("Unexpected v2 signature count: %d\n", v2_signing_blocks);
v2_signing_blocks);
#endif #endif
v2_signing_valid = false; v2_signing_valid = false;
} }
// Check v1 signatures
if (v2_signing_valid) { if (v2_signing_valid) {
int has_v1_signing = has_v1_signature_file(fp); bool has_v1_signing = has_v1_signature_file(fp);
if (has_v1_signing) { if (has_v1_signing) {
pr_err("Unexpected v1 signature scheme found!\n"); pr_err("Unexpected v1 signature scheme found!\n");
filp_close(fp, 0); filp_close(fp, 0);
return false; return -1;
} }
} }
clean: clean:
filp_close(fp, 0); filp_close(fp, 0);
@@ -284,10 +787,46 @@ clean:
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
pr_err("Unexpected v3 signature scheme found!\n"); pr_err("Unexpected v3 signature scheme found!\n");
#endif #endif
return false; return -1;
} }
return v2_signing_valid; if (v2_signing_valid) {
if (signature_index) {
*signature_index = matched_index;
}
if (check_multi_manager) {
// 1: ShirkNeko/SukiSU, 2: Dynamic Sign
if (matched_index == 1 || matched_index == 2) {
pr_info("Multi-manager APK detected (dynamic_sign enabled): signature_index=%d\n", matched_index);
return 1;
}
return 0;
} else {
// Common manager check: any valid signature will do
return 1;
}
}
return 0;
}
bool ksu_is_multi_manager_apk(char *path, int *signature_index)
{
int result = parse_apk_signature(path, true, signature_index);
return result == 1;
}
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset)
{
int result = verify_signature_block(fp, size4, pos, offset, NULL);
return result == 1;
}
static __always_inline bool check_v2_signature(char *path)
{
int result = parse_apk_signature(path, false, NULL);
return result == 1;
} }
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
@@ -316,5 +855,5 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
bool is_manager_apk(char *path) bool is_manager_apk(char *path)
{ {
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); return check_v2_signature(path);
} }

View File

@@ -2,7 +2,33 @@
#define __KSU_H_APK_V2_SIGN #define __KSU_H_APK_V2_SIGN
#include <linux/types.h> #include <linux/types.h>
#include "ksu.h"
#include "manager.h"
bool is_manager_apk(char *path); bool is_manager_apk(char *path);
struct dynamic_sign_config {
unsigned int size;
char hash[65];
int is_set;
};
struct manager_info {
uid_t uid;
int signature_index;
bool is_active;
};
bool ksu_is_multi_manager_apk(char *path, int *signature_index);
void ksu_add_manager(uid_t uid, int signature_index);
void ksu_remove_manager(uid_t uid);
bool ksu_is_any_manager(uid_t uid);
int ksu_get_manager_signature_index(uid_t uid);
int ksu_get_active_managers(struct manager_list_info *info);
int ksu_handle_dynamic_sign(struct dynamic_sign_user_config *config);
void ksu_dynamic_sign_init(void);
void ksu_dynamic_sign_exit(void);
bool ksu_load_dynamic_sign(void);
#endif #endif

View File

@@ -250,6 +250,16 @@ static void nuke_ext4_sysfs() {
static inline void nuke_ext4_sysfs() { } static inline void nuke_ext4_sysfs() { }
#endif #endif
static bool is_system_bin_su()
{
// YES in_execve becomes 0 when it succeeds.
if (!current->mm || current->in_execve)
return false;
// quick af check
return (current->mm->exe_file && !strcmp(current->mm->exe_file->f_path.dentry->d_name.name, "su"));
}
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5) unsigned long arg4, unsigned long arg5)
{ {
@@ -272,7 +282,8 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
bool from_root = 0 == current_uid().val; bool from_root = 0 == current_uid().val;
bool from_manager = is_manager(); bool from_manager = is_manager();
if (!from_root && !from_manager) { if (!from_root && !from_manager
&& !(is_allow_su() && is_system_bin_su())) {
// only root or manager can access this interface // only root or manager can access this interface
return 0; return 0;
} }
@@ -308,7 +319,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
if (copy_to_user(arg3, &version, sizeof(version))) { if (copy_to_user(arg3, &version, sizeof(version))) {
pr_err("prctl reply error, cmd: %lu\n", arg2); pr_err("prctl reply error, cmd: %lu\n", arg2);
} }
u32 version_flags = 0; u32 version_flags = 2;
#ifdef MODULE #ifdef MODULE
version_flags |= 0x1; version_flags |= 0x1;
#endif #endif
@@ -319,6 +330,72 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0; return 0;
} }
// Allow root manager to get full version strings
if (arg2 == CMD_GET_FULL_VERSION) {
char ksu_version_full[KSU_FULL_VERSION_STRING] = {0};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
strscpy(ksu_version_full, KSU_VERSION_FULL, KSU_FULL_VERSION_STRING);
#else
strlcpy(ksu_version_full, KSU_VERSION_FULL, KSU_FULL_VERSION_STRING);
#endif
if (copy_to_user((void __user *)arg3, ksu_version_full, KSU_FULL_VERSION_STRING)) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
return -EFAULT;
}
return 0;
}
// Allow the root manager to configure dynamic signatures
if (arg2 == CMD_DYNAMIC_SIGN) {
if (!from_root && !from_manager) {
return 0;
}
struct dynamic_sign_user_config config;
if (copy_from_user(&config, (void __user *)arg3, sizeof(config))) {
pr_err("copy dynamic sign config failed\n");
return 0;
}
int ret = ksu_handle_dynamic_sign(&config);
if (ret == 0 && config.operation == DYNAMIC_SIGN_OP_GET) {
if (copy_to_user((void __user *)arg3, &config, sizeof(config))) {
pr_err("copy dynamic sign config back failed\n");
return 0;
}
}
if (ret == 0) {
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("dynamic_sign: prctl reply error\n");
}
}
return 0;
}
// Allow root manager to get active managers
if (arg2 == CMD_GET_MANAGERS) {
if (!from_root && !from_manager) {
return 0;
}
struct manager_list_info manager_info;
int ret = ksu_get_active_managers(&manager_info);
if (ret == 0) {
if (copy_to_user((void __user *)arg3, &manager_info, sizeof(manager_info))) {
pr_err("copy manager list failed\n");
return 0;
}
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("get_managers: prctl reply error\n");
}
}
return 0;
}
if (arg2 == CMD_REPORT_EVENT) { if (arg2 == CMD_REPORT_EVENT) {
if (!from_root) { if (!from_root) {
return 0; return 0;
@@ -330,6 +407,10 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
post_fs_data_lock = true; post_fs_data_lock = true;
pr_info("post-fs-data triggered\n"); pr_info("post-fs-data triggered\n");
on_post_fs_data(); on_post_fs_data();
// Initializing Dynamic Signatures
ksu_dynamic_sign_init();
ksu_load_dynamic_sign();
pr_info("Dynamic sign config loaded during post-fs-data\n");
} }
break; break;
} }
@@ -418,6 +499,30 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0; return 0;
} }
if (arg2 == CMD_ENABLE_SU) {
bool enabled = (arg3 != 0);
if (enabled == ksu_su_compat_enabled) {
pr_info("cmd enable su but no need to change.\n");
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (enabled) {
ksu_sucompat_init();
} else {
ksu_sucompat_exit();
}
ksu_su_compat_enabled = enabled;
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
#ifdef CONFIG_KPM #ifdef CONFIG_KPM
// ADD: 添加KPM模块控制 // ADD: 添加KPM模块控制
if(sukisu_is_kpm_control_code(arg2)) { if(sukisu_is_kpm_control_code(arg2)) {
@@ -492,30 +597,6 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0; return 0;
} }
if (arg2 == CMD_ENABLE_SU) {
bool enabled = (arg3 != 0);
if (enabled == ksu_su_compat_enabled) {
pr_info("cmd enable su but no need to change.\n");
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {// return the reply_ok directly
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
if (enabled) {
ksu_sucompat_init();
} else {
ksu_sucompat_exit();
}
ksu_su_compat_enabled = enabled;
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
pr_err("prctl reply error, cmd: %lu\n", arg2);
}
return 0;
}
return 0; return 0;
} }

View File

@@ -2,6 +2,7 @@
#define __KSU_H_KSU_CORE #define __KSU_H_KSU_CORE
#include <linux/init.h> #include <linux/init.h>
#include "apk_sign.h"
void __init ksu_core_init(void); void __init ksu_core_init(void);
void ksu_core_exit(void); void ksu_core_exit(void);

View File

@@ -23,7 +23,12 @@
#define CMD_UID_SHOULD_UMOUNT 13 #define CMD_UID_SHOULD_UMOUNT 13
#define CMD_IS_SU_ENABLED 14 #define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15 #define CMD_ENABLE_SU 15
#define CMD_GET_FULL_VERSION 0xC0FFEE1A
#define CMD_ENABLE_KPM 100 #define CMD_ENABLE_KPM 100
#define CMD_DYNAMIC_SIGN 103
#define CMD_GET_MANAGERS 104
#define EVENT_POST_FS_DATA 1 #define EVENT_POST_FS_DATA 1
#define EVENT_BOOT_COMPLETED 2 #define EVENT_BOOT_COMPLETED 2
@@ -35,6 +40,30 @@
#define KSU_MAX_GROUPS 32 #define KSU_MAX_GROUPS 32
#define KSU_SELINUX_DOMAIN 64 #define KSU_SELINUX_DOMAIN 64
// SukiSU Ultra kernel su version full strings
#ifndef KSU_VERSION_FULL
#define KSU_VERSION_FULL "v3.x-00000000@unknown"
#endif
#define KSU_FULL_VERSION_STRING 255
#define DYNAMIC_SIGN_OP_SET 0
#define DYNAMIC_SIGN_OP_GET 1
#define DYNAMIC_SIGN_OP_CLEAR 2
struct dynamic_sign_user_config {
unsigned int operation;
unsigned int size;
char hash[65];
};
struct manager_list_info {
int count;
struct {
uid_t uid;
int signature_index;
} managers[2];
};
struct root_profile { struct root_profile {
int32_t uid; int32_t uid;
int32_t gid; int32_t gid;

View File

@@ -8,6 +8,11 @@
extern uid_t ksu_manager_uid; // DO NOT DIRECT USE extern uid_t ksu_manager_uid; // DO NOT DIRECT USE
extern bool ksu_is_any_manager(uid_t uid);
extern void ksu_add_manager(uid_t uid, int signature_index);
extern void ksu_remove_manager(uid_t uid);
extern int ksu_get_manager_signature_index(uid_t uid);
static inline bool ksu_is_manager_uid_valid() static inline bool ksu_is_manager_uid_valid()
{ {
return ksu_manager_uid != KSU_INVALID_UID; return ksu_manager_uid != KSU_INVALID_UID;
@@ -15,7 +20,7 @@ static inline bool ksu_is_manager_uid_valid()
static inline bool is_manager() static inline bool is_manager()
{ {
return unlikely(ksu_manager_uid == current_uid().val); return unlikely(ksu_is_any_manager(current_uid().val) || ksu_manager_uid == current_uid().val);
} }
static inline uid_t ksu_get_manager_uid() static inline uid_t ksu_get_manager_uid()

13
kernel/manager_sign.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef MANAGER_SIGN_H
#define MANAGER_SIGN_H
// ShirkNeko/SukiSU
#define EXPECTED_SIZE_SHIRKNEKO 0x35c
#define EXPECTED_HASH_SHIRKNEKO "947ae944f3de4ed4c21a7e4f7953ecf351bfa2b36239da37a34111ad29993eef"
// Dynamic Sign
#define EXPECTED_SIZE_OTHER 0x300
#define EXPECTED_HASH_OTHER "0000000000000000000000000000000000000000000000000000000000000000"
#endif /* MANAGER_SIGN_H */

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
set -eu set -eu
GKI_ROOT=$(pwd) KERNEL_ROOT=$(pwd)
display_usage() { display_usage() {
echo "Usage: $0 [--cleanup | <commit-or-tag>]" echo "Usage: $0 [--cleanup | <commit-or-tag>]"
@@ -12,10 +12,10 @@ display_usage() {
} }
initialize_variables() { initialize_variables() {
if test -d "$GKI_ROOT/common/drivers"; then if test -d "$KERNEL_ROOT/common/drivers"; then
DRIVER_DIR="$GKI_ROOT/common/drivers" DRIVER_DIR="$KERNEL_ROOT/common/drivers"
elif test -d "$GKI_ROOT/drivers"; then elif test -d "$KERNEL_ROOT/drivers"; then
DRIVER_DIR="$GKI_ROOT/drivers" DRIVER_DIR="$KERNEL_ROOT/drivers"
else else
echo '[ERROR] "drivers/" directory not found.' echo '[ERROR] "drivers/" directory not found.'
exit 127 exit 127
@@ -30,22 +30,21 @@ perform_cleanup() {
echo "[+] Cleaning up..." echo "[+] Cleaning up..."
[ -L "$DRIVER_DIR/kernelsu" ] && rm "$DRIVER_DIR/kernelsu" && echo "[-] Symlink removed." [ -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 "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." grep -q "kernelsu" "$DRIVER_KCONFIG" && sed -i '/kernelsu/d' "$DRIVER_KCONFIG" && echo "[-] Kconfig reverted."
if [ -d "$GKI_ROOT/KernelSU" ]; then if [ -d "$KERNEL_ROOT/KernelSU" ]; then
rm -rf "$GKI_ROOT/KernelSU" && echo "[-] KernelSU directory deleted." rm -rf "$KERNEL_ROOT/KernelSU" && echo "[-] KernelSU directory deleted."
fi fi
} }
# Sets up or update KernelSU environment # Sets up or update KernelSU environment
setup_kernelsu() { setup_kernelsu() {
echo "[+] Setting up KernelSU..." echo "[+] Setting up KernelSU..."
# Clone the repository and rename it to KernelSU # Clone the repository
if [ ! -d "$GKI_ROOT/KernelSU" ]; then if [ ! -d "$KERNEL_ROOT/KernelSU" ]; then
git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra SukiSU-Ultra git clone https://github.com/SukiSU-Ultra/SukiSU-Ultra KernelSU
mv SukiSU-Ultra KernelSU echo "[+] Repository cloned."
echo "[+] Repository cloned and renamed to KernelSU."
fi fi
cd "$GKI_ROOT/KernelSU" cd "$KERNEL_ROOT/KernelSU"
git stash && echo "[-] Stashed current changes." git stash && echo "[-] Stashed current changes."
if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then if [ "$(git status | grep -Po 'v\d+(\.\d+)*' | head -n1)" ]; then
git checkout main && echo "[-] Switched to main branch." git checkout main && echo "[-] Switched to main branch."
@@ -57,11 +56,11 @@ setup_kernelsu() {
git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch" git checkout "$1" && echo "[-] Checked out $1." || echo "[-] Checkout default branch"
fi fi
cd "$DRIVER_DIR" 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" "$KERNEL_ROOT/KernelSU/kernel")" "kernelsu" && echo "[+] Symlink created."
# Add entries in Makefile and Kconfig if not already existing # 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." grep -q "kernelsu" "$DRIVER_MAKEFILE" || echo 'obj-$(CONFIG_KSU) += kernelsu/' >> "$DRIVER_MAKEFILE" && echo "[+] Modified Makefile."
grep -q "source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG" && echo "[+] Modified Kconfig." grep -q 'source "drivers/kernelsu/Kconfig"' "$DRIVER_KCONFIG" || sed -i '/endmenu/i\source "drivers/kernelsu/Kconfig"' "$DRIVER_KCONFIG" && echo "[+] Modified Kconfig."
echo '[+] Done.' echo '[+] Done.'
} }

View File

@@ -62,7 +62,7 @@ static int get_pkg_from_apk_path(char *pkg, const char *path)
return 0; return 0;
} }
static void crown_manager(const char *apk, struct list_head *uid_data) static void crown_manager(const char *apk, struct list_head *uid_data, int signature_index)
{ {
char pkg[KSU_MAX_PACKAGE_NAME]; char pkg[KSU_MAX_PACKAGE_NAME];
if (get_pkg_from_apk_path(pkg, apk) < 0) { if (get_pkg_from_apk_path(pkg, apk) < 0) {
@@ -70,7 +70,7 @@ static void crown_manager(const char *apk, struct list_head *uid_data)
return; return;
} }
pr_info("manager pkg: %s\n", pkg); pr_info("manager pkg: %s, signature_index: %d\n", pkg, signature_index);
#ifdef KSU_MANAGER_PACKAGE #ifdef KSU_MANAGER_PACKAGE
// pkg is `/<real package>` // pkg is `/<real package>`
@@ -85,8 +85,17 @@ static void crown_manager(const char *apk, struct list_head *uid_data)
list_for_each_entry (np, list, list) { list_for_each_entry (np, list, list) {
if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) { if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) {
pr_info("Crowning manager: %s(uid=%d)\n", pkg, np->uid); pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n", pkg, np->uid, signature_index);
if (signature_index == 1 || signature_index == 2) {
ksu_add_manager(np->uid, signature_index);
if (!ksu_is_manager_uid_valid()) {
ksu_set_manager_uid(np->uid); ksu_set_manager_uid(np->uid);
}
} else {
ksu_set_manager_uid(np->uid);
}
break; break;
} }
} }
@@ -185,11 +194,24 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
} }
} }
bool is_manager = is_manager_apk(dirpath); int signature_index = -1;
pr_info("Found new base.apk at path: %s, is_manager: %d\n", bool is_multi_manager = ksu_is_multi_manager_apk(dirpath, &signature_index);
dirpath, is_manager);
if (is_manager) { pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n",
crown_manager(dirpath, my_ctx->private_data); dirpath, is_multi_manager, signature_index);
if (is_multi_manager && (signature_index == 1 || signature_index == 2)) {
crown_manager(dirpath, my_ctx->private_data, signature_index);
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
if (apk_data) {
apk_data->hash = hash;
apk_data->exists = true;
list_add_tail(&apk_data->list, &apk_path_hash_list);
}
} else if (is_manager_apk(dirpath)) {
crown_manager(dirpath, my_ctx->private_data, 0);
*my_ctx->stop = 1; *my_ctx->stop = 1;
// Manager found, clear APK cache list // Manager found, clear APK cache list
@@ -199,12 +221,14 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
} }
} else { } else {
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC); struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
if (apk_data) {
apk_data->hash = hash; apk_data->hash = hash;
apk_data->exists = true; apk_data->exists = true;
list_add_tail(&apk_data->list, &apk_path_hash_list); list_add_tail(&apk_data->list, &apk_path_hash_list);
} }
} }
} }
}
return FILLDIR_ACTOR_CONTINUE; return FILLDIR_ACTOR_CONTINUE;
} }
@@ -371,6 +395,10 @@ void track_throne()
manager_exist = true; manager_exist = true;
break; break;
} }
if (ksu_is_any_manager(np->uid)) {
manager_exist = true;
}
} }
if (!manager_exist) { if (!manager_exist) {

View File

@@ -1,6 +1,5 @@
@file:Suppress("UnstableApiUsage") @file:Suppress("UnstableApiUsage")
import com.android.build.api.dsl.ApkSigningConfig
import com.android.build.gradle.internal.api.BaseVariantOutputImpl import com.android.build.gradle.internal.api.BaseVariantOutputImpl
import com.android.build.gradle.tasks.PackageAndroidArtifact import com.android.build.gradle.tasks.PackageAndroidArtifact
@@ -107,6 +106,10 @@ android {
} }
} }
ksp {
arg("compose-destinations.defaultTransitions", "none")
}
dependencies { dependencies {
implementation(libs.gson) implementation(libs.gson)
implementation(libs.androidx.activity.compose) implementation(libs.androidx.activity.compose)
@@ -159,4 +162,6 @@ dependencies {
implementation(libs.mmrl.webui) implementation(libs.mmrl.webui)
implementation(libs.mmrl.ui) implementation(libs.mmrl.ui)
implementation(libs.accompanist.drawablepainter)
} }

Binary file not shown.

View File

@@ -19,6 +19,13 @@ NativeBridgeNP(getVersion, jint) {
return get_version(); return get_version();
} }
// get VERSION FULL
NativeBridgeNP(getFullVersion, jstring) {
char buff[255] = { 0 };
get_full_version((char *) &buff);
return GetEnvironment()->NewStringUTF(env, buff);
}
NativeBridgeNP(getAllowList, jintArray) { NativeBridgeNP(getAllowList, jintArray) {
int uids[1024]; int uids[1024];
int size = 0; int size = 0;
@@ -291,16 +298,19 @@ NativeBridge(setSuEnabled, jboolean, jboolean enabled) {
return set_su_enabled(enabled); return set_su_enabled(enabled);
} }
// Check if KPM is enabled
NativeBridgeNP(isKPMEnabled, jboolean) { NativeBridgeNP(isKPMEnabled, jboolean) {
return is_KPM_enable(); return is_KPM_enable();
} }
// Get HOOK type
NativeBridgeNP(getHookType, jstring) { NativeBridgeNP(getHookType, jstring) {
char hook_type[16]; char hook_type[16];
get_hook_type(hook_type, sizeof(hook_type)); get_hook_type(hook_type, sizeof(hook_type));
return GetEnvironment()->NewStringUTF(env, hook_type); return GetEnvironment()->NewStringUTF(env, hook_type);
} }
// SuSFS Related Function Status
NativeBridgeNP(getSusfsFeatureStatus, jobject) { NativeBridgeNP(getSusfsFeatureStatus, jobject) {
struct susfs_feature_status status; struct susfs_feature_status status;
bool result = get_susfs_feature_status(&status); bool result = get_susfs_feature_status(&status);
@@ -313,36 +323,93 @@ NativeBridgeNP(getSusfsFeatureStatus, jobject) {
jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", "()V"); jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", "()V");
jobject obj = GetEnvironment()->NewObject(env, cls, constructor); jobject obj = GetEnvironment()->NewObject(env, cls, constructor);
// 设置各个字段 SET_BOOLEAN_FIELD(obj, cls, statusSusPath, status.status_sus_path);
jfieldID statusSusPathField = GetEnvironment()->GetFieldID(env, cls, "statusSusPath", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusSusMount, status.status_sus_mount);
jfieldID statusSusMountField = GetEnvironment()->GetFieldID(env, cls, "statusSusMount", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusAutoDefaultMount, status.status_auto_default_mount);
jfieldID statusAutoDefaultMountField = GetEnvironment()->GetFieldID(env, cls, "statusAutoDefaultMount", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusAutoBindMount, status.status_auto_bind_mount);
jfieldID statusAutoBindMountField = GetEnvironment()->GetFieldID(env, cls, "statusAutoBindMount", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusSusKstat, status.status_sus_kstat);
jfieldID statusSusKstatField = GetEnvironment()->GetFieldID(env, cls, "statusSusKstat", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusTryUmount, status.status_try_umount);
jfieldID statusTryUmountField = GetEnvironment()->GetFieldID(env, cls, "statusTryUmount", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusAutoTryUmountBind, status.status_auto_try_umount_bind);
jfieldID statusAutoTryUmountBindField = GetEnvironment()->GetFieldID(env, cls, "statusAutoTryUmountBind", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusSpoofUname, status.status_spoof_uname);
jfieldID statusSpoofUnameField = GetEnvironment()->GetFieldID(env, cls, "statusSpoofUname", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusEnableLog, status.status_enable_log);
jfieldID statusEnableLogField = GetEnvironment()->GetFieldID(env, cls, "statusEnableLog", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusHideSymbols, status.status_hide_symbols);
jfieldID statusHideSymbolsField = GetEnvironment()->GetFieldID(env, cls, "statusHideSymbols", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusSpoofCmdline, status.status_spoof_cmdline);
jfieldID statusSpoofCmdlineField = GetEnvironment()->GetFieldID(env, cls, "statusSpoofCmdline", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusOpenRedirect, status.status_open_redirect);
jfieldID statusOpenRedirectField = GetEnvironment()->GetFieldID(env, cls, "statusOpenRedirect", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusMagicMount, status.status_magic_mount);
jfieldID statusMagicMountField = GetEnvironment()->GetFieldID(env, cls, "statusMagicMount", "Z"); SET_BOOLEAN_FIELD(obj, cls, statusSusSu, status.status_sus_su);
jfieldID statusSusSuField = GetEnvironment()->GetFieldID(env, cls, "statusSusSu", "Z");
GetEnvironment()->SetBooleanField(env, obj, statusSusPathField, status.status_sus_path);
GetEnvironment()->SetBooleanField(env, obj, statusSusMountField, status.status_sus_mount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoDefaultMountField, status.status_auto_default_mount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoBindMountField, status.status_auto_bind_mount);
GetEnvironment()->SetBooleanField(env, obj, statusSusKstatField, status.status_sus_kstat);
GetEnvironment()->SetBooleanField(env, obj, statusTryUmountField, status.status_try_umount);
GetEnvironment()->SetBooleanField(env, obj, statusAutoTryUmountBindField, status.status_auto_try_umount_bind);
GetEnvironment()->SetBooleanField(env, obj, statusSpoofUnameField, status.status_spoof_uname);
GetEnvironment()->SetBooleanField(env, obj, statusEnableLogField, status.status_enable_log);
GetEnvironment()->SetBooleanField(env, obj, statusHideSymbolsField, status.status_hide_symbols);
GetEnvironment()->SetBooleanField(env, obj, statusSpoofCmdlineField, status.status_spoof_cmdline);
GetEnvironment()->SetBooleanField(env, obj, statusOpenRedirectField, status.status_open_redirect);
GetEnvironment()->SetBooleanField(env, obj, statusMagicMountField, status.status_magic_mount);
GetEnvironment()->SetBooleanField(env, obj, statusSusSuField, status.status_sus_su);
return obj; return obj;
} }
// dynamic sign
NativeBridge(setDynamicSign, jboolean, jint size, jstring hash) {
if (!hash) {
LogDebug("setDynamicSign: hash is null");
return false;
}
const char* chash = GetEnvironment()->GetStringUTFChars(env, hash, nullptr);
bool result = set_dynamic_sign((unsigned int)size, chash);
GetEnvironment()->ReleaseStringUTFChars(env, hash, chash);
LogDebug("setDynamicSign: size=0x%x, result=%d", size, result);
return result;
}
NativeBridgeNP(getDynamicSign, jobject) {
struct dynamic_sign_user_config config;
bool result = get_dynamic_sign(&config);
if (!result) {
LogDebug("getDynamicSign: failed to get dynamic sign config");
return NULL;
}
jobject obj = CREATE_JAVA_OBJECT("com/sukisu/ultra/Natives$DynamicSignConfig");
jclass cls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$DynamicSignConfig");
SET_INT_FIELD(obj, cls, size, (jint)config.size);
SET_STRING_FIELD(obj, cls, hash, config.hash);
LogDebug("getDynamicSign: size=0x%x, hash=%.16s...", config.size, config.hash);
return obj;
}
NativeBridgeNP(clearDynamicSign, jboolean) {
bool result = clear_dynamic_sign();
LogDebug("clearDynamicSign: result=%d", result);
return result;
}
// Get a list of active managers
NativeBridgeNP(getManagersList, jobject) {
struct manager_list_info managerListInfo;
bool result = get_managers_list(&managerListInfo);
if (!result) {
LogDebug("getManagersList: failed to get active managers list");
return NULL;
}
jobject obj = CREATE_JAVA_OBJECT("com/sukisu/ultra/Natives$ManagersList");
jclass managerListCls = GetEnvironment()->FindClass(env, "com/sukisu/ultra/Natives$ManagersList");
SET_INT_FIELD(obj, managerListCls, count, (jint)managerListInfo.count);
jobject managersList = CREATE_ARRAYLIST();
for (int i = 0; i < managerListInfo.count; i++) {
jobject managerInfo = CREATE_JAVA_OBJECT_WITH_PARAMS(
"com/sukisu/ultra/Natives$ManagerInfo",
"(II)V",
(jint)managerListInfo.managers[i].uid,
(jint)managerListInfo.managers[i].signature_index
);
ADD_TO_LIST(managersList, managerInfo);
}
SET_OBJECT_FIELD(obj, managerListCls, managers, managersList);
LogDebug("getManagersList: count=%d", managerListInfo.count);
return obj;
}

View File

@@ -30,9 +30,18 @@
#define CMD_IS_UID_SHOULD_UMOUNT 13 #define CMD_IS_UID_SHOULD_UMOUNT 13
#define CMD_IS_SU_ENABLED 14 #define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15 #define CMD_ENABLE_SU 15
#define CMD_GET_VERSION_FULL 0xC0FFEE1A
#define CMD_ENABLE_KPM 100 #define CMD_ENABLE_KPM 100
#define CMD_HOOK_TYPE 101 #define CMD_HOOK_TYPE 101
#define CMD_GET_SUSFS_FEATURE_STATUS 102 #define CMD_GET_SUSFS_FEATURE_STATUS 102
#define CMD_DYNAMIC_SIGN 103
#define CMD_GET_MANAGERS 104
#define DYNAMIC_SIGN_OP_SET 0
#define DYNAMIC_SIGN_OP_GET 1
#define DYNAMIC_SIGN_OP_CLEAR 2
static bool ksuctl(int cmd, void* arg1, void* arg2) { static bool ksuctl(int cmd, void* arg1, void* arg2) {
int32_t result = 0; int32_t result = 0;
@@ -58,14 +67,18 @@ bool become_manager(const char* pkg) {
static bool is_lkm; static bool is_lkm;
int get_version() { int get_version() {
int32_t version = -1; int32_t version = -1;
int32_t lkm = 0; int32_t flags = 0;
ksuctl(CMD_GET_VERSION, &version, &lkm); ksuctl(CMD_GET_VERSION, &version, &flags);
if (!is_lkm && lkm != 0) { if (!is_lkm && (flags & 0x1)) {
is_lkm = true; is_lkm = true;
} }
return version; return version;
} }
void get_full_version(char* buff) {
ksuctl(CMD_GET_VERSION_FULL, buff, NULL);
}
bool get_allow_list(int *uids, int *size) { bool get_allow_list(int *uids, int *size) {
return ksuctl(CMD_GET_SU_LIST, uids, size); return ksuctl(CMD_GET_SU_LIST, uids, size);
} }
@@ -133,3 +146,40 @@ bool get_susfs_feature_status(struct susfs_feature_status* status) {
return ksuctl(CMD_GET_SUSFS_FEATURE_STATUS, status, NULL); return ksuctl(CMD_GET_SUSFS_FEATURE_STATUS, status, NULL);
} }
bool set_dynamic_sign(unsigned int size, const char* hash) {
if (hash == NULL) {
return false;
}
struct dynamic_sign_user_config config;
config.operation = DYNAMIC_SIGN_OP_SET;
config.size = size;
strncpy(config.hash, hash, sizeof(config.hash) - 1);
config.hash[sizeof(config.hash) - 1] = '\0';
return ksuctl(CMD_DYNAMIC_SIGN, &config, NULL);
}
bool get_dynamic_sign(struct dynamic_sign_user_config* config) {
if (config == NULL) {
return false;
}
config->operation = DYNAMIC_SIGN_OP_GET;
return ksuctl(CMD_DYNAMIC_SIGN, config, NULL);
}
bool clear_dynamic_sign() {
struct dynamic_sign_user_config config;
config.operation = DYNAMIC_SIGN_OP_CLEAR;
return ksuctl(CMD_DYNAMIC_SIGN, &config, NULL);
}
bool get_managers_list(struct manager_list_info* info) {
if (info == NULL) {
return false;
}
return ksuctl(CMD_GET_MANAGERS, info, NULL);
}

View File

@@ -7,9 +7,12 @@
#include "prelude.h" #include "prelude.h"
#include <linux/capability.h> #include <linux/capability.h>
#include <sys/types.h>
bool become_manager(const char *); bool become_manager(const char *);
void get_full_version(char* buff);
int get_version(); int get_version();
bool get_allow_list(int *uids, int *size); bool get_allow_list(int *uids, int *size);
@@ -26,6 +29,16 @@ bool is_lkm_mode();
#define KSU_MAX_GROUPS 32 #define KSU_MAX_GROUPS 32
#define KSU_SELINUX_DOMAIN 64 #define KSU_SELINUX_DOMAIN 64
#define DYNAMIC_SIGN_OP_SET 0
#define DYNAMIC_SIGN_OP_GET 1
#define DYNAMIC_SIGN_OP_CLEAR 2
struct dynamic_sign_user_config {
unsigned int operation;
unsigned int size;
char hash[65];
};
// SUSFS Functional State Structures // SUSFS Functional State Structures
struct susfs_feature_status { struct susfs_feature_status {
bool status_sus_path; bool status_sus_path;
@@ -93,6 +106,14 @@ struct app_profile {
}; };
}; };
struct manager_list_info {
int count;
struct {
uid_t uid;
int signature_index;
} managers[2];
};
bool set_app_profile(const struct app_profile* profile); bool set_app_profile(const struct app_profile* profile);
bool get_app_profile(char* key, struct app_profile* profile); bool get_app_profile(char* key, struct app_profile* profile);
@@ -107,4 +128,12 @@ bool get_hook_type(char* hook_type, size_t size);
bool get_susfs_feature_status(struct susfs_feature_status* status); bool get_susfs_feature_status(struct susfs_feature_status* status);
bool set_dynamic_sign(unsigned int size, const char* hash);
bool get_dynamic_sign(struct dynamic_sign_user_config* config);
bool clear_dynamic_sign();
bool get_managers_list(struct manager_list_info* info);
#endif //KERNELSU_KSU_H #endif //KERNELSU_KSU_H

View File

@@ -12,6 +12,55 @@
#define NativeBridge(fn, rtn, ...) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz, __VA_ARGS__) #define NativeBridge(fn, rtn, ...) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz, __VA_ARGS__)
#define NativeBridgeNP(fn, rtn) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz) #define NativeBridgeNP(fn, rtn) JNIEXPORT rtn JNICALL Java_com_sukisu_ultra_Natives_##fn(JNIEnv* env, jclass clazz)
// Macros to simplify field setup
#define SET_BOOLEAN_FIELD(obj, cls, fieldName, value) do { \
jfieldID field = GetEnvironment()->GetFieldID(env, cls, #fieldName, "Z"); \
GetEnvironment()->SetBooleanField(env, obj, field, value); \
} while(0)
#define SET_INT_FIELD(obj, cls, fieldName, value) do { \
jfieldID field = GetEnvironment()->GetFieldID(env, cls, #fieldName, "I"); \
GetEnvironment()->SetIntField(env, obj, field, value); \
} while(0)
#define SET_STRING_FIELD(obj, cls, fieldName, value) do { \
jfieldID field = GetEnvironment()->GetFieldID(env, cls, #fieldName, "Ljava/lang/String;"); \
GetEnvironment()->SetObjectField(env, obj, field, GetEnvironment()->NewStringUTF(env, value)); \
} while(0)
#define SET_OBJECT_FIELD(obj, cls, fieldName, value) do { \
jfieldID field = GetEnvironment()->GetFieldID(env, cls, #fieldName, "Ljava/util/List;"); \
GetEnvironment()->SetObjectField(env, obj, field, value); \
} while(0)
// Macros for creating Java objects
#define CREATE_JAVA_OBJECT(className) ({ \
jclass cls = GetEnvironment()->FindClass(env, className); \
jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", "()V"); \
GetEnvironment()->NewObject(env, cls, constructor); \
})
// Macros for creating ArrayList
#define CREATE_ARRAYLIST() ({ \
jclass arrayListCls = GetEnvironment()->FindClass(env, "java/util/ArrayList"); \
jmethodID constructor = GetEnvironment()->GetMethodID(env, arrayListCls, "<init>", "()V"); \
GetEnvironment()->NewObject(env, arrayListCls, constructor); \
})
// Macros for adding elements to an ArrayList
#define ADD_TO_LIST(list, item) do { \
jclass cls = GetEnvironment()->GetObjectClass(env, list); \
jmethodID addMethod = GetEnvironment()->GetMethodID(env, cls, "add", "(Ljava/lang/Object;)Z"); \
GetEnvironment()->CallBooleanMethod(env, list, addMethod, item); \
} while(0)
// Macros for creating Java objects with parameter constructors
#define CREATE_JAVA_OBJECT_WITH_PARAMS(className, signature, ...) ({ \
jclass cls = GetEnvironment()->FindClass(env, className); \
jmethodID constructor = GetEnvironment()->GetMethodID(env, cls, "<init>", signature); \
GetEnvironment()->NewObject(env, cls, constructor, __VA_ARGS__); \
})
#define LogDebug(...) __android_log_print(ANDROID_LOG_DEBUG, "KernelSU", __VA_ARGS__) #define LogDebug(...) __android_log_print(ANDROID_LOG_DEBUG, "KernelSU", __VA_ARGS__)
#endif #endif

View File

@@ -17,6 +17,7 @@ object Natives {
// 10977: change groups_count and groups to avoid overflow write // 10977: change groups_count and groups to avoid overflow write
// 11071: Fix the issue of failing to set a custom SELinux type. // 11071: Fix the issue of failing to set a custom SELinux type.
const val MINIMAL_SUPPORTED_KERNEL = 11071 const val MINIMAL_SUPPORTED_KERNEL = 11071
const val MINIMAL_SUPPORTED_KERNEL_FULL = "v3.1.5"
// 11640: Support query working mode, LKM or GKI // 11640: Support query working mode, LKM or GKI
// when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant. // when MINIMAL_SUPPORTED_KERNEL > 11640, we can remove this constant.
@@ -28,9 +29,28 @@ object Natives {
const val MINIMAL_SUPPORTED_KPM = 12800 const val MINIMAL_SUPPORTED_KPM = 12800
const val MINIMAL_SUPPORTED_DYNAMIC_SIGN = 13215
const val ROOT_UID = 0 const val ROOT_UID = 0
const val ROOT_GID = 0 const val ROOT_GID = 0
external fun getFullVersion(): String
fun getSimpleVersionFull(): String {
val fullVersion = getFullVersion()
val startIndex = fullVersion.indexOf('v')
if (startIndex < 0) {
return fullVersion
}
val endIndex = fullVersion.indexOf('-', startIndex)
val versionStr = if (endIndex > startIndex) {
fullVersion.substring(startIndex, endIndex)
} else {
fullVersion.substring(startIndex)
}
return "v" + (Regex("""\d+(\.\d+)*""").find(versionStr)?.value ?: versionStr)
}
init { init {
System.loadLibrary("zako") System.loadLibrary("zako")
} }
@@ -77,6 +97,33 @@ object Natives {
*/ */
external fun getSusfsFeatureStatus(): SusfsFeatureStatus? external fun getSusfsFeatureStatus(): SusfsFeatureStatus?
/**
* Set dynamic signature configuration
* @param size APK signature size
* @param hash APK signature hash (64 character hex string)
* @return true if successful, false otherwise
*/
external fun setDynamicSign(size: Int, hash: String): Boolean
/**
* Get current dynamic signature configuration
* @return DynamicSignConfig object containing current configuration, or null if not set
*/
external fun getDynamicSign(): DynamicSignConfig?
/**
* Clear dynamic signature configuration
* @return true if successful, false otherwise
*/
external fun clearDynamicSign(): Boolean
/**
* Get active managers list when dynamic sign is enabled
* @return ManagersList object containing active managers, or null if failed or not enabled
*/
external fun getManagersList(): ManagersList?
private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$" private const val NON_ROOT_DEFAULT_PROFILE_KEY = "$"
private const val NOBODY_UID = 9999 private const val NOBODY_UID = 9999
@@ -98,7 +145,14 @@ object Natives {
} }
fun requireNewKernel(): Boolean { fun requireNewKernel(): Boolean {
return version < MINIMAL_SUPPORTED_KERNEL if (version < MINIMAL_SUPPORTED_KERNEL) {
return true
}
val simpleVersionFull = getSimpleVersionFull()
if (simpleVersionFull.isEmpty()) {
return false
}
return simpleVersionFull < MINIMAL_SUPPORTED_KERNEL_FULL
} }
@Immutable @Immutable
@@ -120,28 +174,38 @@ object Natives {
val statusMagicMount: Boolean = false, val statusMagicMount: Boolean = false,
val statusOverlayfsAutoKstat: Boolean = false, val statusOverlayfsAutoKstat: Boolean = false,
val statusSusSu: Boolean = false val statusSusSu: Boolean = false
) : Parcelable
@Immutable
@Parcelize
@Keep
data class DynamicSignConfig(
val size: Int = 0,
val hash: String = ""
) : Parcelable { ) : Parcelable {
fun toMap(): Map<String, Boolean> {
return mapOf( fun isValid(): Boolean {
"CONFIG_KSU_SUSFS_SUS_PATH" to statusSusPath, return size > 0 && hash.length == 64 && hash.all {
"CONFIG_KSU_SUSFS_SUS_MOUNT" to statusSusMount, it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F'
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT" to statusAutoDefaultMount, }
"CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT" to statusAutoBindMount,
"CONFIG_KSU_SUSFS_SUS_KSTAT" to statusSusKstat,
"CONFIG_KSU_SUSFS_TRY_UMOUNT" to statusTryUmount,
"CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT" to statusAutoTryUmountBind,
"CONFIG_KSU_SUSFS_SPOOF_UNAME" to statusSpoofUname,
"CONFIG_KSU_SUSFS_ENABLE_LOG" to statusEnableLog,
"CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS" to statusHideSymbols,
"CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG" to statusSpoofCmdline,
"CONFIG_KSU_SUSFS_OPEN_REDIRECT" to statusOpenRedirect,
"CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT" to statusMagicMount,
"CONFIG_KSU_SUSFS_SUS_OVERLAYFS" to statusOverlayfsAutoKstat,
"CONFIG_KSU_SUSFS_SUS_SU" to statusSusSu
)
} }
} }
@Immutable
@Parcelize
@Keep
data class ManagersList(
val count: Int = 0,
val managers: List<ManagerInfo> = emptyList()
) : Parcelable
@Immutable
@Parcelize
@Keep
data class ManagerInfo(
val uid: Int = 0,
val signatureIndex: Int = 0
) : Parcelable
@Immutable @Immutable
@Parcelize @Parcelize

View File

@@ -0,0 +1,141 @@
package com.sukisu.ultra.ui
import android.content.Intent
import android.content.pm.PackageInfo
import android.os.Binder
import android.os.IBinder
import android.os.IInterface
import android.os.Parcel
import android.os.UserManager
import android.util.Log
import com.topjohnwu.superuser.ipc.RootService
import rikka.parcelablelist.ParcelableListSlice
import java.lang.reflect.Method
/**
* @author ShirkNeko
* @date 2025/7/2.
*/
class KsuService : RootService() {
companion object {
private const val TAG = "KsuService"
private const val DESCRIPTOR = "com.sukisu.ultra.IKsuInterface"
private const val TRANSACTION_GET_PACKAGES = IBinder.FIRST_CALL_TRANSACTION + 0
}
interface IKsuInterface : IInterface {
fun getPackages(flags: Int): ParcelableListSlice<PackageInfo>
}
abstract class Stub : Binder(), IKsuInterface {
init {
attachInterface(this, DESCRIPTOR)
}
companion object {
fun asInterface(obj: IBinder?): IKsuInterface? {
if (obj == null) return null
val iin = obj.queryLocalInterface(DESCRIPTOR)
return if (iin != null && iin is IKsuInterface) {
iin
} else {
Proxy(obj)
}
}
}
override fun asBinder(): IBinder = this
override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
val descriptor = DESCRIPTOR
when (code) {
INTERFACE_TRANSACTION -> {
reply?.writeString(descriptor)
return true
}
TRANSACTION_GET_PACKAGES -> {
data.enforceInterface(descriptor)
val flagsArg = data.readInt()
val result = getPackages(flagsArg)
reply?.writeNoException()
reply?.writeInt(1)
result.writeToParcel(reply!!, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE)
return true
}
}
return super.onTransact(code, data, reply, flags)
}
private class Proxy(private val mRemote: IBinder) : IKsuInterface {
override fun getPackages(flags: Int): ParcelableListSlice<PackageInfo> {
val data = Parcel.obtain()
val reply = Parcel.obtain()
return try {
data.writeInterfaceToken(DESCRIPTOR)
data.writeInt(flags)
mRemote.transact(TRANSACTION_GET_PACKAGES, data, reply, 0)
reply.readException()
if (reply.readInt() != 0) {
@Suppress("UNCHECKED_CAST")
ParcelableListSlice.CREATOR.createFromParcel(reply) as ParcelableListSlice<PackageInfo>
} else {
ParcelableListSlice(emptyList<PackageInfo>())
}
} finally {
reply.recycle()
data.recycle()
}
}
override fun asBinder(): IBinder = mRemote
}
}
inner class KsuInterfaceImpl : Stub() {
override fun getPackages(flags: Int): ParcelableListSlice<PackageInfo> {
val list = getInstalledPackagesAll(flags)
Log.i(TAG, "getPackages: ${list.size}")
return ParcelableListSlice(list)
}
}
override fun onBind(intent: Intent): IBinder {
return KsuInterfaceImpl()
}
private fun getUserIds(): List<Int> {
val result = mutableListOf<Int>()
val um = getSystemService(USER_SERVICE) as UserManager
val userProfiles = um.userProfiles
for (userProfile in userProfiles) {
result.add(userProfile.hashCode())
}
return result
}
private fun getInstalledPackagesAll(flags: Int): ArrayList<PackageInfo> {
val packages = ArrayList<PackageInfo>()
for (userId in getUserIds()) {
Log.i(TAG, "getInstalledPackagesAll: $userId")
packages.addAll(getInstalledPackagesAsUser(flags, userId))
}
return packages
}
private fun getInstalledPackagesAsUser(flags: Int, userId: Int): List<PackageInfo> {
return try {
val pm = packageManager
val getInstalledPackagesAsUser: Method = pm.javaClass.getDeclaredMethod(
"getInstalledPackagesAsUser",
Int::class.java,
Int::class.java
)
@Suppress("UNCHECKED_CAST")
getInstalledPackagesAsUser.invoke(pm, flags, userId) as List<PackageInfo>
} catch (e: Throwable) {
Log.e(TAG, "err", e)
ArrayList()
}
}
}

View File

@@ -7,20 +7,32 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge 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.animation.scaleOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavBackStackEntry
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.ramcosta.composedestinations.DestinationsNavHost import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.NavHostAnimatedDestinationStyle
import com.ramcosta.composedestinations.generated.NavGraphs import com.ramcosta.composedestinations.generated.NavGraphs
import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination
import com.ramcosta.composedestinations.spec.NavHostGraphSpec import com.ramcosta.composedestinations.spec.NavHostGraphSpec
import io.sukisu.ultra.UltraToolInstall import io.sukisu.ultra.UltraToolInstall
import com.sukisu.ultra.ksuApp import com.sukisu.ultra.ksuApp
import zako.zako.zako.zakoui.activity.util.AppData import zako.zako.zako.zakoui.activity.util.AppData
import com.sukisu.ultra.ui.screen.BottomBarDestination
import com.sukisu.ultra.ui.theme.* import com.sukisu.ultra.ui.theme.*
import zako.zako.zako.zakoui.activity.util.* import zako.zako.zako.zakoui.activity.util.*
import zako.zako.zako.zakoui.activity.component.BottomBar import zako.zako.zako.zakoui.activity.component.BottomBar
@@ -82,6 +94,10 @@ class MainActivity : ComponentActivity() {
val snackBarHostState = remember { SnackbarHostState() } val snackBarHostState = remember { SnackbarHostState() }
val currentDestination = navController.currentBackStackEntryAsState().value?.destination val currentDestination = navController.currentBackStackEntryAsState().value?.destination
val bottomBarRoutes = remember {
BottomBarDestination.entries.map { it.direction.route }.toSet()
}
val showBottomBar = when (currentDestination?.route) { val showBottomBar = when (currentDestination?.route) {
ExecuteModuleActionScreenDestination.route -> false ExecuteModuleActionScreenDestination.route -> false
else -> true else -> true
@@ -107,7 +123,47 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.padding(innerPadding), modifier = Modifier.padding(innerPadding),
navGraph = NavGraphs.root as NavHostGraphSpec, navGraph = NavGraphs.root as NavHostGraphSpec,
navController = navController, navController = navController,
defaultTransitions = NavigationUtils.defaultTransitions() defaultTransitions = object : NavHostAnimatedDestinationStyle() {
override val enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
// If the target is a detail page (not a bottom navigation page), slide in from the right
if (targetState.destination.route !in bottomBarRoutes) {
slideInHorizontally(initialOffsetX = { it })
} else {
// Otherwise (switching between bottom navigation pages), use fade in
fadeIn(animationSpec = tween(340))
}
}
override val exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
// If navigating from the home page (bottom navigation page) to a detail page, slide out to the left
if (initialState.destination.route in bottomBarRoutes && targetState.destination.route !in bottomBarRoutes) {
slideOutHorizontally(targetOffsetX = { -it / 4 }) + fadeOut()
} else {
// Otherwise (switching between bottom navigation pages), use fade out
fadeOut(animationSpec = tween(340))
}
}
override val popEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
// If returning to the home page (bottom navigation page), slide in from the left
if (targetState.destination.route in bottomBarRoutes) {
slideInHorizontally(initialOffsetX = { -it / 4 }) + fadeIn()
} else {
// Otherwise (e.g., returning between multiple detail pages), use default fade in
fadeIn(animationSpec = tween(340))
}
}
override val popExitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
// If returning from a detail page (not a bottom navigation page), scale down and fade out
if (initialState.destination.route !in bottomBarRoutes) {
scaleOut(targetScale = 0.9f) + fadeOut()
} else {
// Otherwise, use default fade out
fadeOut(animationSpec = tween(340))
}
}
}
) )
} }
} }

View File

@@ -99,7 +99,10 @@ private fun AboutCardContent() {
htmlString = stringResource( htmlString = stringResource(
id = R.string.about_source_code, id = R.string.about_source_code,
"<b><a href=\"https://github.com/ShirkNeko/SukiSU-Ultra\">GitHub</a></b>", "<b><a href=\"https://github.com/ShirkNeko/SukiSU-Ultra\">GitHub</a></b>",
"<b><a href=\"https://t.me/SukiKSU\">Telegram</a></b>" "<b><a href=\"https://t.me/SukiKSU\">Telegram</a></b>",
"<b>怡子曰曰</b>",
"<b>明风 OuO</b>",
"<b><a href=\"https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.txt\">CC BY-NC-SA 4.0</a></b>"
), ),
linkStyles = TextLinkStyles( linkStyles = TextLinkStyles(
style = SpanStyle( style = SpanStyle(

View File

@@ -17,8 +17,11 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Apps
import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.Loop
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Storage import androidx.compose.material.icons.filled.Storage
import androidx.compose.material3.Button import androidx.compose.material3.Button
@@ -27,21 +30,21 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.sukisu.ultra.R import com.sukisu.ultra.R
import com.sukisu.ultra.ui.screen.extensions.AddKstatPathItemCard
import com.sukisu.ultra.ui.screen.extensions.EmptyStateCard
import com.sukisu.ultra.ui.screen.extensions.FeatureStatusCard
import com.sukisu.ultra.ui.screen.extensions.KstatConfigItemCard
import com.sukisu.ultra.ui.screen.extensions.PathItemCard
import com.sukisu.ultra.ui.screen.extensions.SusMountHidingControlCard
import com.sukisu.ultra.ui.util.SuSFSManager import com.sukisu.ultra.ui.util.SuSFSManager
import com.sukisu.ultra.ui.util.SuSFSManager.isSusVersion158
import com.sukisu.ultra.ui.viewmodel.SuperUserViewModel
/** /**
* SUS路径内容组件 * SUS路径内容组件
@@ -51,31 +54,111 @@ fun SusPathsContent(
susPaths: Set<String>, susPaths: Set<String>,
isLoading: Boolean, isLoading: Boolean,
onAddPath: () -> Unit, onAddPath: () -> Unit,
onRemovePath: (String) -> Unit onAddAppPath: () -> Unit,
onRemovePath: (String) -> Unit,
onEditPath: ((String) -> Unit)? = null,
forceRefreshApps: Boolean = false
) { ) {
val superUserApps = SuperUserViewModel.apps
val superUserIsRefreshing = remember { SuperUserViewModel().isRefreshing }
LaunchedEffect(superUserIsRefreshing, superUserApps.size) {
if (!superUserIsRefreshing && superUserApps.isNotEmpty()) {
AppInfoCache.clearCache()
}
}
LaunchedEffect(forceRefreshApps) {
if (forceRefreshApps) {
AppInfoCache.clearCache()
}
}
val (appPathGroups, otherPaths) = remember(susPaths) {
val appPathRegex = Regex(".*/Android/data/([^/]+)/?.*")
val appPathMap = mutableMapOf<String, MutableList<String>>()
val others = mutableListOf<String>()
susPaths.forEach { path ->
val matchResult = appPathRegex.find(path)
if (matchResult != null) {
val packageName = matchResult.groupValues[1]
appPathMap.getOrPut(packageName) { mutableListOf() }.add(path)
} else {
others.add(path)
}
}
val sortedAppGroups = appPathMap.toList()
.sortedBy { it.first }
.map { (packageName, paths) -> packageName to paths.sorted() }
Pair(sortedAppGroups, others.sorted())
}
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
// 应用路径分组
if (appPathGroups.isNotEmpty()) {
item {
SectionHeader(
title = stringResource(R.string.app_paths_section),
subtitle = null,
icon = Icons.Default.Apps,
count = appPathGroups.size
)
}
items(appPathGroups) { (packageName, paths) ->
AppPathGroupCard(
packageName = packageName,
paths = paths,
onDeleteGroup = {
paths.forEach { path -> onRemovePath(path) }
},
onEditGroup = if (onEditPath != null) {
{
onEditPath(paths.first())
}
} else null,
isLoading = isLoading
)
}
}
// 其他路径
if (otherPaths.isNotEmpty()) {
item {
SectionHeader(
title = stringResource(R.string.other_paths_section),
subtitle = null,
icon = Icons.Default.Folder,
count = otherPaths.size
)
}
items(otherPaths) { path ->
PathItemCard(
path = path,
icon = Icons.Default.Folder,
onDelete = { onRemovePath(path) },
onEdit = if (onEditPath != null) { { onEditPath(path) } } else null,
isLoading = isLoading
)
}
}
if (susPaths.isEmpty()) { if (susPaths.isEmpty()) {
item { item {
EmptyStateCard( EmptyStateCard(
message = stringResource(R.string.susfs_no_paths_configured) message = stringResource(R.string.susfs_no_paths_configured)
) )
} }
} else {
items(susPaths.toList()) { path ->
PathItemCard(
path = path,
icon = Icons.Default.Folder,
onDelete = { onRemovePath(path) },
isLoading = isLoading
)
}
} }
// 添加普通长按钮
item { item {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -97,7 +180,128 @@ fun SusPathsContent(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add)) Text(text = stringResource(R.string.add_custom_path))
}
Button(
onClick = onAddAppPath,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Apps,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.add_app_path))
}
}
}
}
}
}
/**
* SUS循环路径内容组件
*/
@Composable
fun SusLoopPathsContent(
susLoopPaths: Set<String>,
isLoading: Boolean,
onAddLoopPath: () -> Unit,
onRemoveLoopPath: (String) -> Unit,
onEditLoopPath: ((String) -> Unit)? = null
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 说明卡片
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)
),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = stringResource(R.string.sus_loop_paths_description_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary
)
Text(
text = stringResource(R.string.sus_loop_paths_description_text),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = stringResource(R.string.susfs_loop_path_restriction_warning),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.secondary
)
}
}
}
if (susLoopPaths.isEmpty()) {
item {
EmptyStateCard(
message = stringResource(R.string.susfs_no_loop_paths_configured)
)
}
} else {
item {
SectionHeader(
title = stringResource(R.string.loop_paths_section),
subtitle = null,
icon = Icons.Default.Loop,
count = susLoopPaths.size
)
}
items(susLoopPaths.toList()) { path ->
PathItemCard(
path = path,
icon = Icons.Default.Loop,
onDelete = { onRemoveLoopPath(path) },
onEdit = if (onEditLoopPath != null) { { onEditLoopPath(path) } } else null,
isLoading = isLoading
)
}
}
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
onClick = onAddLoopPath,
modifier = Modifier
.weight(1f)
.height(48.dp),
shape = RoundedCornerShape(8.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.add_loop_path))
} }
} }
} }
@@ -112,10 +316,11 @@ fun SusPathsContent(
fun SusMountsContent( fun SusMountsContent(
susMounts: Set<String>, susMounts: Set<String>,
hideSusMountsForAllProcs: Boolean, hideSusMountsForAllProcs: Boolean,
isSusVersion_1_5_8: Boolean, isSusVersion158: Boolean,
isLoading: Boolean, isLoading: Boolean,
onAddMount: () -> Unit, onAddMount: () -> Unit,
onRemoveMount: (String) -> Unit, onRemoveMount: (String) -> Unit,
onEditMount: ((String) -> Unit)? = null,
onToggleHideSusMountsForAllProcs: (Boolean) -> Unit onToggleHideSusMountsForAllProcs: (Boolean) -> Unit
) { ) {
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
@@ -123,7 +328,7 @@ fun SusMountsContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
if (isSusVersion_1_5_8) { if (isSusVersion158) {
item { item {
SusMountHidingControlCard( SusMountHidingControlCard(
hideSusMountsForAllProcs = hideSusMountsForAllProcs, hideSusMountsForAllProcs = hideSusMountsForAllProcs,
@@ -145,12 +350,12 @@ fun SusMountsContent(
path = mount, path = mount,
icon = Icons.Default.Storage, icon = Icons.Default.Storage,
onDelete = { onRemoveMount(mount) }, onDelete = { onRemoveMount(mount) },
onEdit = if (onEditMount != null) { { onEditMount(mount) } } else null,
isLoading = isLoading isLoading = isLoading
) )
} }
} }
// 添加普通长按钮
item { item {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -172,7 +377,7 @@ fun SusMountsContent(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add)) Text(text = stringResource(R.string.add))
} }
} }
} }
@@ -186,17 +391,73 @@ fun SusMountsContent(
@Composable @Composable
fun TryUmountContent( fun TryUmountContent(
tryUmounts: Set<String>, tryUmounts: Set<String>,
umountForZygoteIsoService: Boolean,
isLoading: Boolean, isLoading: Boolean,
onAddUmount: () -> Unit, onAddUmount: () -> Unit,
onRunUmount: () -> Unit, onRunUmount: () -> Unit,
onRemoveUmount: (String) -> Unit onRemoveUmount: (String) -> Unit,
onEditUmount: ((String) -> Unit)? = null,
onToggleUmountForZygoteIsoService: (Boolean) -> Unit
) { ) {
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier.fillMaxSize(),
.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
if (isSusVersion158()) {
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
),
shape = RoundedCornerShape(12.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.Security,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.umount_zygote_iso_service),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurface
)
}
Spacer(modifier = Modifier.height(6.dp))
Text(
text = stringResource(R.string.umount_zygote_iso_service_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp
)
}
Switch(
checked = umountForZygoteIsoService,
onCheckedChange = onToggleUmountForZygoteIsoService,
enabled = !isLoading
)
}
}
}
}
if (tryUmounts.isEmpty()) { if (tryUmounts.isEmpty()) {
item { item {
EmptyStateCard( EmptyStateCard(
@@ -218,12 +479,12 @@ fun TryUmountContent(
icon = Icons.Default.Storage, icon = Icons.Default.Storage,
additionalInfo = stringResource(R.string.susfs_umount_mode_display, modeText, mode), additionalInfo = stringResource(R.string.susfs_umount_mode_display, modeText, mode),
onDelete = { onRemoveUmount(umountEntry) }, onDelete = { onRemoveUmount(umountEntry) },
onEdit = if (onEditUmount != null) { { onEditUmount(umountEntry) } } else null,
isLoading = isLoading isLoading = isLoading
) )
} }
} }
// 添加普通长按钮
item { item {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -245,7 +506,7 @@ fun TryUmountContent(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add)) Text(text = stringResource(R.string.add))
} }
if (tryUmounts.isNotEmpty()) { if (tryUmounts.isNotEmpty()) {
@@ -282,7 +543,9 @@ fun KstatConfigContent(
onAddKstatStatically: () -> Unit, onAddKstatStatically: () -> Unit,
onAddKstat: () -> Unit, onAddKstat: () -> Unit,
onRemoveKstatConfig: (String) -> Unit, onRemoveKstatConfig: (String) -> Unit,
onEditKstatConfig: ((String) -> Unit)? = null,
onRemoveAddKstat: (String) -> Unit, onRemoveAddKstat: (String) -> Unit,
onEditAddKstat: ((String) -> Unit)? = null,
onUpdateKstat: (String) -> Unit, onUpdateKstat: (String) -> Unit,
onUpdateKstatFullClone: (String) -> Unit onUpdateKstatFullClone: (String) -> Unit
) { ) {
@@ -291,7 +554,6 @@ fun KstatConfigContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
// 说明卡片
item { item {
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -334,7 +596,6 @@ fun KstatConfigContent(
} }
} }
// 静态Kstat配置列表
if (kstatConfigs.isNotEmpty()) { if (kstatConfigs.isNotEmpty()) {
item { item {
Text( Text(
@@ -347,12 +608,12 @@ fun KstatConfigContent(
KstatConfigItemCard( KstatConfigItemCard(
config = config, config = config,
onDelete = { onRemoveKstatConfig(config) }, onDelete = { onRemoveKstatConfig(config) },
onEdit = if (onEditKstatConfig != null) { { onEditKstatConfig(config) } } else null,
isLoading = isLoading isLoading = isLoading
) )
} }
} }
// Add Kstat路径列表
if (addKstatPaths.isNotEmpty()) { if (addKstatPaths.isNotEmpty()) {
item { item {
Text( Text(
@@ -365,6 +626,7 @@ fun KstatConfigContent(
AddKstatPathItemCard( AddKstatPathItemCard(
path = path, path = path,
onDelete = { onRemoveAddKstat(path) }, onDelete = { onRemoveAddKstat(path) },
onEdit = if (onEditAddKstat != null) { { onEditAddKstat(path) } } else null,
onUpdate = { onUpdateKstat(path) }, onUpdate = { onUpdateKstat(path) },
onUpdateFullClone = { onUpdateKstatFullClone(path) }, onUpdateFullClone = { onUpdateKstatFullClone(path) },
isLoading = isLoading isLoading = isLoading
@@ -372,7 +634,6 @@ fun KstatConfigContent(
} }
} }
// 空状态显示
if (kstatConfigs.isEmpty() && addKstatPaths.isEmpty()) { if (kstatConfigs.isEmpty() && addKstatPaths.isEmpty()) {
item { item {
EmptyStateCard( EmptyStateCard(
@@ -381,7 +642,6 @@ fun KstatConfigContent(
} }
} }
// 添加普通长按钮
item { item {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -403,7 +663,7 @@ fun KstatConfigContent(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add)) Text(text = stringResource(R.string.add))
} }
Button( Button(
@@ -419,7 +679,7 @@ fun KstatConfigContent(
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text(text = stringResource(R.string.susfs_add)) Text(text = stringResource(R.string.add))
} }
} }
} }
@@ -445,7 +705,6 @@ fun PathSettingsContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
// Android Data路径设置
item { item {
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -480,7 +739,6 @@ fun PathSettingsContent(
} }
} }
// SD卡路径设置
item { item {
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -529,7 +787,6 @@ fun EnabledFeaturesContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)
) { ) {
// 说明卡片
item { item {
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),

View File

@@ -112,6 +112,10 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
var showFloatAction by rememberSaveable { mutableStateOf(false) } var showFloatAction by rememberSaveable { mutableStateOf(false) }
// 添加状态跟踪是否已经完成刷写 // 添加状态跟踪是否已经完成刷写
var hasFlashCompleted by rememberSaveable { mutableStateOf(false) } var hasFlashCompleted by rememberSaveable { mutableStateOf(false) }
var hasExecuted by rememberSaveable { mutableStateOf(false) }
// 更新模块状态管理
var hasUpdateExecuted by rememberSaveable { mutableStateOf(false) }
var hasUpdateCompleted by rememberSaveable { mutableStateOf(false) }
val snackBarHost = LocalSnackbarHost.current val snackBarHost = LocalSnackbarHost.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
@@ -129,24 +133,82 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
// 重置状态 // 重置状态
LaunchedEffect(flashIt) { LaunchedEffect(flashIt) {
if (flashIt is FlashIt.FlashModules && flashIt.currentIndex == 0) { when (flashIt) {
is FlashIt.FlashModules -> {
if (flashIt.currentIndex == 0) {
moduleInstallStatus.value = ModuleInstallStatus( moduleInstallStatus.value = ModuleInstallStatus(
totalModules = flashIt.uris.size, totalModules = flashIt.uris.size,
currentModule = 1 currentModule = 1
) )
hasFlashCompleted = false hasFlashCompleted = false
} else if (flashIt !is FlashIt.FlashModules) { hasExecuted = false
}
}
is FlashIt.FlashModuleUpdate -> {
hasUpdateCompleted = false
hasUpdateExecuted = false
}
else -> {
hasFlashCompleted = false hasFlashCompleted = false
hasExecuted = false
}
} }
} }
// 只有在未完成刷写时才执行刷写操作 // 处理更新模块安装
LaunchedEffect(flashIt, hasFlashCompleted) { LaunchedEffect(flashIt) {
// 如果已经完成刷写或者已有文本内容,则不再执行 if (flashIt !is FlashIt.FlashModuleUpdate) return@LaunchedEffect
if (hasFlashCompleted || text.isNotEmpty()) { if (hasUpdateExecuted || hasUpdateCompleted || text.isNotEmpty()) {
return@LaunchedEffect return@LaunchedEffect
} }
hasUpdateExecuted = true
withContext(Dispatchers.IO) {
setFlashingStatus(FlashingStatus.FLASHING)
try {
logContent.append(text).append("\n")
} catch (_: Exception) {
logContent.append(text).append("\n")
}
flashModuleUpdate(flashIt.uri, onFinish = { showReboot, code ->
if (code != 0) {
text += "$errorCodeString $code.\n$checkLogString\n"
setFlashingStatus(FlashingStatus.FAILED)
} else {
setFlashingStatus(FlashingStatus.SUCCESS)
viewModel.markNeedRefresh()
}
if (showReboot) {
text += "\n\n\n"
showFloatAction = true
}
hasUpdateCompleted = true
}, onStdout = {
tempText = "$it\n"
if (tempText.startsWith("")) { // clear command
text = tempText.substring(6)
} else {
text += tempText
}
logContent.append(it).append("\n")
}, onStderr = {
logContent.append(it).append("\n")
})
}
}
// 安装但排除更新模块
LaunchedEffect(flashIt) {
if (flashIt is FlashIt.FlashModuleUpdate) return@LaunchedEffect
if (hasExecuted || hasFlashCompleted || text.isNotEmpty()) {
return@LaunchedEffect
}
hasExecuted = true
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
setFlashingStatus(FlashingStatus.FLASHING) setFlashingStatus(FlashingStatus.FLASHING)
@@ -210,8 +272,13 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
} }
val onBack: () -> Unit = { val onBack: () -> Unit = {
if (currentFlashingStatus.value != FlashingStatus.FLASHING) { val canGoBack = when (flashIt) {
if (flashIt is FlashIt.FlashModules) { is FlashIt.FlashModuleUpdate -> currentFlashingStatus.value != FlashingStatus.FLASHING
else -> currentFlashingStatus.value != FlashingStatus.FLASHING
}
if (canGoBack) {
if (flashIt is FlashIt.FlashModules || flashIt is FlashIt.FlashModuleUpdate) {
viewModel.markNeedRefresh() viewModel.markNeedRefresh()
viewModel.fetchModuleList() viewModel.fetchModuleList()
navigator.navigate(ModuleScreenDestination) navigator.navigate(ModuleScreenDestination)
@@ -360,7 +427,7 @@ fun ModuleInstallProgressBar(
horizontalArrangement = Arrangement.SpaceBetween horizontalArrangement = Arrangement.SpaceBetween
) { ) {
Text( Text(
text = if (currentModuleName.isNotEmpty()) currentModuleName else stringResource(R.string.module), text = currentModuleName.ifEmpty { stringResource(R.string.module) },
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
@@ -532,10 +599,21 @@ sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : FlashIt() data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : FlashIt()
data class FlashModule(val uri: Uri) : FlashIt() data class FlashModule(val uri: Uri) : FlashIt()
data class FlashModules(val uris: List<Uri>, val currentIndex: Int = 0) : FlashIt() data class FlashModules(val uris: List<Uri>, val currentIndex: Int = 0) : FlashIt()
data class FlashModuleUpdate(val uri: Uri) : FlashIt() // 模块更新
data object FlashRestore : FlashIt() data object FlashRestore : FlashIt()
data object FlashUninstall : FlashIt() data object FlashUninstall : FlashIt()
} }
// 模块更新刷写
fun flashModuleUpdate(
uri: Uri,
onFinish: (Boolean, Int) -> Unit,
onStdout: (String) -> Unit,
onStderr: (String) -> Unit
) {
flashModule(uri, onFinish, onStdout, onStderr)
}
fun flashIt( fun flashIt(
flashIt: FlashIt, flashIt: FlashIt,
onFinish: (Boolean, Int) -> Unit, onFinish: (Boolean, Int) -> Unit,
@@ -563,6 +641,9 @@ fun flashIt(
flashModule(currentUri, onFinish, onStdout, onStderr) flashModule(currentUri, onFinish, onStdout, onStderr)
} }
is FlashIt.FlashModuleUpdate -> {
onFinish(false, 0)
}
FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr) FlashIt.FlashRestore -> restoreBoot(onFinish, onStdout, onStderr)
FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr) FlashIt.FlashUninstall -> uninstallPermanently(onFinish, onStdout, onStderr)
} }

View File

@@ -170,8 +170,8 @@ fun HomeScreen(navigator: DestinationsNavigator) {
if (viewModel.systemStatus.requireNewKernel) { if (viewModel.systemStatus.requireNewKernel) {
WarningCard( WarningCard(
stringResource(id = R.string.require_kernel_version).format( stringResource(id = R.string.require_kernel_version).format(
viewModel.systemStatus.ksuVersion, Natives.getSimpleVersionFull(),
Natives.MINIMAL_SUPPORTED_KERNEL Natives.MINIMAL_SUPPORTED_KERNEL_FULL
) )
) )
} }
@@ -192,6 +192,7 @@ fun HomeScreen(navigator: DestinationsNavigator) {
systemInfo = viewModel.systemInfo, systemInfo = viewModel.systemInfo,
isSimpleMode = viewModel.isSimpleMode, isSimpleMode = viewModel.isSimpleMode,
isHideSusfsStatus = viewModel.isHideSusfsStatus, isHideSusfsStatus = viewModel.isHideSusfsStatus,
isHideZygiskImplement = viewModel.isHideZygiskImplement,
showKpmInfo = viewModel.showKpmInfo, showKpmInfo = viewModel.showKpmInfo,
lkmMode = viewModel.systemStatus.lkmMode, lkmMode = viewModel.systemStatus.lkmMode,
) )
@@ -261,8 +262,8 @@ fun UpdateCard() {
@Composable @Composable
fun RebootDropdownItem(@StringRes id: Int, reason: String = "") { fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
DropdownMenuItem( DropdownMenuItem(
text = {Text(stringResource(id))}, text = { Text(stringResource(id)) },
onClick = {reboot(reason)}) onClick = { reboot(reason) })
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -319,7 +320,8 @@ private fun TopBar(
}) { }) {
RebootDropdownItem(id = R.string.reboot) RebootDropdownItem(id = R.string.reboot)
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager? val pm =
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace") RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
@@ -343,8 +345,10 @@ private fun StatusCard(
onClickInstall: () -> Unit = {} onClickInstall: () -> Unit = {}
) { ) {
ElevatedCard( ElevatedCard(
colors = getCardColors( if (systemStatus.ksuVersion != null)MaterialTheme.colorScheme.secondaryContainer colors = getCardColors(
else MaterialTheme.colorScheme.errorContainer), if (systemStatus.ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.errorContainer
),
elevation = getCardElevation(), elevation = getCardElevation(),
) { ) {
Row( Row(
@@ -433,19 +437,24 @@ private fun StatusCard(
} }
} }
val isHideVersion = LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE) val isHideVersion = LocalContext.current.getSharedPreferences(
"settings",
Context.MODE_PRIVATE
)
.getBoolean("is_hide_version", false) .getBoolean("is_hide_version", false)
if (!isHideVersion) { if (!isHideVersion) {
Spacer(Modifier.height(4.dp)) Spacer(Modifier.height(4.dp))
systemStatus.ksuFullVersion?.let {
Text( Text(
text = stringResource(R.string.home_working_version, systemStatus.ksuVersion), text = stringResource(R.string.home_working_version, it),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
) )
} }
} }
} }
}
systemStatus.kernelVersion.isGKI() -> { systemStatus.kernelVersion.isGKI() -> {
Icon( Icon(
@@ -639,6 +648,7 @@ private fun InfoCard(
systemInfo: HomeViewModel.SystemInfo, systemInfo: HomeViewModel.SystemInfo,
isSimpleMode: Boolean, isSimpleMode: Boolean,
isHideSusfsStatus: Boolean, isHideSusfsStatus: Boolean,
isHideZygiskImplement: Boolean,
showKpmInfo: Boolean, showKpmInfo: Boolean,
lkmMode: Boolean? lkmMode: Boolean?
) { ) {
@@ -677,7 +687,7 @@ private fun InfoCard(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.weight(1f) .weight(1f)
){ ) {
Text( Text(
text = label, text = label,
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
@@ -717,16 +727,56 @@ private fun InfoCard(
icon = Icons.Default.SettingsSuggest, icon = Icons.Default.SettingsSuggest,
) )
// 活跃管理器
if (!isSimpleMode && systemInfo.isDynamicSignEnabled && systemInfo.managersList != null) {
val signatureMap = systemInfo.managersList.managers.groupBy { it.signatureIndex }
val managersText = buildString {
signatureMap.toSortedMap().forEach { (signatureIndex, managers) ->
append(managers.joinToString(", ") { "UID: ${it.uid}" })
append(" ")
append(
when (signatureIndex) {
1 -> "(${stringResource(R.string.default_signature)})"
2 -> "(${stringResource(R.string.dynamic_signature)})"
else -> if (signatureIndex >= 0) "(${
stringResource(
R.string.signature_index,
signatureIndex
)
})" else "(${stringResource(R.string.unknown_signature)})"
}
)
append(" | ")
}
}.trimEnd(' ', '|')
InfoCardItem(
stringResource(R.string.multi_manager_list),
managersText.ifEmpty { stringResource(R.string.no_active_manager) },
icon = Icons.Default.Group,
)
}
InfoCardItem( InfoCardItem(
stringResource(R.string.home_selinux_status), stringResource(R.string.home_selinux_status),
systemInfo.seLinuxStatus, systemInfo.seLinuxStatus,
icon = Icons.Default.Security, icon = Icons.Default.Security,
) )
if (!isHideZygiskImplement && !isSimpleMode && systemInfo.zygiskImplement != "None") {
InfoCardItem(
stringResource(R.string.home_zygisk_implement),
systemInfo.zygiskImplement,
icon = Icons.Default.Adb,
)
}
if (!isSimpleMode) { if (!isSimpleMode) {
// 根据showKpmInfo决定是否显示KPM信息 // 根据showKpmInfo决定是否显示KPM信息
if (lkmMode != true && !showKpmInfo && Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) { if (lkmMode != true && !showKpmInfo) {
val displayVersion = if (systemInfo.kpmVersion.isEmpty() || systemInfo.kpmVersion.startsWith("Error")) { val displayVersion =
if (systemInfo.kpmVersion.isEmpty() || systemInfo.kpmVersion.startsWith("Error")) {
val statusText = if (Natives.isKPMEnabled()) { val statusText = if (Natives.isKPMEnabled()) {
stringResource(R.string.kernel_patched) stringResource(R.string.kernel_patched)
} else { } else {
@@ -747,7 +797,8 @@ private fun InfoCard(
if (!isSimpleMode && !isHideSusfsStatus && if (!isSimpleMode && !isHideSusfsStatus &&
systemInfo.suSFSStatus == "Supported" && systemInfo.suSFSStatus == "Supported" &&
systemInfo.suSFSVersion.isNotEmpty()) { systemInfo.suSFSVersion.isNotEmpty()
) {
val infoText = SuSFSInfoText(systemInfo) val infoText = SuSFSInfoText(systemInfo)
@@ -776,9 +827,11 @@ private fun SuSFSInfoText(systemInfo: HomeViewModel.SystemInfo): String = buildS
append(" ${stringResource(R.string.sus_su_mode)} ${systemInfo.susSUMode}") append(" ${stringResource(R.string.sus_su_mode)} ${systemInfo.susSUMode}")
} }
} }
Natives.getHookType() == "Manual" -> { Natives.getHookType() == "Manual" -> {
append(" (${stringResource(R.string.manual_hook)})") append(" (${stringResource(R.string.manual_hook)})")
} }
else -> { else -> {
append(" (${Natives.getHookType()})") append(" (${Natives.getHookType()})")
} }

View File

@@ -186,7 +186,7 @@ fun InstallScreen(navigator: DestinationsNavigator) {
} }
val onClickNext = { val onClickNext = {
if (isGKI && lkmSelection == LkmSelection.KmiNone && currentKmi.isBlank()) { if (isGKI && lkmSelection == LkmSelection.KmiNone && currentKmi.isBlank() && installMethod !is InstallMethod.HorizonKernel) {
selectKmiDialog.show() selectKmiDialog.show()
} else { } else {
onInstall() onInstall()
@@ -373,7 +373,11 @@ private fun SelectInstallMethod(
val horizonKernelSummary = stringResource(R.string.horizon_kernel_summary) val horizonKernelSummary = stringResource(R.string.horizon_kernel_summary)
val selectFileTip = stringResource( val selectFileTip = stringResource(
id = R.string.select_file_tip, id = R.string.select_file_tip,
if (isInitBoot()) "init_boot" else "boot" if (isInitBoot()) {
"init_boot / vendor_boot ${stringResource(R.string.select_file_tip_vendor)}"
} else {
"boot"
}
) )
val radioOptions = mutableListOf<InstallMethod>( val radioOptions = mutableListOf<InstallMethod>(

View File

@@ -5,11 +5,8 @@ import android.content.Intent
import android.util.Log import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@@ -19,7 +16,6 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@@ -27,7 +23,6 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.sukisu.ultra.ui.component.* import com.sukisu.ultra.ui.component.*
@@ -37,13 +32,10 @@ import com.sukisu.ultra.ui.util.*
import java.io.File import java.io.File
import androidx.core.content.edit import androidx.core.content.edit
import com.sukisu.ultra.R import com.sukisu.ultra.R
import java.io.BufferedReader
import java.io.FileInputStream import java.io.FileInputStream
import java.io.InputStreamReader
import java.net.* import java.net.*
import android.app.Activity import android.app.Activity
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
/** /**
* KPM 管理界面 * KPM 管理界面
@@ -54,7 +46,6 @@ import com.sukisu.ultra.ui.theme.CardConfig.cardElevation
@Destination<RootGraph> @Destination<RootGraph>
@Composable @Composable
fun KpmScreen( fun KpmScreen(
navigator: DestinationsNavigator,
viewModel: KpmViewModel = viewModel() viewModel: KpmViewModel = viewModel()
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -92,18 +83,17 @@ fun KpmScreen(
LaunchedEffect(tempFileForInstall) { LaunchedEffect(tempFileForInstall) {
tempFileForInstall?.let { tempFile -> tempFileForInstall?.let { tempFile ->
try { try {
val command = arrayOf("su", "-c", "strings ${tempFile.absolutePath} | grep 'name='") val shell = getRootShell()
val process = Runtime.getRuntime().exec(command) val command = "strings ${tempFile.absolutePath} | grep 'name='"
val inputStream = process.inputStream val result = shell.newJob().add(command).to(ArrayList(), null).exec()
val reader = BufferedReader(InputStreamReader(inputStream)) if (result.isSuccess) {
var line: String? for (line in result.out) {
while (reader.readLine().also { line = it } != null) { if (line.startsWith("name=")) {
if (line!!.startsWith("name=")) {
moduleName = line.substringAfter("name=").trim() moduleName = line.substringAfter("name=").trim()
break break
} }
} }
process.waitFor() }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("KsuCli", "Failed to get module name: ${e.message}", e) Log.e("KsuCli", "Failed to get module name: ${e.message}", e)
} }
@@ -434,18 +424,17 @@ private suspend fun handleModuleInstall(
) { ) {
var moduleId: String? = null var moduleId: String? = null
try { try {
val command = arrayOf("su", "-c", "strings ${tempFile.absolutePath} | grep 'name='") val shell = getRootShell()
val process = Runtime.getRuntime().exec(command) val command = "strings ${tempFile.absolutePath} | grep 'name='"
val inputStream = process.inputStream val result = shell.newJob().add(command).to(ArrayList(), null).exec()
val reader = BufferedReader(InputStreamReader(inputStream)) if (result.isSuccess) {
var line: String? for (line in result.out) {
while (reader.readLine().also { line = it } != null) { if (line.startsWith("name=")) {
if (line!!.startsWith("name=")) {
moduleId = line.substringAfter("name=").trim() moduleId = line.substringAfter("name=").trim()
break break
} }
} }
process.waitFor() }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("KsuCli", "Failed to get module ID from strings command: ${e.message}", e) Log.e("KsuCli", "Failed to get module ID from strings command: ${e.message}", e)
} }
@@ -464,8 +453,9 @@ private suspend fun handleModuleInstall(
try { try {
if (isEmbed) { if (isEmbed) {
Runtime.getRuntime().exec(arrayOf("su", "-c", "mkdir -p /data/adb/kpm")).waitFor() val shell = getRootShell()
Runtime.getRuntime().exec(arrayOf("su", "-c", "cp ${tempFile.absolutePath} $targetPath")).waitFor() shell.newJob().add("mkdir -p /data/adb/kpm").exec()
shell.newJob().add("cp ${tempFile.absolutePath} $targetPath").exec()
} }
val loadResult = loadKpmModule(tempFile.absolutePath) val loadResult = loadKpmModule(tempFile.absolutePath)
@@ -509,8 +499,9 @@ private suspend fun handleModuleUninstall(
val moduleFilePath = "/data/adb/kpm/$moduleFileName" val moduleFilePath = "/data/adb/kpm/$moduleFileName"
val fileExists = try { val fileExists = try {
val result = Runtime.getRuntime().exec(arrayOf("su", "-c", "ls /data/adb/kpm/$moduleFileName")).waitFor() == 0 val shell = getRootShell()
result val result = shell.newJob().add("ls /data/adb/kpm/$moduleFileName").exec()
result.isSuccess
} catch (e: Exception) { } catch (e: Exception) {
Log.e("KsuCli", "Failed to check module file existence: ${e.message}", e) Log.e("KsuCli", "Failed to check module file existence: ${e.message}", e)
snackBarHost.showSnackbar( snackBarHost.showSnackbar(
@@ -519,6 +510,7 @@ private suspend fun handleModuleUninstall(
) )
false false
} }
val confirmResult = confirmDialog.awaitConfirm( val confirmResult = confirmDialog.awaitConfirm(
title = confirmTitle, title = confirmTitle,
content = confirmContent, content = confirmContent,
@@ -539,7 +531,8 @@ private suspend fun handleModuleUninstall(
} }
if (fileExists) { if (fileExists) {
Runtime.getRuntime().exec(arrayOf("su", "-c", "rm $moduleFilePath")).waitFor() val shell = getRootShell()
shell.newJob().add("rm $moduleFilePath").exec()
} }
viewModel.fetchModuleList() viewModel.fetchModuleList()
@@ -710,29 +703,31 @@ private fun KpmModuleItem(
} }
private fun checkStringsCommand(tempFile: File): Int { private fun checkStringsCommand(tempFile: File): Int {
val command = arrayOf("su", "-c", "strings ${tempFile.absolutePath} | grep -E 'name=|version=|license=|author='") val shell = getRootShell()
val process = Runtime.getRuntime().exec(command) val command = "strings ${tempFile.absolutePath} | grep -E 'name=|version=|license=|author='"
val inputStream = process.inputStream val result = shell.newJob().add(command).to(ArrayList(), null).exec()
val reader = BufferedReader(InputStreamReader(inputStream))
var line: String? if (!result.isSuccess) {
return 0
}
var matchCount = 0 var matchCount = 0
val keywords = listOf("name=", "version=", "license=", "author=") val keywords = listOf("name=", "version=", "license=", "author=")
var nameExists = false var nameExists = false
while (reader.readLine().also { line = it } != null) { for (line in result.out) {
if (!nameExists && line!!.startsWith("name=")) { if (!nameExists && line.startsWith("name=")) {
nameExists = true nameExists = true
matchCount++ matchCount++
} else if (nameExists) { } else if (nameExists) {
for (keyword in keywords) { for (keyword in keywords) {
if (line!!.startsWith(keyword)) { if (line.startsWith(keyword)) {
matchCount++ matchCount++
break break
} }
} }
} }
} }
process.waitFor()
return if (nameExists) matchCount else 0 return if (nameExists) matchCount else 0
} }

View File

@@ -352,6 +352,9 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
onInstallModule = { onInstallModule = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it))) navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
}, },
onUpdateModule = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModuleUpdate(it)))
},
onClickModule = { id, name, hasWebUi -> onClickModule = { id, name, hasWebUi ->
val currentTime = System.currentTimeMillis() val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime < 600) { if (currentTime - lastClickTime < 600) {
@@ -622,6 +625,7 @@ private fun ModuleList(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
boxModifier: Modifier = Modifier, boxModifier: Modifier = Modifier,
onInstallModule: (Uri) -> Unit, onInstallModule: (Uri) -> Unit,
onUpdateModule: (Uri) -> Unit,
onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit, onClickModule: (id: String, name: String, hasWebUi: Boolean) -> Unit,
context: Context, context: Context,
snackBarHost: SnackbarHostState snackBarHost: SnackbarHostState
@@ -709,7 +713,7 @@ private fun ModuleList(
downloadUrl, downloadUrl,
fileName, fileName,
downloading, downloading,
onDownloaded = onInstallModule, onDownloaded = onUpdateModule,
onDownloading = { onDownloading = {
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
Toast.makeText(context, downloading, Toast.LENGTH_SHORT).show() Toast.makeText(context, downloading, Toast.LENGTH_SHORT).show()

View File

@@ -122,11 +122,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
// 配置卡片 // 配置卡片
KsuIsValid {
SettingsGroupCard( SettingsGroupCard(
title = stringResource(R.string.configuration), title = stringResource(R.string.configuration),
content = { content = {
// 配置文件模板入口 // 配置文件模板入口
KsuIsValid {
SettingItem( SettingItem(
icon = Icons.Filled.Fence, icon = Icons.Filled.Fence,
title = stringResource(R.string.settings_profile_template), title = stringResource(R.string.settings_profile_template),
@@ -135,14 +135,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
navigator.navigate(AppProfileTemplateScreenDestination) navigator.navigate(AppProfileTemplateScreenDestination)
} }
) )
}
// 卸载模块开关 // 卸载模块开关
var umountChecked by rememberSaveable { var umountChecked by rememberSaveable {
mutableStateOf(Natives.isDefaultUmountModules()) mutableStateOf(Natives.isDefaultUmountModules())
} }
KsuIsValid {
SwitchItem( SwitchItem(
icon = Icons.Filled.FolderDelete, icon = Icons.Filled.FolderDelete,
title = stringResource(R.string.settings_umount_modules_default), title = stringResource(R.string.settings_umount_modules_default),
@@ -154,10 +152,8 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
} }
) )
}
// SU 禁用开关 // SU 禁用开关
KsuIsValid {
if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) { if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) {
var isSuDisabled by rememberSaveable { var isSuDisabled by rememberSaveable {
mutableStateOf(!Natives.isSuEnabled()) mutableStateOf(!Natives.isSuEnabled())
@@ -176,8 +172,8 @@ fun SettingScreen(navigator: DestinationsNavigator) {
) )
} }
} }
}
) )
}
// 应用设置卡片 // 应用设置卡片
SettingsGroupCard( SettingsGroupCard(

View File

@@ -1,5 +1,6 @@
package com.sukisu.ultra.ui.screen package com.sukisu.ultra.ui.screen
import android.annotation.SuppressLint
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.animation.core.* import androidx.compose.animation.core.*
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -26,7 +27,6 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale import androidx.compose.ui.draw.scale
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -462,13 +462,14 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
// 根据加载状态显示不同内容 // 根据加载状态显示不同内容
if (viewModel.isRefreshing || viewModel.appList.isEmpty()) { if ((viewModel.isRefreshing || viewModel.appList.isEmpty()) && viewModel.search.isEmpty()) {
LoadingAnimation( LoadingAnimation(
isLoading = true isLoading = true
) )
} else { } else {
EmptyState( EmptyState(
selectedCategory = selectedCategory selectedCategory = selectedCategory,
isSearchEmpty = viewModel.search.isNotEmpty()
) )
} }
} }
@@ -900,17 +901,6 @@ private fun LoadingAnimation(
) { ) {
val infiniteTransition = rememberInfiniteTransition(label = "loading") val infiniteTransition = rememberInfiniteTransition(label = "loading")
// 旋转动画
val rotation by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "rotation"
)
// 透明度动画 // 透明度动画
val alpha by infiniteTransition.animateFloat( val alpha by infiniteTransition.animateFloat(
initialValue = 0.3f, initialValue = 0.3f,
@@ -932,18 +922,6 @@ private fun LoadingAnimation(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
// 主加载图标
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary.copy(alpha = alpha),
modifier = Modifier
.size(64.dp)
.rotate(rotation)
)
Spacer(modifier = Modifier.height(16.dp))
// 进度指示器 // 进度指示器
LinearProgressIndicator( LinearProgressIndicator(
modifier = Modifier modifier = Modifier
@@ -960,9 +938,11 @@ private fun LoadingAnimation(
* 空状态组件 * 空状态组件
*/ */
@Composable @Composable
@SuppressLint("ModifierParameter")
private fun EmptyState( private fun EmptyState(
selectedCategory: AppCategory, selectedCategory: AppCategory,
modifier: Modifier = Modifier modifier: Modifier = Modifier,
isSearchEmpty: Boolean = false
) { ) {
Column( Column(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
@@ -970,7 +950,7 @@ private fun EmptyState(
modifier = modifier modifier = modifier
) { ) {
Icon( Icon(
imageVector = Icons.Filled.Archive, imageVector = if (isSearchEmpty) Icons.Filled.SearchOff else Icons.Filled.Archive,
contentDescription = null, contentDescription = null,
tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.6f), tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.6f),
modifier = Modifier modifier = Modifier
@@ -978,7 +958,7 @@ private fun EmptyState(
.padding(bottom = 16.dp) .padding(bottom = 16.dp)
) )
Text( Text(
text = if (selectedCategory == AppCategory.ALL) { text = if (isSearchEmpty || selectedCategory == AppCategory.ALL) {
stringResource(R.string.no_apps_found) stringResource(R.string.no_apps_found)
} else { } else {
stringResource(R.string.no_apps_in_category) stringResource(R.string.no_apps_in_category)

View File

@@ -1,581 +0,0 @@
package com.sukisu.ultra.ui.screen.extensions
import android.annotation.SuppressLint
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.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
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.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Update
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
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.unit.dp
import androidx.compose.ui.unit.sp
import com.sukisu.ultra.R
import com.sukisu.ultra.ui.util.SuSFSManager
import kotlinx.coroutines.launch
/**
* 空状态显示组件
*/
@Composable
fun EmptyStateCard(
message: String,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.2f)
),
shape = RoundedCornerShape(12.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
contentAlignment = Alignment.Center
) {
Text(
text = message,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center
)
}
}
}
/**
* 路径项目卡片组件
*/
@Composable
fun PathItemCard(
path: String,
icon: ImageVector,
onDelete: () -> Unit,
isLoading: Boolean = false,
additionalInfo: String? = null
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = path,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (additionalInfo != null) {
Text(
text = additionalInfo,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
/**
* Kstat配置项目卡片组件
*/
@Composable
fun KstatConfigItemCard(
config: String,
onDelete: () -> Unit,
isLoading: Boolean = false
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Column {
val parts = config.split("|")
if (parts.isNotEmpty()) {
Text(
text = parts[0], // 路径
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (parts.size > 1) {
Text(
text = "${parts.drop(1).joinToString(" ")}",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
} else {
Text(
text = config,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
}
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
/**
* Add Kstat路径项目卡片组件
*/
@Composable
fun AddKstatPathItemCard(
path: String,
onDelete: () -> Unit,
onUpdate: () -> Unit,
onUpdateFullClone: () -> Unit,
isLoading: Boolean = false
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 1.dp),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.weight(1f)
) {
Icon(
imageVector = Icons.Default.Folder,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = path,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
IconButton(
onClick = onUpdate,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Update,
contentDescription = null,
tint = MaterialTheme.colorScheme.secondary,
modifier = Modifier.size(16.dp)
)
}
IconButton(
onClick = onUpdateFullClone,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.PlayArrow,
contentDescription = null,
tint = MaterialTheme.colorScheme.tertiary,
modifier = Modifier.size(16.dp)
)
}
IconButton(
onClick = onDelete,
enabled = !isLoading,
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
modifier = Modifier.size(16.dp)
)
}
}
}
}
}
/**
* 启用功能状态卡片组件
*/
@Composable
fun FeatureStatusCard(
feature: SuSFSManager.EnabledFeature,
onRefresh: (() -> Unit)? = null,
@SuppressLint("ModifierParameter") modifier: Modifier = Modifier
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
// 日志配置对话框状态
var showLogConfigDialog by remember { mutableStateOf(false) }
var logEnabled by remember { mutableStateOf(SuSFSManager.getEnableLogState(context)) }
// 日志配置对话框
if (showLogConfigDialog) {
AlertDialog(
onDismissRequest = { showLogConfigDialog = false },
title = {
Text(
text = stringResource(R.string.susfs_log_config_title),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
text = stringResource(R.string.susfs_log_config_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.susfs_enable_log_label),
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
Switch(
checked = logEnabled,
onCheckedChange = { logEnabled = it }
)
}
}
},
confirmButton = {
Button(
onClick = {
coroutineScope.launch {
if (SuSFSManager.setEnableLog(context, logEnabled)) {
onRefresh?.invoke()
}
showLogConfigDialog = false
}
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.susfs_apply))
}
},
dismissButton = {
TextButton(
onClick = {
// 恢复原始状态
logEnabled = SuSFSManager.getEnableLogState(context)
showLogConfigDialog = false
},
shape = RoundedCornerShape(8.dp)
) {
Text(stringResource(R.string.cancel))
}
},
shape = RoundedCornerShape(12.dp)
)
}
Card(
modifier = modifier
.fillMaxWidth()
.padding(vertical = 1.dp)
.then(
if (feature.canConfigure) {
Modifier.clickable {
// 更新当前状态
logEnabled = SuSFSManager.getEnableLogState(context)
showLogConfigDialog = true
}
} else {
Modifier
}
),
shape = RoundedCornerShape(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = feature.name,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
if (feature.canConfigure) {
Text(
text = stringResource(R.string.susfs_feature_configurable),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 状态标签
Surface(
shape = RoundedCornerShape(6.dp),
color = when {
feature.isEnabled -> MaterialTheme.colorScheme.primary
else -> Color.Gray
}
) {
Text(
text = feature.statusText,
style = MaterialTheme.typography.labelLarge,
color = when {
feature.isEnabled -> MaterialTheme.colorScheme.onPrimary
else -> Color.White
},
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp)
)
}
}
}
}
}
/**
* SUS挂载隐藏控制卡片组件
*/
@Composable
fun SusMountHidingControlCard(
hideSusMountsForAllProcs: Boolean,
isLoading: Boolean,
onToggleHiding: (Boolean) -> Unit
) {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 标题行
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = if (hideSusMountsForAllProcs) Icons.Default.VisibilityOff else Icons.Default.Visibility,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.susfs_hide_mounts_control_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSurface
)
}
// 描述文本
Text(
text = stringResource(R.string.susfs_hide_mounts_control_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 16.sp
)
// 控制开关行
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = stringResource(R.string.susfs_hide_mounts_for_all_procs_label),
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = if (hideSusMountsForAllProcs) {
stringResource(R.string.susfs_hide_mounts_for_all_procs_enabled_description)
} else {
stringResource(R.string.susfs_hide_mounts_for_all_procs_disabled_description)
},
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp
)
}
Switch(
checked = hideSusMountsForAllProcs,
onCheckedChange = onToggleHiding,
enabled = !isLoading
)
}
// 当前设置显示
Text(
text = stringResource(
R.string.susfs_hide_mounts_current_setting,
if (hideSusMountsForAllProcs) {
stringResource(R.string.susfs_hide_mounts_setting_all)
} else {
stringResource(R.string.susfs_hide_mounts_setting_non_ksu)
}
),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Medium
)
// 建议文本
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f)
),
shape = RoundedCornerShape(8.dp)
) {
Text(
text = stringResource(R.string.susfs_hide_mounts_recommendation),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
lineHeight = 14.sp,
modifier = Modifier.padding(12.dp)
)
}
}
}
}

View File

@@ -223,7 +223,11 @@ fun restoreBoot(
onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit
): Boolean { ): Boolean {
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libzakoboot.so") val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libzakoboot.so")
val result = flashWithIO("${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot", onStdout, onStderr) val result = flashWithIO(
"${getKsuDaemonPath()} boot-restore -f --magiskboot $magiskboot",
onStdout,
onStderr
)
onFinish(result.isSuccess, result.code) onFinish(result.isSuccess, result.code)
return result.isSuccess return result.isSuccess
} }
@@ -232,7 +236,8 @@ fun uninstallPermanently(
onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit onFinish: (Boolean, Int) -> Unit, onStdout: (String) -> Unit, onStderr: (String) -> Unit
): Boolean { ): Boolean {
val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libzakoboot.so") val magiskboot = File(ksuApp.applicationInfo.nativeLibraryDir, "libzakoboot.so")
val result = flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr) val result =
flashWithIO("${getKsuDaemonPath()} uninstall --magiskboot $magiskboot", onStdout, onStderr)
onFinish(result.isSuccess, result.code) onFinish(result.isSuccess, result.code)
return result.isSuccess return result.isSuccess
} }
@@ -457,6 +462,7 @@ fun getSuSFSVariant(): String {
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} variant") val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} variant")
return result return result
} }
fun getSuSFSFeatures(): String { fun getSuSFSFeatures(): String {
val shell = getRootShell() val shell = getRootShell()
val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features") val result = ShellUtils.fastCmd(shell, "${getSuSFSDaemonPath()} features")
@@ -505,7 +511,7 @@ fun getKpmModuleCount(): Int {
return result.trim().toIntOrNull() ?: 0 return result.trim().toIntOrNull() ?: 0
} }
fun runCmd(shell : Shell, cmd : String) : String { fun runCmd(shell: Shell, cmd: String): String {
return shell.newJob() return shell.newJob()
.add(cmd) .add(cmd)
.to(mutableListOf<String>(), null) .to(mutableListOf<String>(), null)
@@ -548,3 +554,18 @@ fun getKpmVersion(): String {
val result = ShellUtils.fastCmd(shell, cmd) val result = ShellUtils.fastCmd(shell, cmd)
return result.trim() return result.trim()
} }
fun getZygiskImplement(): String {
val shell = getRootShell()
val zygiskPath = "/data/adb/modules/zygisksu"
val rezygiskPath = "/data/adb/modules/rezygisk"
val result = if (ShellUtils.fastCmdResult(shell, "test -f $zygiskPath/module.prop && test ! -f $zygiskPath/disable")) {
ShellUtils.fastCmd(shell, "grep '^name=' $zygiskPath/module.prop | cut -d'=' -f2")
} else if (ShellUtils.fastCmdResult(shell, "test -f $rezygiskPath/module.prop && test ! -f $rezygiskPath/disable")) {
ShellUtils.fastCmd(shell, "grep '^name=' $rezygiskPath/module.prop | cut -d'=' -f2")
} else {
"None"
}
Log.i(TAG, "Zygisk implement: $result")
return result
}

View File

@@ -9,14 +9,22 @@ import android.annotation.SuppressLint
object ScriptGenerator { object ScriptGenerator {
// 常量定义 // 常量定义
@SuppressLint("SdCardPath")
private const val DEFAULT_ANDROID_DATA_PATH = "/sdcard/Android/data"
@SuppressLint("SdCardPath")
private const val DEFAULT_SDCARD_PATH = "/sdcard"
private const val DEFAULT_UNAME = "default" private const val DEFAULT_UNAME = "default"
private const val DEFAULT_BUILD_TIME = "default" private const val DEFAULT_BUILD_TIME = "default"
private const val LOG_DIR = "/data/adb/ksu/log" private const val LOG_DIR = "/data/adb/ksu/log"
/**
* 生成所有脚本文件
*/
fun generateAllScripts(config: SuSFSManager.ModuleConfig): Map<String, String> {
return mapOf(
"service.sh" to generateServiceScript(config),
"post-fs-data.sh" to generatePostFsDataScript(config),
"post-mount.sh" to generatePostMountScript(config),
"boot-completed.sh" to generateBootCompletedScript(config)
)
}
// 日志相关的通用脚本片段 // 日志相关的通用脚本片段
private fun generateLogSetup(logFileName: String): String = """ private fun generateLogSetup(logFileName: String): String = """
# 日志目录 # 日志目录
@@ -46,18 +54,7 @@ object ScriptGenerator {
* 生成service.sh脚本内容 * 生成service.sh脚本内容
*/ */
@SuppressLint("SdCardPath") @SuppressLint("SdCardPath")
fun generateServiceScript( private fun generateServiceScript(config: SuSFSManager.ModuleConfig): String {
targetPath: String,
unameValue: String,
buildTimeValue: String,
susPaths: Set<String>,
androidDataPath: String,
sdcardPath: String,
enableLog: Boolean,
executeInPostFsData: Boolean = false,
kstatConfigs: Set<String> = emptySet(),
addKstatPaths: Set<String> = emptySet()
): String {
return buildString { return buildString {
appendLine("#!/system/bin/sh") appendLine("#!/system/bin/sh")
appendLine("# SuSFS Service Script") appendLine("# SuSFS Service Script")
@@ -65,31 +62,53 @@ object ScriptGenerator {
appendLine() appendLine()
appendLine(generateLogSetup("susfs_service.log")) appendLine(generateLogSetup("susfs_service.log"))
appendLine() appendLine()
appendLine(generateBinaryCheck(targetPath)) appendLine(generateBinaryCheck(config.targetPath))
appendLine() appendLine()
// 设置日志启用状态 if (shouldConfigureInService(config)) {
generateLogSettingSection(enableLog) // 添加SUS路径 (仅在不支持隐藏挂载时)
if (!config.support158 && config.susPaths.isNotEmpty()) {
// 设置路径 appendLine()
generatePathSettingSection(androidDataPath, sdcardPath) appendLine("until [ -d \"/sdcard/Android\" ]; do sleep 1; done")
appendLine("sleep 45")
// 添加SUS路径 generateSusPathsSection(config.susPaths)
generateSusPathsSection(susPaths) }
// 添加Kstat配置
generateKstatSection(kstatConfigs, addKstatPaths)
// 设置uname和构建时间 // 设置uname和构建时间
generateUnameSection(unameValue, buildTimeValue, executeInPostFsData) generateUnameSection(config)
// 添加Kstat配置
generateKstatSection(config.kstatConfigs, config.addKstatPaths)
}
// 添加日志设置
generateLogSettingSection(config.enableLog)
// 隐藏BL相关配置 // 隐藏BL相关配置
if (config.enableHideBl) {
generateHideBlSection() generateHideBlSection()
}
// 清理工具残留
if (config.enableCleanupResidue) {
generateCleanupResidueSection()
}
appendLine("echo \"$(get_current_time): Service脚本执行完成\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Service脚本执行完成\" >> \"${'$'}LOG_FILE\"")
} }
} }
/**
* 判断是否需要在service中配置
*/
private fun shouldConfigureInService(config: SuSFSManager.ModuleConfig): Boolean {
return config.susPaths.isNotEmpty() ||
config.susLoopPaths.isNotEmpty() ||
config.kstatConfigs.isNotEmpty() ||
config.addKstatPaths.isNotEmpty() ||
(!config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME))
}
private fun StringBuilder.generateLogSettingSection(enableLog: Boolean) { private fun StringBuilder.generateLogSettingSection(enableLog: Boolean) {
appendLine("# 设置日志启用状态") appendLine("# 设置日志启用状态")
val logValue = if (enableLog) 1 else 0 val logValue = if (enableLog) 1 else 0
@@ -98,27 +117,6 @@ object ScriptGenerator {
appendLine() appendLine()
} }
private fun StringBuilder.generatePathSettingSection(
androidDataPath: String,
sdcardPath: String
) {
// 设置Android Data路径
if (androidDataPath != DEFAULT_ANDROID_DATA_PATH) {
appendLine("# 设置Android Data路径")
appendLine("\"${'$'}SUSFS_BIN\" set_android_data_root_path '$androidDataPath'")
appendLine("echo \"$(get_current_time): Android Data路径设置为: $androidDataPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
// 设置SD卡路径
if (sdcardPath != DEFAULT_SDCARD_PATH) {
appendLine("# 设置SD卡路径")
appendLine("\"${'$'}SUSFS_BIN\" set_sdcard_root_path '$sdcardPath'")
appendLine("echo \"$(get_current_time): SD卡路径设置为: $sdcardPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
}
private fun StringBuilder.generateSusPathsSection(susPaths: Set<String>) { private fun StringBuilder.generateSusPathsSection(susPaths: Set<String>) {
if (susPaths.isNotEmpty()) { if (susPaths.isNotEmpty()) {
appendLine("# 添加SUS路径") appendLine("# 添加SUS路径")
@@ -130,6 +128,18 @@ object ScriptGenerator {
} }
} }
private fun StringBuilder.generateSusLoopPathsSection(susLoopPaths: Set<String>) {
if (susLoopPaths.isNotEmpty()) {
appendLine("# 添加SUS循环路径")
susLoopPaths.forEach { path ->
appendLine("\"${'$'}SUSFS_BIN\" add_sus_path_loop '$path'")
appendLine("echo \"$(get_current_time): 添加SUS循环路径: $path\" >> \"${'$'}LOG_FILE\"")
}
appendLine()
}
}
@SuppressLint("SdCardPath")
private fun StringBuilder.generateKstatSection( private fun StringBuilder.generateKstatSection(
kstatConfigs: Set<String>, kstatConfigs: Set<String>,
addKstatPaths: Set<String> addKstatPaths: Set<String>
@@ -152,9 +162,10 @@ object ScriptGenerator {
if (parts.size >= 13) { if (parts.size >= 13) {
val path = parts[0] val path = parts[0]
val params = parts.drop(1).joinToString("' '", "'", "'") val params = parts.drop(1).joinToString("' '", "'", "'")
appendLine()
appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat_statically '$path' $params") appendLine("\"${'$'}SUSFS_BIN\" add_sus_kstat_statically '$path' $params")
appendLine("echo \"$(get_current_time): 添加Kstat静态配置: $path\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): 添加Kstat静态配置: $path\" >> \"${'$'}LOG_FILE\"")
appendLine()
appendLine("\"${'$'}SUSFS_BIN\" update_sus_kstat '$path'") appendLine("\"${'$'}SUSFS_BIN\" update_sus_kstat '$path'")
appendLine("echo \"$(get_current_time): 更新Kstat配置: $path\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): 更新Kstat配置: $path\" >> \"${'$'}LOG_FILE\"")
} }
@@ -163,15 +174,11 @@ object ScriptGenerator {
} }
} }
private fun StringBuilder.generateUnameSection( private fun StringBuilder.generateUnameSection(config: SuSFSManager.ModuleConfig) {
unameValue: String, if (!config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME)) {
buildTimeValue: String,
executeInPostFsData: Boolean
) {
if (!executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) {
appendLine("# 设置uname和构建时间") appendLine("# 设置uname和构建时间")
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'") appendLine("\"${'$'}SUSFS_BIN\" set_uname '${config.unameValue}' '${config.buildTimeValue}'")
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): 设置uname为: ${config.unameValue}, 构建时间为: ${config.buildTimeValue}\" >> \"${'$'}LOG_FILE\"")
appendLine() appendLine()
} }
} }
@@ -180,45 +187,50 @@ object ScriptGenerator {
appendLine("# 隐藏BL 来自 Shamiko 脚本") appendLine("# 隐藏BL 来自 Shamiko 脚本")
appendLine( appendLine(
""" """
RESETPROP_BIN="/data/adb/ksu/bin/resetprop"
check_reset_prop() { check_reset_prop() {
local NAME=$1 local NAME=$1
local EXPECTED=$2 local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME) local VALUE=$("${'$'}RESETPROP_BIN" ${'$'}NAME)
[ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || resetprop ${'$'}NAME ${'$'}EXPECTED [ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || "${'$'}RESETPROP_BIN" ${'$'}NAME ${'$'}EXPECTED
} }
check_missing_prop() { check_missing_prop() {
local NAME=$1 local NAME=$1
local EXPECTED=$2 local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME) local VALUE=$("${'$'}RESETPROP_BIN" ${'$'}NAME)
[ -z ${'$'}VALUE ] && resetprop ${'$'}NAME ${'$'}EXPECTED [ -z ${'$'}VALUE ] && "${'$'}RESETPROP_BIN" ${'$'}NAME ${'$'}EXPECTED
} }
check_missing_match_prop() { check_missing_match_prop() {
local NAME=$1 local NAME=$1
local EXPECTED=$2 local EXPECTED=$2
local VALUE=$(resetprop ${'$'}NAME) local VALUE=$("${'$'}RESETPROP_BIN" ${'$'}NAME)
[ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || resetprop ${'$'}NAME ${'$'}EXPECTED [ -z ${'$'}VALUE ] || [ ${'$'}VALUE = ${'$'}EXPECTED ] || "${'$'}RESETPROP_BIN" ${'$'}NAME ${'$'}EXPECTED
[ -z ${'$'}VALUE ] && resetprop ${'$'}NAME ${'$'}EXPECTED [ -z ${'$'}VALUE ] && "${'$'}RESETPROP_BIN" ${'$'}NAME ${'$'}EXPECTED
} }
contains_reset_prop() { contains_reset_prop() {
local NAME=$1 local NAME=$1
local CONTAINS=$2 local CONTAINS=$2
local NEWVAL=$3 local NEWVAL=$3
[[ "$(resetprop ${'$'}NAME)" = *"${'$'}CONTAINS"* ]] && resetprop ${'$'}NAME ${'$'}NEWVAL case "$("${'$'}RESETPROP_BIN" ${'$'}NAME)" in
*"${'$'}CONTAINS"*) "${'$'}RESETPROP_BIN" ${'$'}NAME ${'$'}NEWVAL ;;
esac
} }
""".trimIndent()) """.trimIndent())
appendLine() appendLine()
appendLine("sleep 30")
appendLine("resetprop -w sys.boot_completed 0")
appendLine() appendLine()
appendLine("\"${'$'}RESETPROP_BIN\" -w sys.boot_completed 0")
// 添加所有系统属性重置 // 添加所有系统属性重置
val systemProps = listOf( val systemProps = listOf(
"ro.boot.vbmeta.invalidate_on_error" to "yes", "ro.boot.vbmeta.invalidate_on_error" to "yes",
"ro.boot.vbmeta.avb_version" to "1.2", "ro.boot.vbmeta.avb_version" to "1.2",
"ro.boot.vbmeta.hash_alg" to "sha256", "ro.boot.vbmeta.hash_alg" to "sha256",
"ro.boot.vbmeta.size" to "19968",
"ro.boot.vbmeta.device_state" to "locked", "ro.boot.vbmeta.device_state" to "locked",
"ro.boot.verifiedbootstate" to "green", "ro.boot.verifiedbootstate" to "green",
"ro.boot.flash.locked" to "1", "ro.boot.flash.locked" to "1",
@@ -269,15 +281,89 @@ object ScriptGenerator {
appendLine() appendLine()
} }
// 清理残留脚本生成
private fun StringBuilder.generateCleanupResidueSection() {
appendLine("# 清理工具残留文件")
appendLine("echo \"$(get_current_time): 开始清理工具残留\" >> \"${'$'}LOG_FILE\"")
appendLine()
// 定义清理函数
appendLine("""
cleanup_path() {
local path="$1"
local desc="$2"
local current="$3"
local total="$4"
if [ -n "${'$'}desc" ]; then
echo "$(get_current_time): [${'$'}current/${'$'}total] 清理: ${'$'}path (${'$'}desc)" >> "${'$'}LOG_FILE"
else
echo "$(get_current_time): [${'$'}current/${'$'}total] 清理: ${'$'}path" >> "${'$'}LOG_FILE"
fi
if rm -rf "${'$'}path" 2>/dev/null; then
echo "$(get_current_time): ✓ 成功清理: ${'$'}path" >> "${'$'}LOG_FILE"
else
echo "$(get_current_time): ✗ 清理失败或不存在: ${'$'}path" >> "${'$'}LOG_FILE"
fi
}
""".trimIndent())
appendLine()
appendLine("# 开始清理各种工具残留")
appendLine("TOTAL=33")
appendLine()
val cleanupPaths = listOf(
"/data/local/stryker/" to "Stryker残留",
"/data/system/AppRetention" to "AppRetention残留",
"/data/local/tmp/luckys" to "Luck Tool残留",
"/data/local/tmp/HyperCeiler" to "西米露残留",
"/data/local/tmp/simpleHook" to "simple Hook残留",
"/data/local/tmp/DisabledAllGoogleServices" to "谷歌省电模块残留",
"/data/local/MIO" to "解包软件",
"/data/DNA" to "解包软件",
"/data/local/tmp/cleaner_starter" to "质感清理残留",
"/data/local/tmp/byyang" to "",
"/data/local/tmp/mount_mask" to "",
"/data/local/tmp/mount_mark" to "",
"/data/local/tmp/scriptTMP" to "",
"/data/local/luckys" to "",
"/data/local/tmp/horae_control.log" to "",
"/data/gpu_freq_table.conf" to "",
"/storage/emulated/0/Download/advanced/" to "",
"/storage/emulated/0/Documents/advanced/" to "爱玩机",
"/storage/emulated/0/Android/naki/" to "旧版asoulopt",
"/data/swap_config.conf" to "scene附加模块2",
"/data/local/tmp/resetprop" to "",
"/dev/cpuset/AppOpt/" to "AppOpt模块",
"/storage/emulated/0/Android/Clash/" to "Clash for Magisk模块",
"/storage/emulated/0/Android/Yume-Yunyun/" to "网易云后台优化模块",
"/data/local/tmp/Surfing_update" to "Surfing模块缓存",
"/data/encore/custom_default_cpu_gov" to "encore模块",
"/data/encore/default_cpu_gov" to "encore模块",
"/data/local/tmp/yshell" to "",
"/data/local/tmp/encore_logo.png" to "",
"/storage/emulated/legacy/" to "",
"/storage/emulated/elgg/" to "",
"/data/system/junge/" to "",
"/data/local/tmp/mount_namespace" to "挂载命名空间残留"
)
cleanupPaths.forEachIndexed { index, (path, desc) ->
val current = index + 1
appendLine("cleanup_path '$path' '$desc' $current \$TOTAL")
}
appendLine()
appendLine("echo \"$(get_current_time): 工具残留清理完成\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
/** /**
* 生成post-fs-data.sh脚本内容 * 生成post-fs-data.sh脚本内容
*/ */
fun generatePostFsDataScript( private fun generatePostFsDataScript(config: SuSFSManager.ModuleConfig): String {
targetPath: String,
unameValue: String,
buildTimeValue: String,
executeInPostFsData: Boolean = false
): String {
return buildString { return buildString {
appendLine("#!/system/bin/sh") appendLine("#!/system/bin/sh")
appendLine("# SuSFS Post-FS-Data Script") appendLine("# SuSFS Post-FS-Data Script")
@@ -285,31 +371,40 @@ object ScriptGenerator {
appendLine() appendLine()
appendLine(generateLogSetup("susfs_post_fs_data.log")) appendLine(generateLogSetup("susfs_post_fs_data.log"))
appendLine() appendLine()
appendLine(generateBinaryCheck(targetPath)) appendLine(generateBinaryCheck(config.targetPath))
appendLine() appendLine()
appendLine("echo \"$(get_current_time): Post-FS-Data脚本开始执行\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Post-FS-Data脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine() appendLine()
// 设置uname和构建时间 - 只有在选择在post-fs-data中执行时才执行 // 设置uname和构建时间 - 只有在选择在post-fs-data中执行时才执行
if (executeInPostFsData && (unameValue != DEFAULT_UNAME || buildTimeValue != DEFAULT_BUILD_TIME)) { if (config.executeInPostFsData && (config.unameValue != DEFAULT_UNAME || config.buildTimeValue != DEFAULT_BUILD_TIME)) {
appendLine("# 设置uname和构建时间") appendLine("# 设置uname和构建时间")
appendLine("\"${'$'}SUSFS_BIN\" set_uname '$unameValue' '$buildTimeValue'") appendLine("\"${'$'}SUSFS_BIN\" set_uname '${config.unameValue}' '${config.buildTimeValue}'")
appendLine("echo \"$(get_current_time): 设置uname为: $unameValue, 构建时间为: $buildTimeValue\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): 设置uname为: ${config.unameValue}, 构建时间为: ${config.buildTimeValue}\" >> \"${'$'}LOG_FILE\"")
appendLine() appendLine()
} }
generateUmountZygoteIsoServiceSection(config.umountForZygoteIsoService, config.support158)
appendLine("echo \"$(get_current_time): Post-FS-Data脚本执行完成\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Post-FS-Data脚本执行完成\" >> \"${'$'}LOG_FILE\"")
} }
} }
// 添加新的生成方法
private fun StringBuilder.generateUmountZygoteIsoServiceSection(umountForZygoteIsoService: Boolean, support158: Boolean) {
if (support158) {
appendLine("# 设置Zygote隔离服务卸载状态")
val umountValue = if (umountForZygoteIsoService) 1 else 0
appendLine("\"${'$'}SUSFS_BIN\" umount_for_zygote_iso_service $umountValue")
appendLine("echo \"$(get_current_time): Zygote隔离服务卸载设置为: ${if (umountForZygoteIsoService) "启用" else "禁用"}\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
}
/** /**
* 生成post-mount.sh脚本内容 * 生成post-mount.sh脚本内容
*/ */
fun generatePostMountScript( private fun generatePostMountScript(config: SuSFSManager.ModuleConfig): String {
targetPath: String,
susMounts: Set<String>,
tryUmounts: Set<String>
): String {
return buildString { return buildString {
appendLine("#!/system/bin/sh") appendLine("#!/system/bin/sh")
appendLine("# SuSFS Post-Mount Script") appendLine("# SuSFS Post-Mount Script")
@@ -319,13 +414,13 @@ object ScriptGenerator {
appendLine() appendLine()
appendLine("echo \"$(get_current_time): Post-Mount脚本开始执行\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Post-Mount脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine() appendLine()
appendLine(generateBinaryCheck(targetPath)) appendLine(generateBinaryCheck(config.targetPath))
appendLine() appendLine()
// 添加SUS挂载 // 添加SUS挂载
if (susMounts.isNotEmpty()) { if (config.susMounts.isNotEmpty()) {
appendLine("# 添加SUS挂载") appendLine("# 添加SUS挂载")
susMounts.forEach { mount -> config.susMounts.forEach { mount ->
appendLine("\"${'$'}SUSFS_BIN\" add_sus_mount '$mount'") appendLine("\"${'$'}SUSFS_BIN\" add_sus_mount '$mount'")
appendLine("echo \"$(get_current_time): 添加SUS挂载: $mount\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): 添加SUS挂载: $mount\" >> \"${'$'}LOG_FILE\"")
} }
@@ -333,9 +428,9 @@ object ScriptGenerator {
} }
// 添加尝试卸载 // 添加尝试卸载
if (tryUmounts.isNotEmpty()) { if (config.tryUmounts.isNotEmpty()) {
appendLine("# 添加尝试卸载") appendLine("# 添加尝试卸载")
tryUmounts.forEach { umount -> config.tryUmounts.forEach { umount ->
val parts = umount.split("|") val parts = umount.split("|")
if (parts.size == 2) { if (parts.size == 2) {
val path = parts[0] val path = parts[0]
@@ -354,10 +449,8 @@ object ScriptGenerator {
/** /**
* 生成boot-completed.sh脚本内容 * 生成boot-completed.sh脚本内容
*/ */
fun generateBootCompletedScript( @SuppressLint("SdCardPath")
targetPath: String, private fun generateBootCompletedScript(config: SuSFSManager.ModuleConfig): String {
hideSusMountsForAllProcs: Boolean = true
): String {
return buildString { return buildString {
appendLine("#!/system/bin/sh") appendLine("#!/system/bin/sh")
appendLine("# SuSFS Boot-Completed Script") appendLine("# SuSFS Boot-Completed Script")
@@ -367,36 +460,61 @@ object ScriptGenerator {
appendLine() appendLine()
appendLine("echo \"$(get_current_time): Boot-Completed脚本开始执行\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Boot-Completed脚本开始执行\" >> \"${'$'}LOG_FILE\"")
appendLine() appendLine()
appendLine(generateBinaryCheck(targetPath)) appendLine(generateBinaryCheck(config.targetPath))
appendLine() appendLine()
// SUS挂载隐藏控制仅限1.5.8及以上版本 // 仅在支持隐藏挂载功能时执行相关配置
appendLine("# 设置SUS挂载隐藏控制仅限1.5.8及以上版本)") if (config.support158) {
appendLine("SUSFS_VERSION=$(${'$'}SUSFS_BIN show version 2>/dev/null | grep -o 'v[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+' | head -1)") // SUS挂载隐藏控制
appendLine("if [ -n \"${'$'}SUSFS_VERSION\" ]; then") val hideValue = if (config.hideSusMountsForAllProcs) 1 else 0
appendLine(" VERSION_NUM=$(echo \"${'$'}SUSFS_VERSION\" | sed 's/v//' | awk -F. '{printf \"%d%02d%02d\", $1, $2, $3}')") appendLine("# 设置SUS挂载隐藏控制")
appendLine(" if [ \"${'$'}VERSION_NUM\" -ge 10508 ]; then") appendLine("\"${'$'}SUSFS_BIN\" hide_sus_mnts_for_all_procs $hideValue")
val hideValue = if (hideSusMountsForAllProcs) 1 else 0 appendLine("echo \"$(get_current_time): SUS挂载隐藏控制设置为: ${if (config.hideSusMountsForAllProcs) "对所有进程隐藏" else "仅对非KSU进程隐藏"}\" >> \"${'$'}LOG_FILE\"")
appendLine(" \"${'$'}SUSFS_BIN\" hide_sus_mnts_for_all_procs $hideValue")
appendLine(" echo \"$(get_current_time): SUS挂载隐藏控制设置为: ${if (hideSusMountsForAllProcs) "对所有进程隐藏" else "仅对非KSU进程隐藏"}\" >> \"${'$'}LOG_FILE\"")
appendLine(" else")
appendLine(" echo \"$(get_current_time): 当前版本 ${'$'}SUSFS_VERSION 不支持SUS挂载隐藏控制功能需要1.5.8及以上版本\" >> \"${'$'}LOG_FILE\"")
appendLine(" fi")
appendLine("else")
appendLine(" echo \"$(get_current_time): 无法获取SuSFS版本信息跳过SUS挂载隐藏控制设置\" >> \"${'$'}LOG_FILE\"")
appendLine("fi")
appendLine() appendLine()
// 路径设置和SUS路径设置
if (config.susPaths.isNotEmpty() || config.susLoopPaths.isNotEmpty()) {
generatePathSettingSection(config.androidDataPath, config.sdcardPath)
appendLine()
// 添加普通SUS路径
if (config.susPaths.isNotEmpty()) {
generateSusPathsSection(config.susPaths)
}
// 添加循环SUS路径
if (config.susLoopPaths.isNotEmpty()) {
generateSusLoopPathsSection(config.susLoopPaths)
}
}
}
appendLine("echo \"$(get_current_time): Boot-Completed脚本执行完成\" >> \"${'$'}LOG_FILE\"") appendLine("echo \"$(get_current_time): Boot-Completed脚本执行完成\" >> \"${'$'}LOG_FILE\"")
} }
} }
@SuppressLint("SdCardPath")
private fun StringBuilder.generatePathSettingSection(androidDataPath: String, sdcardPath: String) {
appendLine("# 路径配置")
appendLine("# 设置Android Data路径")
appendLine("until [ -d \"/sdcard/Android\" ]; do sleep 1; done")
appendLine("sleep 60")
appendLine()
appendLine("\"${'$'}SUSFS_BIN\" set_android_data_root_path '$androidDataPath'")
appendLine("echo \"$(get_current_time): Android Data路径设置为: $androidDataPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
appendLine("# 设置SD卡路径")
appendLine("\"${'$'}SUSFS_BIN\" set_sdcard_root_path '$sdcardPath'")
appendLine("echo \"$(get_current_time): SD卡路径设置为: $sdcardPath\" >> \"${'$'}LOG_FILE\"")
appendLine()
}
/** /**
* 生成module.prop文件内容 * 生成module.prop文件内容
*/ */
fun generateModuleProp(moduleId: String): String { fun generateModuleProp(moduleId: String): String {
val moduleVersion = "v1.0.0" val moduleVersion = "v1.0.2"
val moduleVersionCode = "1000" val moduleVersionCode = "1002"
return """ return """
id=$moduleId id=$moduleId

View File

@@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.dergoogler.mmrl.platform.Platform.Companion.context import com.dergoogler.mmrl.platform.Platform.Companion.context
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.sukisu.ultra.KernelVersion import com.sukisu.ultra.KernelVersion
import com.sukisu.ultra.Natives import com.sukisu.ultra.Natives
import com.sukisu.ultra.getKernelVersion import com.sukisu.ultra.getKernelVersion
@@ -31,12 +32,15 @@ class HomeViewModel : ViewModel() {
private const val KEY_SYSTEM_INFO = "system_info" private const val KEY_SYSTEM_INFO = "system_info"
private const val KEY_VERSION_INFO = "version_info" private const val KEY_VERSION_INFO = "version_info"
private const val KEY_LAST_UPDATE = "last_update_time" private const val KEY_LAST_UPDATE = "last_update_time"
private const val KEY_ERROR_COUNT = "error_count"
private const val MAX_ERROR_COUNT = 2
} }
// 系统状态 // 系统状态
data class SystemStatus( data class SystemStatus(
val isManager: Boolean = false, val isManager: Boolean = false,
val ksuVersion: Int? = null, val ksuVersion: Int? = null,
val ksuFullVersion : String? = null,
val lkmMode: Boolean? = null, val lkmMode: Boolean? = null,
val kernelVersion: KernelVersion = getKernelVersion(), val kernelVersion: KernelVersion = getKernelVersion(),
val isRootAvailable: Boolean = false, val isRootAvailable: Boolean = false,
@@ -59,7 +63,10 @@ class HomeViewModel : ViewModel() {
val susSUMode: String = "", val susSUMode: String = "",
val superuserCount: Int = 0, val superuserCount: Int = 0,
val moduleCount: Int = 0, val moduleCount: Int = 0,
val kpmModuleCount: Int = 0 val kpmModuleCount: Int = 0,
val managersList: Natives.ManagersList? = null,
val isDynamicSignEnabled: Boolean = false,
val zygiskImplement: String = ""
) )
private val gson = Gson() private val gson = Gson()
@@ -76,48 +83,143 @@ class HomeViewModel : ViewModel() {
var isSimpleMode by mutableStateOf(false) var isSimpleMode by mutableStateOf(false)
private set private set
var isKernelSimpleMode by mutableStateOf(false)
private set
var isHideVersion by mutableStateOf(false) var isHideVersion by mutableStateOf(false)
private set private set
var isHideOtherInfo by mutableStateOf(false) var isHideOtherInfo by mutableStateOf(false)
private set private set
var isHideSusfsStatus by mutableStateOf(false) var isHideSusfsStatus by mutableStateOf(false)
private set private set
var isHideZygiskImplement by mutableStateOf(false)
private set
var isHideLinkCard by mutableStateOf(false) var isHideLinkCard by mutableStateOf(false)
private set private set
var showKpmInfo by mutableStateOf(false) var showKpmInfo by mutableStateOf(false)
private set private set
private fun clearAllCache() {
try {
prefs.edit { clear() }
Log.i(TAG, "All cache cleared successfully")
} catch (e: Exception) {
Log.e(TAG, "Error clearing cache", e)
}
}
private fun resetToDefaults() {
systemStatus = SystemStatus()
systemInfo = SystemInfo()
latestVersionInfo = LatestVersionInfo()
isSimpleMode = false
isKernelSimpleMode = false
isHideVersion = false
isHideOtherInfo = false
isHideSusfsStatus = false
isHideZygiskImplement = false
isHideLinkCard = false
showKpmInfo = false
}
private fun handleError(error: Exception, operation: String) {
Log.e(TAG, "Error in $operation", error)
val errorCount = prefs.getInt(KEY_ERROR_COUNT, 0)
val newErrorCount = errorCount + 1
if (newErrorCount >= MAX_ERROR_COUNT) {
Log.w(TAG, "Too many errors ($newErrorCount), clearing cache and resetting")
clearAllCache()
resetToDefaults()
} else {
prefs.edit {
putInt(KEY_ERROR_COUNT, newErrorCount)
}
}
}
private fun String?.orSafe(default: String = ""): String {
return if (this.isNullOrBlank()) default else this
}
private fun <T, R> Pair<T?, R?>?.orSafe(default: Pair<T, R>): Pair<T, R> {
return if (this?.first == null || this.second == null) default else Pair(this.first!!, this.second!!)
}
fun loadUserSettings(context: Context) { fun loadUserSettings(context: Context) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) try {
isSimpleMode = prefs.getBoolean("is_simple_mode", false) val settingsPrefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
isHideVersion = prefs.getBoolean("is_hide_version", false) isSimpleMode = settingsPrefs.getBoolean("is_simple_mode", false)
isHideOtherInfo = prefs.getBoolean("is_hide_other_info", false) isKernelSimpleMode = settingsPrefs.getBoolean("is_kernel_simple_mode", false)
isHideSusfsStatus = prefs.getBoolean("is_hide_susfs_status", false) isHideVersion = settingsPrefs.getBoolean("is_hide_version", false)
isHideLinkCard = prefs.getBoolean("is_hide_link_card", false) isHideOtherInfo = settingsPrefs.getBoolean("is_hide_other_info", false)
showKpmInfo = prefs.getBoolean("show_kpm_info", false) isHideSusfsStatus = settingsPrefs.getBoolean("is_hide_susfs_status", false)
isHideLinkCard = settingsPrefs.getBoolean("is_hide_link_card", false)
isHideZygiskImplement = settingsPrefs.getBoolean("is_hide_zygisk_Implement", false)
showKpmInfo = settingsPrefs.getBoolean("show_kpm_info", false)
} catch (e: Exception) {
handleError(e, "loadUserSettings")
}
} }
} }
fun initializeData() { fun initializeData() {
viewModelScope.launch { viewModelScope.launch {
try {
loadCachedData() loadCachedData()
// 成功加载后重置错误计数
prefs.edit {
putInt(KEY_ERROR_COUNT, 0)
}
} catch(e: Exception) {
handleError(e, "initializeData")
}
} }
} }
private fun loadCachedData() { private fun loadCachedData() {
prefs.getString(KEY_SYSTEM_STATUS, null)?.let { try {
systemStatus = gson.fromJson(it, SystemStatus::class.java) prefs.getString(KEY_SYSTEM_STATUS, null)?.let { statusJson ->
try {
val cachedStatus = gson.fromJson(statusJson, SystemStatus::class.java)
if (cachedStatus != null) {
systemStatus = cachedStatus
} }
prefs.getString(KEY_SYSTEM_INFO, null)?.let { } catch (e: JsonSyntaxException) {
systemInfo = gson.fromJson(it, SystemInfo::class.java) Log.w(TAG, "Invalid system status JSON, using defaults", e)
} }
prefs.getString(KEY_VERSION_INFO, null)?.let { }
latestVersionInfo = gson.fromJson(it, LatestVersionInfo::class.java)
prefs.getString(KEY_SYSTEM_INFO, null)?.let { infoJson ->
try {
val cachedInfo = gson.fromJson(infoJson, SystemInfo::class.java)
if (cachedInfo != null) {
systemInfo = cachedInfo
}
} catch (e: JsonSyntaxException) {
Log.w(TAG, "Invalid system info JSON, using defaults", e)
}
}
prefs.getString(KEY_VERSION_INFO, null)?.let { versionJson ->
try {
val cachedVersion = gson.fromJson(versionJson, LatestVersionInfo::class.java)
if (cachedVersion != null) {
latestVersionInfo = cachedVersion
}
} catch (e: JsonSyntaxException) {
Log.w(TAG, "Invalid version info JSON, using defaults", e)
}
}
} catch (e: Exception) {
Log.e(TAG, "Error loading cached data", e)
throw e
} }
} }
private suspend fun fetchAndSaveData() { private suspend fun fetchAndSaveData() {
try {
fetchSystemStatus() fetchSystemStatus()
fetchSystemInfo() fetchSystemInfo()
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@@ -126,15 +228,19 @@ class HomeViewModel : ViewModel() {
putString(KEY_SYSTEM_INFO, gson.toJson(systemInfo)) putString(KEY_SYSTEM_INFO, gson.toJson(systemInfo))
putString(KEY_VERSION_INFO, gson.toJson(latestVersionInfo)) putString(KEY_VERSION_INFO, gson.toJson(latestVersionInfo))
putLong(KEY_LAST_UPDATE, System.currentTimeMillis()) putLong(KEY_LAST_UPDATE, System.currentTimeMillis())
putInt(KEY_ERROR_COUNT, 0)
} }
} }
} catch (e: Exception) {
handleError(e, "fetchAndSaveData")
}
} }
fun checkForUpdates(context: Context) { fun checkForUpdates(context: Context) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val checkUpdate = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val settingsPrefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("check_update", true) val checkUpdate = settingsPrefs.getBoolean("check_update", true)
if (checkUpdate) { if (checkUpdate) {
val newVersionInfo = checkNewVersion() val newVersionInfo = checkNewVersion()
@@ -145,7 +251,7 @@ class HomeViewModel : ViewModel() {
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error checking for updates", e) handleError(e, "checkForUpdates")
} }
} }
} }
@@ -156,7 +262,7 @@ class HomeViewModel : ViewModel() {
fetchAndSaveData() fetchAndSaveData()
checkForUpdates(context) checkForUpdates(context)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error refreshing data", e) handleError(e, "refreshAllData")
} }
} }
} }
@@ -165,23 +271,97 @@ class HomeViewModel : ViewModel() {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
try { try {
val kernelVersion = getKernelVersion() val kernelVersion = getKernelVersion()
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = try {
val ksuVersion = if (isManager) Natives.version else null Natives.becomeManager(ksuApp.packageName.orSafe("com.sukisu.ultra"))
} catch (e: Exception) {
Log.w(TAG, "Failed to become manager", e)
false
}
val ksuVersion = if (isManager) {
try {
Natives.version
} catch (e: Exception) {
Log.w(TAG, "Failed to get KSU version", e)
null
}
} else null
val fullVersion = try {
Natives.getFullVersion().orSafe("Unknown")
} catch (e: Exception) {
Log.w(TAG, "Failed to get full version", e)
"Unknown"
}
val ksuFullVersion = if (isKernelSimpleMode) {
try {
val startIndex = fullVersion.indexOf('v')
if (startIndex >= 0) {
val endIndex = fullVersion.indexOf('-', startIndex)
val versionStr = if (endIndex > startIndex) {
fullVersion.substring(startIndex, endIndex)
} else {
fullVersion.substring(startIndex)
}
val numericVersion = "v" + (Regex("""\d+(\.\d+)*""").find(versionStr)?.value ?: versionStr)
numericVersion
} else {
fullVersion
}
} catch (e: Exception) {
Log.w(TAG, "Failed to process full version", e)
fullVersion
}
} else {
fullVersion
}
val lkmMode = ksuVersion?.let { val lkmMode = ksuVersion?.let {
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null try {
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) {
Natives.isLkmMode
} else null
} catch (e: Exception) {
Log.w(TAG, "Failed to get LKM mode", e)
null
}
}
val isRootAvailable = try {
rootAvailable()
} catch (e: Exception) {
Log.w(TAG, "Failed to check root availability", e)
false
}
val isKpmConfigured = try {
Natives.isKPMEnabled()
} catch (e: Exception) {
Log.w(TAG, "Failed to check KPM status", e)
false
}
val requireNewKernel = try {
isManager && Natives.requireNewKernel()
} catch (e: Exception) {
Log.w(TAG, "Failed to check kernel requirement", e)
false
} }
systemStatus = SystemStatus( systemStatus = SystemStatus(
isManager = isManager, isManager = isManager,
ksuVersion = ksuVersion, ksuVersion = ksuVersion,
ksuFullVersion = ksuFullVersion,
lkmMode = lkmMode, lkmMode = lkmMode,
kernelVersion = kernelVersion, kernelVersion = kernelVersion,
isRootAvailable = rootAvailable(), isRootAvailable = isRootAvailable,
isKpmConfigured = Natives.isKPMEnabled(), isKpmConfigured = isKpmConfigured,
requireNewKernel = isManager && Natives.requireNewKernel() requireNewKernel = requireNewKernel
) )
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error fetching system status", e) Log.e(TAG, "Error fetching system status", e)
throw e
} }
} }
} }
@@ -190,60 +370,188 @@ class HomeViewModel : ViewModel() {
private suspend fun fetchSystemInfo() { private suspend fun fetchSystemInfo() {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
try { try {
val uname = Os.uname() val uname = try {
val kpmVersion = getKpmVersion() Os.uname()
val suSFS = getSuSFS() } catch (e: Exception) {
Log.w(TAG, "Failed to get uname", e)
null
}
val kpmVersion = try {
getKpmVersion().orSafe("Unknown")
} catch (e: Exception) {
Log.w(TAG, "Failed to get kpm version", e)
"Unknown"
}
val suSFS = try {
getSuSFS().orSafe("Unknown")
} catch (e: Exception) {
Log.w(TAG, "Failed to get SuSFS", e)
"Unknown"
}
var suSFSVersion = "" var suSFSVersion = ""
var suSFSVariant = "" var suSFSVariant = ""
var suSFSFeatures = "" var suSFSFeatures = ""
var susSUMode = "" var susSUMode = ""
if (suSFS == "Supported") { if (suSFS == "Supported") {
suSFSVersion = getSuSFSVersion() suSFSVersion = try {
getSuSFSVersion().orSafe("")
} catch (e: Exception) {
Log.w(TAG, "Failed to get SuSFS version", e)
""
}
if (suSFSVersion.isNotEmpty()) { if (suSFSVersion.isNotEmpty()) {
suSFSVariant = getSuSFSVariant() suSFSVariant = try {
suSFSFeatures = getSuSFSFeatures() getSuSFSVariant().orSafe("")
} catch (e: Exception) {
Log.w(TAG, "Failed to get SuSFS variant", e)
""
}
suSFSFeatures = try {
getSuSFSFeatures().orSafe("")
} catch (e: Exception) {
Log.w(TAG, "Failed to get SuSFS features", e)
""
}
val isSUS_SU = suSFSFeatures == "CONFIG_KSU_SUSFS_SUS_SU" val isSUS_SU = suSFSFeatures == "CONFIG_KSU_SUSFS_SUS_SU"
if (isSUS_SU) { if (isSUS_SU) {
susSUMode = try { susSUMode = try {
susfsSUS_SU_Mode().toString() susfsSUS_SU_Mode()
} catch (_: Exception) { } catch (e: Exception) {
Log.w(TAG, "Failed to get SUS SU mode", e)
"" ""
} }
} }
} }
} }
// 获取动态签名状态和管理器列表
val dynamicSignConfig = try {
Natives.getDynamicSign()
} catch (e: Exception) {
Log.w(TAG, "Failed to get dynamic sign config", e)
null
}
val isDynamicSignEnabled = try {
dynamicSignConfig?.isValid() == true
} catch (e: Exception) {
Log.w(TAG, "Failed to check dynamic sign validity", e)
false
}
val managersList = if (isDynamicSignEnabled) {
try {
Natives.getManagersList()
} catch (e: Exception) {
Log.w(TAG, "Failed to get managers list", e)
null
}
} else {
null
}
val deviceModel = try {
getDeviceModel().orSafe("Unknown")
} catch (e: Exception) {
Log.w(TAG, "Failed to get device model", e)
"Unknown"
}
val managerVersion = try {
getManagerVersion(ksuApp.applicationContext).orSafe(Pair("Unknown", 0L))
} catch (e: Exception) {
Log.w(TAG, "Failed to get manager version", e)
Pair("Unknown", 0L)
}
val seLinuxStatus = try {
getSELinuxStatus(context).orSafe("Unknown")
} catch (e: Exception) {
Log.w(TAG, "Failed to get SELinux status", e)
"Unknown"
}
val superuserCount = try {
getSuperuserCount()
} catch (e: Exception) {
Log.w(TAG, "Failed to get superuser count", e)
0
}
val moduleCount = try {
getModuleCount()
} catch (e: Exception) {
Log.w(TAG, "Failed to get module count", e)
0
}
val kpmModuleCount = try {
getKpmModuleCount()
} catch (e: Exception) {
Log.w(TAG, "Failed to get kpm module count", e)
0
}
val zygiskImplement = try {
getZygiskImplement().orSafe("None")
} catch (e: Exception) {
Log.w(TAG, "Failed to get Zygisk implement", e)
"None"
}
systemInfo = SystemInfo( systemInfo = SystemInfo(
kernelRelease = uname.release, kernelRelease = uname?.release.orSafe("Unknown"),
androidVersion = Build.VERSION.RELEASE, androidVersion = Build.VERSION.RELEASE.orSafe("Unknown"),
deviceModel = getDeviceModel(), deviceModel = deviceModel,
managerVersion = getManagerVersion(ksuApp.applicationContext), managerVersion = managerVersion,
seLinuxStatus = getSELinuxStatus(context), seLinuxStatus = seLinuxStatus,
kpmVersion = kpmVersion, kpmVersion = kpmVersion,
suSFSStatus = suSFS, suSFSStatus = suSFS,
suSFSVersion = suSFSVersion, suSFSVersion = suSFSVersion,
suSFSVariant = suSFSVariant, suSFSVariant = suSFSVariant,
suSFSFeatures = suSFSFeatures, suSFSFeatures = suSFSFeatures,
susSUMode = susSUMode, susSUMode = susSUMode,
superuserCount = getSuperuserCount(), superuserCount = superuserCount,
moduleCount = getModuleCount(), moduleCount = moduleCount,
kpmModuleCount = getKpmModuleCount() kpmModuleCount = kpmModuleCount,
managersList = managersList,
isDynamicSignEnabled = isDynamicSignEnabled,
zygiskImplement = zygiskImplement
) )
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error fetching system info", e) Log.e(TAG, "Error fetching system info", e)
throw e
} }
} }
} }
private fun getDeviceInfo(): String { private fun getDeviceInfo(): String {
var manufacturer = return try {
Build.MANUFACTURER[0].uppercaseChar().toString() + Build.MANUFACTURER.substring(1) var manufacturer = Build.MANUFACTURER.orSafe("Unknown")
if (!Build.BRAND.equals(Build.MANUFACTURER, ignoreCase = true)) { manufacturer = manufacturer[0].uppercaseChar().toString() + manufacturer.substring(1)
manufacturer += " " + Build.BRAND[0].uppercaseChar() + Build.BRAND.substring(1)
val brand = Build.BRAND.orSafe("")
if (brand.isNotEmpty() && !brand.equals(Build.MANUFACTURER, ignoreCase = true)) {
manufacturer += " " + brand[0].uppercaseChar() + brand.substring(1)
}
val model = Build.MODEL.orSafe("")
if (model.isNotEmpty()) {
manufacturer += " $model "
}
manufacturer
} catch (e: Exception) {
Log.w(TAG, "Failed to get device info", e)
"Unknown Device"
} }
manufacturer += " " + Build.MODEL + " "
return manufacturer
} }
@SuppressLint("PrivateApi") @SuppressLint("PrivateApi")
@@ -259,27 +567,32 @@ class HomeViewModel : ViewModel() {
) )
var result = getDeviceInfo() var result = getDeviceInfo()
for (key in marketNameKeys) { for (key in marketNameKeys) {
try {
val marketName = getMethod.invoke(null, key, "") as String val marketName = getMethod.invoke(null, key, "") as String
if (marketName.isNotEmpty()) { if (marketName.isNotEmpty()) {
result = marketName result = marketName
break break
} }
} catch (e: Exception) {
Log.w(TAG, "Failed to get market name for key: $key", e)
}
} }
result result
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error getting device model", e) Log.w(TAG, "Error getting device model", e)
getDeviceInfo() getDeviceInfo()
} }
} }
private fun getManagerVersion(context: Context): Pair<String, Long> { private fun getManagerVersion(context: Context): Pair<String, Long> {
return try { return try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!! val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
val versionCode = androidx.core.content.pm.PackageInfoCompat.getLongVersionCode(packageInfo) val versionCode = androidx.core.content.pm.PackageInfoCompat.getLongVersionCode(packageInfo)
Pair(packageInfo.versionName!!, versionCode) val versionName = packageInfo.versionName.orSafe("Unknown")
Pair(versionName, versionCode)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error getting manager version", e) Log.w(TAG, "Error getting manager version", e)
Pair("", 0L) Pair("Unknown", 0L)
} }
} }
} }

View File

@@ -15,11 +15,10 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.sukisu.ultra.ui.util.HanziToPinyin import com.sukisu.ultra.ui.util.HanziToPinyin
import com.sukisu.ultra.ui.util.listModules import com.sukisu.ultra.ui.util.listModules
import com.sukisu.ultra.ui.util.getRootShell
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader
import java.text.Collator import java.text.Collator
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.Locale import java.util.Locale
@@ -405,14 +404,12 @@ class ModuleSizeCache(context: Context) {
*/ */
private fun calculateModuleFolderSize(dirId: String): Long { private fun calculateModuleFolderSize(dirId: String): Long {
return try { return try {
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "du -sb /data/adb/modules/$dirId")) val shell = getRootShell()
val reader = BufferedReader(InputStreamReader(process.inputStream)) val command = "du -sb /data/adb/modules/$dirId"
val output = reader.readLine() val result = shell.newJob().add(command).to(ArrayList(), null).exec()
process.waitFor()
reader.close()
if (output != null) { if (result.isSuccess && result.out.isNotEmpty()) {
val sizeStr = output.split("\t").firstOrNull() val sizeStr = result.out.firstOrNull()?.split("\t")?.firstOrNull()
sizeStr?.toLongOrNull() ?: 0L sizeStr?.toLongOrNull() ?: 0L
} else { } else {
0L 0L

View File

@@ -1,9 +1,13 @@
package com.sukisu.ultra.ui.viewmodel package com.sukisu.ultra.ui.viewmodel
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.os.IBinder
import android.os.Parcelable import android.os.Parcelable
import android.os.SystemClock import android.os.SystemClock
import android.util.Log import android.util.Log
@@ -29,13 +33,13 @@ import java.util.*
import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.LinkedBlockingQueue
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
import com.sukisu.ultra.ui.webui.getInstalledPackagesAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeoutOrNull
import androidx.core.content.edit import androidx.core.content.edit
import com.sukisu.ultra.ui.KsuService
import com.sukisu.ultra.ui.util.KsuCli
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
// 应用分类 // 应用分类
enum class AppCategory(val displayNameRes: Int, val persistKey: String) { enum class AppCategory(val displayNameRes: Int, val persistKey: String) {
@@ -73,8 +77,6 @@ enum class SortType(val displayNameRes: Int, val persistKey: String) {
* @date 2025/5/31. * @date 2025/5/31.
*/ */
class SuperUserViewModel : ViewModel() { class SuperUserViewModel : ViewModel() {
val isPlatformAlive get() = Platform.isAlive
companion object { companion object {
private const val TAG = "SuperUserViewModel" private const val TAG = "SuperUserViewModel"
var apps by mutableStateOf<List<AppInfo>>(emptyList()) var apps by mutableStateOf<List<AppInfo>>(emptyList())
@@ -392,83 +394,99 @@ class SuperUserViewModel : ViewModel() {
} }
} }
private var serviceConnection: ServiceConnection? = null
private suspend fun connectKsuService(
onDisconnect: () -> Unit = {}
): IBinder? = suspendCoroutine { continuation ->
val connection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
onDisconnect()
serviceConnection = null
}
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
continuation.resume(binder)
}
}
serviceConnection = connection
val intent = Intent(ksuApp, KsuService::class.java)
try {
val task = com.topjohnwu.superuser.ipc.RootService.bindOrTask(
intent,
Shell.EXECUTOR,
connection
)
val shell = KsuCli.SHELL
task?.let { shell.execTask(it) }
} catch (e: Exception) {
Log.e(TAG, "Failed to bind KsuService", e)
continuation.resume(null)
}
}
private fun stopKsuService() {
serviceConnection?.let { connection ->
try {
val intent = Intent(ksuApp, KsuService::class.java)
com.topjohnwu.superuser.ipc.RootService.stop(intent)
serviceConnection = null
} catch (e: Exception) {
Log.e(TAG, "Failed to stop KsuService", e)
}
}
}
suspend fun fetchAppList() { suspend fun fetchAppList() {
isRefreshing = true isRefreshing = true
loadingProgress = 0f loadingProgress = 0f
withContext(Dispatchers.IO) { val result = connectKsuService {
withTimeoutOrNull(TIMEOUT_MILLIS) { Log.w(TAG, "KsuService disconnected")
while (!isPlatformAlive) {
delay(500)
} }
} ?: return@withContext // Exit early if timeout
if (result == null) {
Log.e(TAG, "Failed to connect to KsuService")
isRefreshing = false
return
}
withContext(Dispatchers.IO) {
val pm = ksuApp.packageManager val pm = ksuApp.packageManager
val start = SystemClock.elapsedRealtime() val start = SystemClock.elapsedRealtime()
try { try {
val packages = Platform.getInstalledPackagesAll { val service = KsuService.Stub.asInterface(result)
Log.e(TAG, "getInstalledPackagesAll:", it) val allPackages = service?.getPackages(0)
}
withContext(Dispatchers.Main) {
stopKsuService()
}
loadingProgress = 0.3f loadingProgress = 0.3f
val filteredPackages = packages.filter { it.packageName != ksuApp.packageName } val packages = allPackages?.list ?: emptyList()
withContext(appProcessingThreadPool) { apps = packages.map { packageInfo ->
supervisorScope {
val batches = filteredPackages.chunked(BATCH_SIZE)
val processedApps = batches.mapIndexed { batchIndex, batch ->
async {
val batchResult = batch.mapNotNull { packageInfo ->
try {
val appInfo = packageInfo.applicationInfo!! val appInfo = packageInfo.applicationInfo!!
val uid = appInfo.uid val uid = appInfo.uid
val profile = Natives.getAppProfile(packageInfo.packageName, uid)
val labelDeferred = async {
appInfo.loadLabel(pm).toString()
}
val profileDeferred = async {
Natives.getAppProfile(packageInfo.packageName, uid)
}
val label = labelDeferred.await()
val profile = profileDeferred.await()
AppInfo( AppInfo(
label = label, label = appInfo.loadLabel(pm).toString(),
packageInfo = packageInfo, packageInfo = packageInfo,
profile = profile, profile = profile,
) )
} catch (e: Exception) { }.filter { it.packageName != ksuApp.packageName }
Log.e(
TAG,
"Error processing app ${packageInfo.packageName}",
e
)
null
}
}
val progress = 0.3f + (batchIndex + 1).toFloat() / batches.size * 0.6f
loadingProgress = progress
batchResult
}
}.awaitAll().flatten()
appListMutex.withLock {
apps = processedApps
}
loadingProgress = 1f loadingProgress = 1f
val elapsed = SystemClock.elapsedRealtime() - start Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}")
Log.i(TAG, "Loaded ${processedApps.size} apps in ${elapsed}ms using concurrent processing")
}
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error fetching app list", e) Log.e(TAG, "Error fetching app list", e)
withContext(Dispatchers.Main) {
stopKsuService()
}
} finally { } finally {
isRefreshing = false isRefreshing = false
loadingProgress = 0f loadingProgress = 0f
@@ -482,6 +500,7 @@ class SuperUserViewModel : ViewModel() {
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
try { try {
stopKsuService()
appProcessingThreadPool.close() appProcessingThreadPool.close()
configChangeListeners.clear() configChangeListeners.clear()
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -41,10 +41,10 @@ class WebUIActivity : ComponentActivity() {
val name = intent.getStringExtra("name")!! val name = intent.getStringExtra("name")!!
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name")) setTaskDescription(ActivityManager.TaskDescription("SukiSU-Ultra - $name"))
} else { } else {
val taskDescription = val taskDescription =
ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build() ActivityManager.TaskDescription.Builder().setLabel("SukiSU-Ultra - $name").build()
setTaskDescription(taskDescription) setTaskDescription(taskDescription)
} }

View File

@@ -42,7 +42,7 @@ class WebUIXActivity : ComponentActivity() {
val osVersion = Build.VERSION.RELEASE val osVersion = Build.VERSION.RELEASE
val deviceModel = Build.MODEL val deviceModel = Build.MODEL
return "SukiSU /$ksuVersion (Linux; Android $osVersion; $deviceModel; $platform/$platformVersion)" return "SukiSU-Ultra /$ksuVersion (Linux; Android $osVersion; $deviceModel; $platform/$platformVersion)"
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -59,10 +59,10 @@ class WebUIXActivity : ComponentActivity() {
val name = intent.getStringExtra("name")!! val name = intent.getStringExtra("name")!!
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name")) setTaskDescription(ActivityManager.TaskDescription("SukiSU-Ultra - $name"))
} else { } else {
val taskDescription = val taskDescription =
ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build() ActivityManager.TaskDescription.Builder().setLabel("SukiSU-Ultra - $name").build()
setTaskDescription(taskDescription) setTaskDescription(taskDescription)
} }

View File

@@ -73,11 +73,13 @@ import kotlin.math.roundToInt
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.NavigateNext import androidx.compose.material.icons.automirrored.filled.NavigateNext
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
@@ -86,6 +88,7 @@ import com.sukisu.ultra.ui.theme.getCardElevation
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.ksuApp import com.sukisu.ultra.ksuApp
@@ -145,6 +148,13 @@ fun MoreSettingsScreen(
var showDpiConfirmDialog by remember { mutableStateOf(false) } var showDpiConfirmDialog by remember { mutableStateOf(false) }
var showImageEditor by remember { mutableStateOf(false) } var showImageEditor by remember { mutableStateOf(false) }
// 动态签名配置状态
var dynamicSignConfig by remember { mutableStateOf<Natives.DynamicSignConfig?>(null) }
var isDynamicSignEnabled by remember { mutableStateOf(false) }
var dynamicSignSize by remember { mutableStateOf("") }
var dynamicSignHash by remember { mutableStateOf("") }
var showDynamicSignDialog by remember { mutableStateOf(false) }
// 主题模式选项 // 主题模式选项
val themeOptions = listOf( val themeOptions = listOf(
stringResource(R.string.theme_follow_system), stringResource(R.string.theme_follow_system),
@@ -222,6 +232,11 @@ fun MoreSettingsScreen(
mutableStateOf(prefs.getBoolean("show_kpm_info", false)) mutableStateOf(prefs.getBoolean("show_kpm_info", false))
} }
// 隐藏 Zygisk 状态开关状态
var isHideZygiskImplement by remember {
mutableStateOf(prefs.getBoolean("is_hide_zygisk_Implement", false))
}
// 隐藏SuSFS状态开关状态 // 隐藏SuSFS状态开关状态
var isHideSusfsStatus by remember { var isHideSusfsStatus by remember {
mutableStateOf(prefs.getBoolean("is_hide_susfs_status", false)) mutableStateOf(prefs.getBoolean("is_hide_susfs_status", false))
@@ -237,6 +252,11 @@ fun MoreSettingsScreen(
mutableStateOf(prefs.getBoolean("is_hide_tag_row", false)) mutableStateOf(prefs.getBoolean("is_hide_tag_row", false))
} }
// 内核版本简洁模式开关状态
var isKernelSimpleMode by remember {
mutableStateOf(prefs.getBoolean("is_kernel_simple_mode", false))
}
// 显示更多模块信息开关状态 // 显示更多模块信息开关状态
var showMoreModuleInfo by remember { var showMoreModuleInfo by remember {
mutableStateOf(prefs.getBoolean("show_more_module_info", false)) mutableStateOf(prefs.getBoolean("show_more_module_info", false))
@@ -294,6 +314,12 @@ fun MoreSettingsScreen(
isSimpleMode = newValue isSimpleMode = newValue
} }
// 内核版本简洁模式开关状态
val onKernelSimpleModeChange = { newValue: Boolean ->
prefs.edit { putBoolean("is_kernel_simple_mode", newValue) }
isKernelSimpleMode = newValue
}
// 隐藏内核版本号开关状态 // 隐藏内核版本号开关状态
val onHideVersionChange = { newValue: Boolean -> val onHideVersionChange = { newValue: Boolean ->
prefs.edit { putBoolean("is_hide_version", newValue) } prefs.edit { putBoolean("is_hide_version", newValue) }
@@ -318,6 +344,12 @@ fun MoreSettingsScreen(
isHideSusfsStatus = newValue isHideSusfsStatus = newValue
} }
val onHideZygiskImplement = { newValue: Boolean ->
prefs.edit { putBoolean("is_hide_zygisk_Implement", newValue) }
isHideZygiskImplement = newValue
}
// 隐藏链接状态开关状态 // 隐藏链接状态开关状态
val onHideLinkCardChange = { newValue: Boolean -> val onHideLinkCardChange = { newValue: Boolean ->
prefs.edit { putBoolean("is_hide_link_card", newValue) } prefs.edit { putBoolean("is_hide_link_card", newValue) }
@@ -641,6 +673,167 @@ fun MoreSettingsScreen(
) )
} }
LaunchedEffect(Unit) {
// 初始化动态签名配置
dynamicSignConfig = Natives.getDynamicSign()
dynamicSignConfig?.let { config ->
if (config.isValid()) {
isDynamicSignEnabled = true
dynamicSignSize = config.size.toString()
dynamicSignHash = config.hash
}
}
}
fun parseDynamicSignSize(input: String): Int? {
return try {
when {
input.startsWith("0x", true) -> input.substring(2).toInt(16)
else -> input.toInt()
}
} catch (_: NumberFormatException) {
null
}
}
// 动态签名配置对话框
if (showDynamicSignDialog) {
AlertDialog(
onDismissRequest = { showDynamicSignDialog = false },
title = { Text(stringResource(R.string.dynamic_sign_title)) },
text = {
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
) {
// 启用开关
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { isDynamicSignEnabled = !isDynamicSignEnabled }
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Switch(
checked = isDynamicSignEnabled,
onCheckedChange = { isDynamicSignEnabled = it }
)
Spacer(modifier = Modifier.width(12.dp))
Text(stringResource(R.string.enable_dynamic_sign))
}
Spacer(modifier = Modifier.height(16.dp))
// 签名大小输入
OutlinedTextField(
value = dynamicSignSize,
onValueChange = { input ->
val isValid = when {
input.isEmpty() -> true
input.matches(Regex("^\\d+$")) -> true
input.matches(Regex("^0[xX][0-9a-fA-F]*$")) -> true
else -> false
}
if (isValid) {
dynamicSignSize = input
}
},
label = { Text(stringResource(R.string.signature_size)) },
enabled = isDynamicSignEnabled,
modifier = Modifier.fillMaxWidth(),
singleLine = true,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text
)
)
Spacer(modifier = Modifier.height(12.dp))
// 签名哈希输入
OutlinedTextField(
value = dynamicSignHash,
onValueChange = { hash ->
if (hash.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) {
dynamicSignHash = hash
}
},
label = { Text(stringResource(R.string.signature_hash)) },
enabled = isDynamicSignEnabled,
modifier = Modifier.fillMaxWidth(),
singleLine = true,
supportingText = {
Text(stringResource(R.string.hash_must_be_64_chars))
},
isError = isDynamicSignEnabled && dynamicSignHash.isNotEmpty() && dynamicSignHash.length != 64
)
}
},
confirmButton = {
Button(
onClick = {
if (isDynamicSignEnabled) {
val size = parseDynamicSignSize(dynamicSignSize)
if (size != null && size > 0 && dynamicSignHash.length == 64) {
val success = Natives.setDynamicSign(size, dynamicSignHash)
if (success) {
dynamicSignConfig = Natives.DynamicSignConfig(size, dynamicSignHash)
Toast.makeText(
context,
context.getString(R.string.dynamic_sign_set_success),
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
context,
context.getString(R.string.dynamic_sign_set_failed),
Toast.LENGTH_SHORT
).show()
}
} else {
Toast.makeText(
context,
context.getString(R.string.invalid_sign_config),
Toast.LENGTH_SHORT
).show()
return@Button
}
} else {
val success = Natives.clearDynamicSign()
if (success) {
dynamicSignConfig = null
dynamicSignSize = ""
dynamicSignHash = ""
Toast.makeText(
context,
context.getString(R.string.dynamic_sign_disabled_success),
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
context,
context.getString(R.string.dynamic_sign_clear_failed),
Toast.LENGTH_SHORT
).show()
return@Button
}
}
showDynamicSignDialog = false
},
enabled = if (isDynamicSignEnabled) {
parseDynamicSignSize(dynamicSignSize)?.let { it > 0 } == true &&
dynamicSignHash.length == 64
} else true
) {
Text(stringResource(R.string.confirm))
}
},
dismissButton = {
TextButton(onClick = { showDynamicSignDialog = false }) {
Text(stringResource(R.string.cancel))
}
}
)
}
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
@@ -1064,6 +1257,14 @@ fun MoreSettingsScreen(
onChange = onSimpleModeChange onChange = onSimpleModeChange
) )
SwitchSettingItem(
icon = Icons.Filled.Brush,
title = stringResource(R.string.kernel_simple_kernel),
summary = stringResource(R.string.kernel_simple_kernel_summary),
checked = isKernelSimpleMode,
onChange = onKernelSimpleModeChange
)
// 隐藏内核部分版本号 // 隐藏内核部分版本号
SwitchSettingItem( SwitchSettingItem(
icon = Icons.Filled.VisibilityOff, icon = Icons.Filled.VisibilityOff,
@@ -1091,6 +1292,15 @@ fun MoreSettingsScreen(
onChange = onHideSusfsStatusChange onChange = onHideSusfsStatusChange
) )
// Zygsik 实现状态信息
SwitchSettingItem(
icon = Icons.Filled.VisibilityOff,
title = stringResource(R.string.hide_zygisk_implement),
summary = stringResource(R.string.hide_zygisk_implement_summary),
checked = isHideZygiskImplement,
onChange = onHideZygiskImplement
)
if (Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) { if (Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
// 隐藏KPM开关 // 隐藏KPM开关
SwitchSettingItem( SwitchSettingItem(
@@ -1207,6 +1417,22 @@ fun MoreSettingsScreen(
} }
) )
} }
// 动态签名设置
if (Natives.version >= Natives.MINIMAL_SUPPORTED_DYNAMIC_SIGN) {
SettingItem(
icon = Icons.Filled.Security,
title = stringResource(R.string.dynamic_sign_title),
subtitle = if (isDynamicSignEnabled) {
stringResource(
R.string.dynamic_sign_enabled_summary,
dynamicSignSize
)
} else {
stringResource(R.string.dynamic_sign_disabled)
},
onClick = { showDynamicSignDialog = true }
)
}
} }
} }
} }

Binary file not shown.

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">غير مثبت</string> <string name="home_not_installed">غير مثبت</string>
<string name="home_click_to_install">إضغط للتثبيت</string> <string name="home_click_to_install">إضغط للتثبيت</string>
<string name="home_working">يعمل</string> <string name="home_working">يعمل</string>
<string name="home_working_version">الإصدار: %d</string> <string name="home_working_version">الإصدار: %s</string>
<string name="home_unsupported">غير مدعوم</string> <string name="home_unsupported">غير مدعوم</string>
<string name="home_unsupported_reason">KernelSU يدعم GKI kernels فقط</string> <string name="home_unsupported_reason">KernelSU يدعم GKI kernels فقط</string>
<string name="home_kernel">إصدار النواة</string> <string name="home_kernel">إصدار النواة</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">سياق SELinux</string> <string name="profile_selinux_context">سياق SELinux</string>
<string name="profile_umount_modules">الغاء تحميل الإضافات</string> <string name="profile_umount_modules">الغاء تحميل الإضافات</string>
<string name="failed_to_update_app_profile">فشل تحديث ملف تعريف التطبيق لـ %s</string> <string name="failed_to_update_app_profile">فشل تحديث ملف تعريف التطبيق لـ %s</string>
<string name="require_kernel_version" formatted="false">إصدار KernelSU الحالي %d منخفض جدًا بحيث لا يعمل المدير بشكل صحيح. الرجاء الترقية إلى الإصدار %d أو أعلى!</string> <string name="require_kernel_version" formatted="false">إصدار KernelSU الحالي %s منخفض جدًا بحيث لا يعمل المدير بشكل صحيح. الرجاء الترقية إلى الإصدار %s أو أعلى!</string>
<string name="settings_umount_modules_default">الغاء تحميل الإضافات بشكل افتراضي</string> <string name="settings_umount_modules_default">الغاء تحميل الإضافات بشكل افتراضي</string>
<string name="settings_umount_modules_default_summary">القيمة الافتراضية العامة لـ\"إلغاء تحميل الإضافات\" في ملفات تعريف التطبيقات. إذا تم تمكينه، إزالة جميع تعديلات الإضافات على النظام للتطبيقات التي لا تحتوي على مجموعة ملف تعريف.</string> <string name="settings_umount_modules_default_summary">القيمة الافتراضية العامة لـ\"إلغاء تحميل الإضافات\" في ملفات تعريف التطبيقات. إذا تم تمكينه، إزالة جميع تعديلات الإضافات على النظام للتطبيقات التي لا تحتوي على مجموعة ملف تعريف.</string>
<string name="settings_susfs_toggle">تعطيل روابط kprobe</string> <string name="settings_susfs_toggle">تعطيل روابط kprobe</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Yüklənmədi</string> <string name="home_not_installed">Yüklənmədi</string>
<string name="home_click_to_install">Yükləmək üçün toxunun</string> <string name="home_click_to_install">Yükləmək üçün toxunun</string>
<string name="home_working">İşləyir</string> <string name="home_working">İşləyir</string>
<string name="home_working_version">Versiya: %d</string> <string name="home_working_version">Versiya: %s</string>
<string name="home_unsupported">Dəstəklənmir</string> <string name="home_unsupported">Dəstəklənmir</string>
<string name="home_unsupported_reason">Hal-hazırda KernelSU yalnız GKI nüvələrini dəstəkləyir</string> <string name="home_unsupported_reason">Hal-hazırda KernelSU yalnız GKI nüvələrini dəstəkləyir</string>
<string name="home_kernel">Nüvə</string> <string name="home_kernel">Nüvə</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux konteksi</string> <string name="profile_selinux_context">SELinux konteksi</string>
<string name="profile_umount_modules">Modulları umount et</string> <string name="profile_umount_modules">Modulları umount et</string>
<string name="failed_to_update_app_profile">%s görə tətbiq profillərini güncəlləmək mümkün olmadı</string> <string name="failed_to_update_app_profile">%s görə tətbiq profillərini güncəlləmək mümkün olmadı</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Defolt olaraq modulları umount et</string> <string name="settings_umount_modules_default">Defolt olaraq modulları umount et</string>
<string name="settings_umount_modules_default_summary">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.</string> <string name="settings_umount_modules_default_summary">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.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -28,7 +28,7 @@
<string name="selinux_status_permissive">পারমিসিভ</string> <string name="selinux_status_permissive">পারমিসিভ</string>
<string name="module_failed_to_disable">মোডিউল ডিসেবল করা যায়নি: %s</string> <string name="module_failed_to_disable">মোডিউল ডিসেবল করা যায়নি: %s</string>
<string name="module_empty">কোনো মোডিউল ইন্সটল করা নেই</string> <string name="module_empty">কোনো মোডিউল ইন্সটল করা নেই</string>
<string name="home_working_version">সংস্করণ: %d</string> <string name="home_working_version">সংস্করণ: %s</string>
<string name="profile_capabilities">ক্যাপাবিলিটিস</string> <string name="profile_capabilities">ক্যাপাবিলিটিস</string>
<string name="profile_umount_modules">আনমাউন্ট মোডিউলস</string> <string name="profile_umount_modules">আনমাউন্ট মোডিউলস</string>
<string name="reboot_recovery">রিকভারিতে বুট</string> <string name="reboot_recovery">রিকভারিতে বুট</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">ইনস্টল করা হয়নি</string> <string name="home_not_installed">ইনস্টল করা হয়নি</string>
<string name="home_click_to_install">ইনস্টল করার জন্য ক্লিক করুন</string> <string name="home_click_to_install">ইনস্টল করার জন্য ক্লিক করুন</string>
<string name="home_working"> ওয়ার্কিং</string> <string name="home_working"> ওয়ার্কিং</string>
<string name="home_working_version">ওয়ার্কিং সংস্করণ: %d</string> <string name="home_working_version">ওয়ার্কিং সংস্করণ: %s</string>
<string name="home_unsupported">অসমর্থিত</string> <string name="home_unsupported">অসমর্থিত</string>
<string name="home_unsupported_reason">KernelSU শুধুমাত্র GKI কার্নেল সমর্থন করে</string> <string name="home_unsupported_reason">KernelSU শুধুমাত্র GKI কার্নেল সমর্থন করে</string>
<string name="home_kernel">কার্নেল</string> <string name="home_kernel">কার্নেল</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nije instalirano</string> <string name="home_not_installed">Nije instalirano</string>
<string name="home_click_to_install">Kliknite da instalirate</string> <string name="home_click_to_install">Kliknite da instalirate</string>
<string name="home_working">Radi</string> <string name="home_working">Radi</string>
<string name="home_working_version">Verzija: %d</string> <string name="home_working_version">Verzija: %s</string>
<string name="home_unsupported">Nepodržano</string> <string name="home_unsupported">Nepodržano</string>
<string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string> <string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontekst</string> <string name="profile_selinux_context">SELinux kontekst</string>
<string name="profile_umount_modules">Umount module</string> <string name="profile_umount_modules">Umount module</string>
<string name="failed_to_update_app_profile">Ažuriranje Profila Aplikacije za %s nije uspjelo</string> <string name="failed_to_update_app_profile">Ažuriranje Profila Aplikacije za %s nije uspjelo</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount module po zadanom</string> <string name="settings_umount_modules_default">Umount module po zadanom</string>
<string name="settings_umount_modules_default_summary">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.</string> <string name="settings_umount_modules_default_summary">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.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Ikke installeret</string> <string name="home_not_installed">Ikke installeret</string>
<string name="home_click_to_install">Klik for at installere</string> <string name="home_click_to_install">Klik for at installere</string>
<string name="home_working">Arbejder</string> <string name="home_working">Arbejder</string>
<string name="home_working_version">Version: %d</string> <string name="home_working_version">Version: %s</string>
<string name="home_unsupported">Ikke understøttet</string> <string name="home_unsupported">Ikke understøttet</string>
<string name="home_unsupported_reason">KernelSU understøtter kun GKI kernels</string> <string name="home_unsupported_reason">KernelSU understøtter kun GKI kernels</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux-kontext</string> <string name="profile_selinux_context">SELinux-kontext</string>
<string name="profile_umount_modules">Afmonteret moduler</string> <string name="profile_umount_modules">Afmonteret moduler</string>
<string name="failed_to_update_app_profile">Opdatering af App Profil for %s fejlede</string> <string name="failed_to_update_app_profile">Opdatering af App Profil for %s fejlede</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Afmontere moduler som standard</string> <string name="settings_umount_modules_default">Afmontere moduler som standard</string>
<string name="settings_umount_modules_default_summary">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.</string> <string name="settings_umount_modules_default_summary">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.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nicht installiert</string> <string name="home_not_installed">Nicht installiert</string>
<string name="home_click_to_install">Tippe zum Installieren</string> <string name="home_click_to_install">Tippe zum Installieren</string>
<string name="home_working">Funktioniert</string> <string name="home_working">Funktioniert</string>
<string name="home_working_version">Version: %d</string> <string name="home_working_version">Version: %s</string>
<string name="home_unsupported">Nicht unterstützt</string> <string name="home_unsupported">Nicht unterstützt</string>
<string name="home_unsupported_reason">KernelSU unterstützt derzeit nur GKI-Kernel</string> <string name="home_unsupported_reason">KernelSU unterstützt derzeit nur GKI-Kernel</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux-Kontext</string> <string name="profile_selinux_context">SELinux-Kontext</string>
<string name="profile_umount_modules">Module aushängen</string> <string name="profile_umount_modules">Module aushängen</string>
<string name="failed_to_update_app_profile">App-Profilaktualisierung für %s fehlgeschlagen</string> <string name="failed_to_update_app_profile">App-Profilaktualisierung für %s fehlgeschlagen</string>
<string name="require_kernel_version" formatted="false">Die aktuelle KernelSU-Version %d ist zu alt für diese Manager-Version. Bitte auf Version %d oder höher aktualisieren!</string> <string name="require_kernel_version" formatted="false">Die aktuelle KernelSU-Version %s ist zu alt für diese Manager-Version. Bitte auf Version %s oder höher aktualisieren!</string>
<string name="settings_umount_modules_default">Module standardmäßig aushängen</string> <string name="settings_umount_modules_default">Module standardmäßig aushängen</string>
<string name="settings_umount_modules_default_summary">Globaler Standardwert für \"Module aushängen\" im App-Profil. Falls er aktiviert ist, werden alle Moduländerungen im System für alle Apps entfernt, für die kein Profil festgelegt ist.</string> <string name="settings_umount_modules_default_summary">Globaler Standardwert für \"Module aushängen\" im App-Profil. Falls er aktiviert ist, werden alle Moduländerungen im System für alle Apps entfernt, für die kein Profil festgelegt ist.</string>
<string name="settings_susfs_toggle">Kprobe-Hooks deaktivieren</string> <string name="settings_susfs_toggle">Kprobe-Hooks deaktivieren</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">No instalado</string> <string name="home_not_installed">No instalado</string>
<string name="home_click_to_install">Haz clic para instalar</string> <string name="home_click_to_install">Haz clic para instalar</string>
<string name="home_working">Funcionando</string> <string name="home_working">Funcionando</string>
<string name="home_working_version">Versión: %d</string> <string name="home_working_version">Versión: %s</string>
<string name="home_unsupported">Sin soporte</string> <string name="home_unsupported">Sin soporte</string>
<string name="home_unsupported_reason">KernelSU solo admite kernels GKI por ahora</string> <string name="home_unsupported_reason">KernelSU solo admite kernels GKI por ahora</string>
<string name="home_kernel">Versión del kernel</string> <string name="home_kernel">Versión del kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Contexto SELinux</string> <string name="profile_selinux_context">Contexto SELinux</string>
<string name="profile_umount_modules">Desmontar módulos</string> <string name="profile_umount_modules">Desmontar módulos</string>
<string name="failed_to_update_app_profile">Error al actualizar el perfil de la aplicación para %s</string> <string name="failed_to_update_app_profile">Error al actualizar el perfil de la aplicación para %s</string>
<string name="require_kernel_version" formatted="false">La versión %d actual de KernelSU es demasiado baja para que el gestor funcione correctamente. Por favor, ¡actualice a la versión %d o superior!</string> <string name="require_kernel_version" formatted="false">La versión %s actual de KernelSU es demasiado baja para que el gestor funcione correctamente. Por favor, ¡actualice a la versión %s o superior!</string>
<string name="settings_umount_modules_default">Desmontar módulos por defecto</string> <string name="settings_umount_modules_default">Desmontar módulos por defecto</string>
<string name="settings_umount_modules_default_summary">El valor global predeterminado para \"Umount modules\" en App Profile. Si está activado, eliminará todas las modificaciones de módulos del sistema para las apps que no tengan un perfil establecido.</string> <string name="settings_umount_modules_default_summary">El valor global predeterminado para \"Umount modules\" en App Profile. Si está activado, eliminará todas las modificaciones de módulos del sistema para las apps que no tengan un perfil establecido.</string>
<string name="settings_susfs_toggle">Desactivar kprobe hooks</string> <string name="settings_susfs_toggle">Desactivar kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Pole paigaldatud</string> <string name="home_not_installed">Pole paigaldatud</string>
<string name="home_click_to_install">Klõpsa paigaldamiseks</string> <string name="home_click_to_install">Klõpsa paigaldamiseks</string>
<string name="home_working">Töötamine</string> <string name="home_working">Töötamine</string>
<string name="home_working_version">Versioon: %d</string> <string name="home_working_version">Versioon: %s</string>
<string name="home_unsupported">Mittetoetatud</string> <string name="home_unsupported">Mittetoetatud</string>
<string name="home_unsupported_reason">KernelSU toetab hetkel vaid GSI tuumasid</string> <string name="home_unsupported_reason">KernelSU toetab hetkel vaid GSI tuumasid</string>
<string name="home_kernel">Tuum</string> <string name="home_kernel">Tuum</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontekst</string> <string name="profile_selinux_context">SELinux kontekst</string>
<string name="profile_umount_modules">Lahtihaagitud moodulid</string> <string name="profile_umount_modules">Lahtihaagitud moodulid</string>
<string name="failed_to_update_app_profile">Rakenduseprofiili uuendamine %s jaoks ebaõnnestus</string> <string name="failed_to_update_app_profile">Rakenduseprofiili uuendamine %s jaoks ebaõnnestus</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Haagi moodulid vaikimisi lahti</string> <string name="settings_umount_modules_default">Haagi moodulid vaikimisi lahti</string>
<string name="settings_umount_modules_default_summary">Globaalne vaikeväärtus \"Lahtihaagitud moodulitele\" rakenduseprofiilis. Lubamisel eemaldab see kõik moodulite süsteemimuudatused rakendustele, millel ei ole profiili määratud.</string> <string name="settings_umount_modules_default_summary">Globaalne vaikeväärtus \"Lahtihaagitud moodulitele\" rakenduseprofiilis. Lubamisel eemaldab see kõik moodulite süsteemimuudatused rakendustele, millel ei ole profiili määratud.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">نصب نشده است</string> <string name="home_not_installed">نصب نشده است</string>
<string name="home_click_to_install">برای نصب ضربه بزنید</string> <string name="home_click_to_install">برای نصب ضربه بزنید</string>
<string name="home_working">به درستی کار می‌کند</string> <string name="home_working">به درستی کار می‌کند</string>
<string name="home_working_version">نسخه: %d</string> <string name="home_working_version">نسخه: %s</string>
<string name="home_unsupported">پشتیبانی نشده</string> <string name="home_unsupported">پشتیبانی نشده</string>
<string name="home_unsupported_reason">کرنل اس یو فقط هسته های gki را پشتیبانی میکند</string> <string name="home_unsupported_reason">کرنل اس یو فقط هسته های gki را پشتیبانی میکند</string>
<string name="home_kernel">هسته</string> <string name="home_kernel">هسته</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux context</string> <string name="profile_selinux_context">SELinux context</string>
<string name="profile_umount_modules">جداکردن ماژول ها</string> <string name="profile_umount_modules">جداکردن ماژول ها</string>
<string name="failed_to_update_app_profile">Failed to update App Profile for %s</string> <string name="failed_to_update_app_profile">Failed to update App Profile for %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount modules by default</string> <string name="settings_umount_modules_default">Umount modules by default</string>
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string> <string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Hindi naka-install</string> <string name="home_not_installed">Hindi naka-install</string>
<string name="home_click_to_install">Pindutin para mag-install</string> <string name="home_click_to_install">Pindutin para mag-install</string>
<string name="home_working">Gumagana</string> <string name="home_working">Gumagana</string>
<string name="home_working_version">Bersyon: %d</string> <string name="home_working_version">Bersyon: %s</string>
<string name="home_unsupported">Hindi Suportado</string> <string name="home_unsupported">Hindi Suportado</string>
<string name="home_unsupported_reason">Sinusuportahan lang ng KernelSU ang mga kernel ng GKI ngayon</string> <string name="home_unsupported_reason">Sinusuportahan lang ng KernelSU ang mga kernel ng GKI ngayon</string>
<string name="home_kernel">Kernel version</string> <string name="home_kernel">Kernel version</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Konteksto ng SELinux</string> <string name="profile_selinux_context">Konteksto ng SELinux</string>
<string name="profile_umount_modules">I-unmount ang mga modyul</string> <string name="profile_umount_modules">I-unmount ang mga modyul</string>
<string name="failed_to_update_app_profile">Nabigong i-update ang App Profile para sa %s</string> <string name="failed_to_update_app_profile">Nabigong i-update ang App Profile para sa %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount modules by default</string> <string name="settings_umount_modules_default">Umount modules by default</string>
<string name="settings_umount_modules_default_summary">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.</string> <string name="settings_umount_modules_default_summary">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.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Non installé</string> <string name="home_not_installed">Non installé</string>
<string name="home_click_to_install">Appuyez ici pour installer</string> <string name="home_click_to_install">Appuyez ici pour installer</string>
<string name="home_working">Fonctionnel</string> <string name="home_working">Fonctionnel</string>
<string name="home_working_version">Version : %d</string> <string name="home_working_version">Version : %s</string>
<string name="home_unsupported">Non pris en charge</string> <string name="home_unsupported">Non pris en charge</string>
<string name="home_unsupported_reason">KernelSU ne prend désormais en charge que les noyaux GKI</string> <string name="home_unsupported_reason">KernelSU ne prend désormais en charge que les noyaux GKI</string>
<string name="home_kernel">Noyau</string> <string name="home_kernel">Noyau</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Contexte SELinux</string> <string name="profile_selinux_context">Contexte SELinux</string>
<string name="profile_umount_modules">Démonter les modules</string> <string name="profile_umount_modules">Démonter les modules</string>
<string name="failed_to_update_app_profile">Échec de la modification du profil d\'application de %s</string> <string name="failed_to_update_app_profile">Échec de la modification du profil d\'application de %s</string>
<string name="require_kernel_version" formatted="false">La version actuelle de KernelSU (%d) est trop ancienne pour que le gestionnaire fonctionne correctement. Veuillez passer à la version %d ou à une version supérieure!</string> <string name="require_kernel_version" formatted="false">La version actuelle de KernelSU (%s) est trop ancienne pour que le gestionnaire fonctionne correctement. Veuillez passer à la version %s ou à une version supérieure!</string>
<string name="settings_umount_modules_default">Démonter les modules par défaut</string> <string name="settings_umount_modules_default">Démonter les modules par défaut</string>
<string name="settings_umount_modules_default_summary">Valeur globale par défaut pour l\'option \"Démonter les modules\" dans les profils d\'application. Lorsque l\'option est activée, les modifications apportées au système par les modules sont supprimées pour les applications qui n\'ont pas de profil défini.</string> <string name="settings_umount_modules_default_summary">Valeur globale par défaut pour l\'option \"Démonter les modules\" dans les profils d\'application. Lorsque l\'option est activée, les modifications apportées au système par les modules sont supprimées pour les applications qui n\'ont pas de profil défini.</string>
<string name="settings_susfs_toggle">Désactiver les crochets kprobe</string> <string name="settings_susfs_toggle">Désactiver les crochets kprobe</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">इंस्टाल नहीं हुआ</string> <string name="home_not_installed">इंस्टाल नहीं हुआ</string>
<string name="home_click_to_install">इंस्टाल करने के लिए क्लिक करें</string> <string name="home_click_to_install">इंस्टाल करने के लिए क्लिक करें</string>
<string name="home_working">काम कर रहा है</string> <string name="home_working">काम कर रहा है</string>
<string name="home_working_version">वर्जन: %d</string> <string name="home_working_version">वर्जन: %s</string>
<string name="home_unsupported">सपोर्ट नहीं करता है</string> <string name="home_unsupported">सपोर्ट नहीं करता है</string>
<string name="home_unsupported_reason">KernelSU अभी केवल GKI कर्नल्स को सपोर्ट करता है</string> <string name="home_unsupported_reason">KernelSU अभी केवल GKI कर्नल्स को सपोर्ट करता है</string>
<string name="home_kernel">कर्नल</string> <string name="home_kernel">कर्नल</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux context</string> <string name="profile_selinux_context">SELinux context</string>
<string name="profile_umount_modules">मॉड्यूल्स अनमाउंट करें</string> <string name="profile_umount_modules">मॉड्यूल्स अनमाउंट करें</string>
<string name="failed_to_update_app_profile">%s के लिए ऐप प्रोफ़ाइल अपडेट करने में विफल</string> <string name="failed_to_update_app_profile">%s के लिए ऐप प्रोफ़ाइल अपडेट करने में विफल</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">डिफ़ॉल्ट रूप से मॉड्यूल अनमाउन्ट करें</string> <string name="settings_umount_modules_default">डिफ़ॉल्ट रूप से मॉड्यूल अनमाउन्ट करें</string>
<string name="settings_umount_modules_default_summary">ऐप प्रोफाइल में \"अनमाउंट मॉड्यूल\" के लिए ग्लोबल डिफ़ॉल्ट वैल्यू। यदि चालू किया गया है, तो यह एप्लीकेशंस के लिऐ सिस्टम के सभी मॉड्यूल मोडिफिकेशन को हटा देगा जिनकी प्रोफ़ाइल सेट नहीं है।</string> <string name="settings_umount_modules_default_summary">ऐप प्रोफाइल में \"अनमाउंट मॉड्यूल\" के लिए ग्लोबल डिफ़ॉल्ट वैल्यू। यदि चालू किया गया है, तो यह एप्लीकेशंस के लिऐ सिस्टम के सभी मॉड्यूल मोडिफिकेशन को हटा देगा जिनकी प्रोफ़ाइल सेट नहीं है।</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nije instalirano</string> <string name="home_not_installed">Nije instalirano</string>
<string name="home_click_to_install">Kliknite da instalirate</string> <string name="home_click_to_install">Kliknite da instalirate</string>
<string name="home_working">Radi</string> <string name="home_working">Radi</string>
<string name="home_working_version">Verzija: %d</string> <string name="home_working_version">Verzija: %s</string>
<string name="home_unsupported">Nepodržano</string> <string name="home_unsupported">Nepodržano</string>
<string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string> <string name="home_unsupported_reason">KernelSU samo podržava GKI kernele sad</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontekst</string> <string name="profile_selinux_context">SELinux kontekst</string>
<string name="profile_umount_modules">Umount module</string> <string name="profile_umount_modules">Umount module</string>
<string name="failed_to_update_app_profile">Ažuriranje Profila Aplikacije za %s nije uspjelo</string> <string name="failed_to_update_app_profile">Ažuriranje Profila Aplikacije za %s nije uspjelo</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount module po zadanom</string> <string name="settings_umount_modules_default">Umount module po zadanom</string>
<string name="settings_umount_modules_default_summary">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.</string> <string name="settings_umount_modules_default_summary">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.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nincs telepítve</string> <string name="home_not_installed">Nincs telepítve</string>
<string name="home_click_to_install">Kattintson a telepítéshez</string> <string name="home_click_to_install">Kattintson a telepítéshez</string>
<string name="home_working">Működik</string> <string name="home_working">Működik</string>
<string name="home_working_version">Verzió: %d</string> <string name="home_working_version">Verzió: %s</string>
<string name="home_unsupported">Nem támogatott</string> <string name="home_unsupported">Nem támogatott</string>
<string name="home_unsupported_reason">A KernelSU jelenleg csak GKI kerneleket támogat</string> <string name="home_unsupported_reason">A KernelSU jelenleg csak GKI kerneleket támogat</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontextus</string> <string name="profile_selinux_context">SELinux kontextus</string>
<string name="profile_umount_modules">Modulok leválasztása</string> <string name="profile_umount_modules">Modulok leválasztása</string>
<string name="failed_to_update_app_profile">Nem sikerült frissíteni az App Profilt ehhez: %s</string> <string name="failed_to_update_app_profile">Nem sikerült frissíteni az App Profilt ehhez: %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Modulok leválasztása alapértelmezetten</string> <string name="settings_umount_modules_default">Modulok leválasztása alapértelmezetten</string>
<string name="settings_umount_modules_default_summary">A \"Modulok leválasztása\" globális alapértelmezett értéke az App Profile-ban. Ha engedélyezve van, eltávolít minden modulmódosítást a rendszerből azon alkalmazások esetében, amelyeknek nincs profilja beállítva.</string> <string name="settings_umount_modules_default_summary">A \"Modulok leválasztása\" globális alapértelmezett értéke az App Profile-ban. Ha engedélyezve van, eltávolít minden modulmódosítást a rendszerből azon alkalmazások esetében, amelyeknek nincs profilja beállítva.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,10 +4,11 @@
<string name="home_not_installed">Tidak terinstal</string> <string name="home_not_installed">Tidak terinstal</string>
<string name="home_click_to_install">Klik untuk menginstal</string> <string name="home_click_to_install">Klik untuk menginstal</string>
<string name="home_working">Berfungsi</string> <string name="home_working">Berfungsi</string>
<string name="home_working_version">Versi: %d</string> <string name="home_working_version">Versi: %s</string>
<string name="home_unsupported">Tidak didukung</string> <string name="home_unsupported">Tidak didukung</string>
<string name="home_unsupported_reason">KernelSU saat ini hanya mendukung kernel GKI</string> <string name="home_unsupported_reason">KernelSU saat ini hanya mendukung kernel GKI</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
<string name="home_susfs_version">Versi SuSFS</string>
<string name="home_manager_version">Versi manager</string> <string name="home_manager_version">Versi manager</string>
<string name="home_selinux_status">Status SELinux</string> <string name="home_selinux_status">Status SELinux</string>
<string name="selinux_status_disabled">Nonaktif</string> <string name="selinux_status_disabled">Nonaktif</string>
@@ -19,6 +20,8 @@
<string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string> <string name="module_failed_to_disable">Gagal menonaktifkan modul: %s</string>
<string name="module_empty">Tidak ada modul yang terpasang</string> <string name="module_empty">Tidak ada modul yang terpasang</string>
<string name="module">Modul</string> <string name="module">Modul</string>
<string name="module_sort_action_first">Urut (Tindakan pertama)</string>
<string name="module_sort_enabled_first">Urut (Diaktifkan terlebih dahulu)</string>
<string name="uninstall">Hapus</string> <string name="uninstall">Hapus</string>
<string name="module_install">Instal</string> <string name="module_install">Instal</string>
<string name="install">Instal</string> <string name="install">Instal</string>
@@ -47,6 +50,7 @@
<string name="home_click_to_learn_kernelsu">Pelajari cara instal KernelSU dan menggunakan modul</string> <string name="home_click_to_learn_kernelsu">Pelajari cara instal KernelSU dan menggunakan modul</string>
<string name="home_support_title">Dukung Kami</string> <string name="home_support_title">Dukung Kami</string>
<string name="home_support_content">KernelSU akan selalu menjadi aplikasi gratis dan terbuka. Anda dapat memberikan donasi sebagai bentuk dukungan.</string> <string name="home_support_content">KernelSU akan selalu menjadi aplikasi gratis dan terbuka. Anda dapat memberikan donasi sebagai bentuk dukungan.</string>
<string name="about_source_code"><![CDATA[Lihat kode sumber di %1$s<br/>Gabung dengan kami di saluran %2$s]]></string>
<string name="profile_default">Bawaan</string> <string name="profile_default">Bawaan</string>
<string name="profile_template">Templat</string> <string name="profile_template">Templat</string>
<string name="profile_custom">Khusus</string> <string name="profile_custom">Khusus</string>
@@ -58,6 +62,7 @@
<string name="failed_to_update_app_profile">Gagal membarui Profil pada %s</string> <string name="failed_to_update_app_profile">Gagal membarui Profil pada %s</string>
<string name="settings_umount_modules_default">Melepas Modul secara bawaan</string> <string name="settings_umount_modules_default">Melepas Modul secara bawaan</string>
<string name="settings_umount_modules_default_summary">Menggunakan \"Umount Modul\" secara universal pada Profil Aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set profil.</string> <string name="settings_umount_modules_default_summary">Menggunakan \"Umount Modul\" secara universal pada Profil Aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set profil.</string>
<string name="settings_susfs_toggle">Nonaktifkan kprobe hooks</string>
<string name="profile_umount_modules_summary">Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini.</string> <string name="profile_umount_modules_summary">Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini.</string>
<string name="profile_selinux_domain">Domain</string> <string name="profile_selinux_domain">Domain</string>
<string name="profile_selinux_rules">Aturan</string> <string name="profile_selinux_rules">Aturan</string>
@@ -70,122 +75,84 @@
<string name="restart_app">Mulai ulang</string> <string name="restart_app">Mulai ulang</string>
<string name="failed_to_update_sepolicy">Gagal membarui aturan SELinux pada: %s</string> <string name="failed_to_update_sepolicy">Gagal membarui aturan SELinux pada: %s</string>
<string name="module_changelog">Catatan Perubahan</string> <string name="module_changelog">Catatan Perubahan</string>
<string name="app_profile_template_import_success">Berhasil diimpor</string> <string name="settings_profile_template">Templat Profil Aplikasi</string>
<string name="app_profile_export_to_clipboard">Ekspor ke papan klip</string> <string name="settings_profile_template_summary">Atur templat Profil yang lokal dan daring</string>
<string name="app_profile_template_export_empty">Tidak ditemukan templat lokal untuk diekspor!</string>
<string name="app_profile_template_id_exist">ID templat sudah ada!</string>
<string name="app_profile_import_from_clipboard">Impor dari papan klip</string>
<string name="module_changelog_failed">Gagal mengambil Changelog: %s</string>
<string name="app_profile_template_name">Nama</string>
<string name="app_profile_template_id_invalid">ID template tidak valid</string>
<string name="app_profile_template_sync">Sinkronkan templat daring</string>
<string name="app_profile_template_create">Buat templat</string> <string name="app_profile_template_create">Buat templat</string>
<string name="app_profile_import_export">Impor/Ekspor</string>
<string name="app_profile_template_save_failed">Gagal menyimpan templat</string>
<string name="app_profile_template_edit">Edit templat</string> <string name="app_profile_template_edit">Edit templat</string>
<string name="app_profile_template_id">ID</string> <string name="app_profile_template_id">ID</string>
<string name="settings_profile_template">Templat Profil Aplikasi</string> <string name="app_profile_template_id_invalid">ID template tidak valid</string>
<string name="app_profile_template_name">Nama</string>
<string name="app_profile_template_description">Deskripsi</string> <string name="app_profile_template_description">Deskripsi</string>
<string name="app_profile_template_save">Simpan</string> <string name="app_profile_template_save">Simpan</string>
<string name="settings_profile_template_summary">Atur templat Profil yang lokal dan daring</string>
<string name="app_profile_template_delete">Hapus</string> <string name="app_profile_template_delete">Hapus</string>
<string name="app_profile_template_import_empty">Papan klip kosong!</string>
<string name="app_profile_template_view">Lihat templat</string> <string name="app_profile_template_view">Lihat templat</string>
<string name="app_profile_template_readonly">readonly</string> <string name="app_profile_template_readonly">readonly</string>
<string name="app_profile_template_id_exist">ID templat sudah ada!</string>
<string name="app_profile_import_export">Impor/Ekspor</string>
<string name="app_profile_import_from_clipboard">Impor dari papan klip</string>
<string name="app_profile_export_to_clipboard">Ekspor ke papan klip</string>
<string name="app_profile_template_export_empty">Tidak ditemukan templat lokal untuk diekspor!</string>
<string name="app_profile_template_import_success">Berhasil diimpor</string>
<string name="app_profile_template_sync">Sinkronkan templat daring</string>
<string name="app_profile_template_save_failed">Gagal menyimpan templat</string>
<string name="app_profile_template_import_empty">Papan klip kosong!</string>
<string name="module_changelog_failed">Gagal mengambil Changelog: %s</string>
<string name="settings_check_update">Cek terbaru</string>
<string name="settings_check_update_summary">Cek terbaru setiap membuka aplikasi</string>
<string name="grant_root_failed">Gagal memberikan akses root!</string>
<string name="action">Tindakan</string>
<string name="close">Tutup</string>
<string name="enable_web_debugging">Pengawakutuan WebView</string> <string name="enable_web_debugging">Pengawakutuan WebView</string>
<string name="enable_web_debugging_summary">Dapat digunakan untuk men-debug WebUI. Harap aktifkan hanya bila diperlukan.</string> <string name="enable_web_debugging_summary">Dapat digunakan untuk men-debug WebUI. Harap aktifkan hanya bila diperlukan.</string>
<string name="select_file_tip">%1$s image partisi terekomendasi</string>
<string name="select_kmi">Pilih KMI</string>
<string name="install_next">Selanjutnya</string>
<string name="install_inactive_slot_warning">Gawai akan **DIPAKSA** untuk but ke slot nonaktif!
\nHANYA gunakan setelah proses OTA selesai.
\nLanjutkan?</string>
<string name="direct_install">Instal langsung (rekomendasi)</string> <string name="direct_install">Instal langsung (rekomendasi)</string>
<string name="select_file">Pilih berkas</string> <string name="select_file">Pilih berkas</string>
<string name="install_inactive_slot">Instal ke slot nonaktif (setelah OTA)</string> <string name="install_inactive_slot">Instal ke slot nonaktif (setelah OTA)</string>
<string name="grant_root_failed">Gagal memberikan akses root!</string> <string name="install_inactive_slot_warning">Gawai akan **DIPAKSA** untuk but ke slot nonaktif!
<string name="close">Tutup</string> \nHANYA gunakan setelah proses OTA selesai.
<string name="settings_check_update">Cek terbaru</string> \nLanjutkan?</string>
<string name="settings_check_update_summary">Cek terbaru setiap membuka aplikasi</string> <string name="install_next">Selanjutnya</string>
<string name="settings_uninstall_permanent_message">Hapus permanen KernelSU (root dan modul).</string> <string name="select_file_tip">%1$s image partisi terekomendasi</string>
<string name="settings_uninstall_temporary">Hapus sementara</string> <string name="select_kmi">Pilih KMI</string>
<string name="settings_restore_stock_image">Pulihkan image bawaan</string>
<string name="settings_uninstall">Hapus</string> <string name="settings_uninstall">Hapus</string>
<string name="settings_uninstall_temporary_message">Sementara menghapus KernelSU, memulihkan ke kondisi asal setelah reboot berikutnya.</string> <string name="settings_uninstall_temporary">Hapus sementara</string>
<string name="settings_uninstall_permanent">Hapus permanen</string> <string name="settings_uninstall_permanent">Hapus permanen</string>
<string name="settings_restore_stock_image">Pulihkan image bawaan</string>
<string name="settings_uninstall_temporary_message">Sementara menghapus KernelSU, memulihkan ke kondisi asal setelah reboot berikutnya.</string>
<string name="settings_uninstall_permanent_message">Hapus permanen KernelSU (root dan modul).</string>
<string name="settings_restore_stock_image_message">Pulihkan image bawaan ROM (jika cadangan tersedia), umumnya dilakukan sebelum OTA; jika ingin menghapus KernelSU, gunakan fungsi \"Hapus permanen\".</string> <string name="settings_restore_stock_image_message">Pulihkan image bawaan ROM (jika cadangan tersedia), umumnya dilakukan sebelum OTA; jika ingin menghapus KernelSU, gunakan fungsi \"Hapus permanen\".</string>
<string name="flash_success">Pemasangan Berhasil</string>
<string name="selected_lkm">LKM dipilih: %s</string>
<string name="flashing">Pasang</string> <string name="flashing">Pasang</string>
<string name="flash_success">Pemasangan Berhasil</string>
<string name="flash_failed">Pemasangan Gagal</string> <string name="flash_failed">Pemasangan Gagal</string>
<string name="selected_lkm">LKM dipilih: %s</string>
<string name="save_log">Simpan Log</string> <string name="save_log">Simpan Log</string>
<string name="action">Action</string>
<string name="log_saved">Log disimpan</string> <string name="log_saved">Log disimpan</string>
<string name="module_sort_enabled_first">Urut (Diaktifkan terlebih dahulu)</string> <string name="sus_su_mode">Mode SuS SU:</string>
<string name="module_sort_action_first">Urut (Tindakan pertama)</string> <!-- Module related -->
<string name="home_android_version">Versi Android</string> <string name="module_install_confirm">konfirmasi pemasangan modul %1$s?</string>
<string name="home_kpm_version">Versi KPM</string> <!-- Restore related -->
<string name="home_susfs_version">Versi SuSFS</string> <string name="restore_confirm_message">Operasi ini akan menimpa semua modul yang ada. Lanjutkan?</string>
<string name="home_device_model">Model Perangkat</string> <string name="confirm">Konfirmasi</string>
<string name="home_ContributionCard_kernelsu">Antusias Untuk SukiSU Ultra</string> <string name="cancel">Batal</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra akan menjadi cabang KSU yang relatif independen di masa mendatang, tetapi kami tetap menghargai KernelSU dan MKSU resmi dan sebagainya atas kontribusi mereka!</string> <!-- Backup related -->
<string name="kpm_title">KPM</string> <string name="backup_success">Pencadangan berhasil (tar.gz)</string>
<string name="kpm_empty">Tidak ada modul kernel yang terpasang saat ini</string> <string name="backup_failed">Pencadangan gagal: %1$s</string>
<string name="kpm_version">Versi</string> <string name="backup_modules">cadangkan modul</string>
<string name="kpm_author">Pembuat</string> <string name="restore_modules">pulihkan modul</string>
<string name="kpm_uninstall">Uninstal</string> <!-- Restore related messages -->
<string name="kpm_uninstall_success">Berhasil di Uninstal</string> <string name="restore_success">Modul berhasil dipulihkan, restart diperlukan</string>
<string name="kpm_uninstall_failed">Gagal Uninstal</string> <string name="restore_failed">Pemulihan gagal: %1$s</string>
<string name="kpm_install_success">Memuat module KPM berhasil</string> <string name="restart_now">Mulai Ulang Sekarang</string>
<string name="kpm_install_failed">Memuat module KPM gagal!</string> <string name="unknown_error">Kesalahan tidak diketahui</string>
<string name="kpm_args">Parameter</string> <!-- Command related -->
<string name="kpm_control">Eksekusi</string> <!-- Allowlist related -->
<string name="kernel_module_notice">Fungsi-fungsi modul kernel berikut dikembangkan oleh KernelPatch dan dimodifikasi untuk menyertakan fungsi modul kernel dari SukiSU Ultra</string>
<string name="settings_disable_su">Nonaktifkan kompatibilitas SU</string>
<string name="settings_disable_su_summary">Nonaktifkan sementara kemampuan aplikasi untuk mendapatkan hak akses root melalui perintah su (proses root yang sedang berjalan tidak akan terpengaruh)</string>
<string name="use_webuix">Pilih jenis webUI untuk digunakan</string>
<string name="engine_auto_select">Otomatis memilih</string>
<string name="engine_force_webuix">Paksa menggunakan WebUI X</string>
<string name="engine_force_ksu">Penggunaan wajib KSU WebUI</string>
<string name="more_settings">Setelan lainnya</string>
<string name="language_setting">Bahasa Aplikasi</string>
<string name="language_follow_system">Mengikuti sistem</string>
<string name="language_changed">Bahasa dirubah, mulai ulang aplikasi untuk menerapkan</string>
<string name="theme_mode">Tema</string>
<string name="theme_follow_system">Mengikuti sistem</string>
<string name="theme_light">Terang</string>
<string name="theme_dark">Hitam</string>
<string name="dynamic_color_title">Warna dinamik</string>
<string name="dynamic_color_summary">Warna dinamik, menggunakan sistem tema</string>
<string name="choose_theme_color">Pilih warna tema</string>
<string name="color_default">Biru</string>
<string name="color_green">Hijau</string>
<string name="color_purple">Ungu</string>
<string name="color_orange">Oren</string>
<string name="color_pink">Pink</string>
<string name="color_gray">Abu</string>
<string name="color_yellow">Kuning</string>
<string name="app_dpi_title">Ubah DPI</string>
<string name="app_dpi_summary">Pengaturan DPI hanya untuk aplikasi ini saja</string>
<string name="dpi_size_small">Kecil</string>
<string name="dpi_size_medium">Sedang</string>
<string name="dpi_size_large">Besar</string>
<string name="dpi_size_extra_large">Jumbo</string>
<string name="dpi_size_custom">Kustomisasi</string>
<string name="dpi_apply_settings">Terapkan setelan DPI</string>
<string name="dpi_confirm_title">Konfirmasi perubahan DPI</string>
<string name="dpi_confirm_message">Apa kamu yakin ingin merubah DPI aplikasi dari %1$d ke %2$d?</string>
<string name="dpi_confirm_summary">Aplikasi membutuhkan restar untuk menerapkan opsi DPI ini, perubahan ini tidak mengganggu DPI sistem</string>
<string name="dpi_applied_success">DPI telah di rubah ke %1$d, efektif setelah aplikasi di restar</string>
<string name="settings_custom_background">Latar belakang kustom</string> <string name="settings_custom_background">Latar belakang kustom</string>
<string name="settings_custom_background_summary">Pilih gambar untuk latar belakang</string> <string name="settings_custom_background_summary">Pilih gambar untuk latar belakang</string>
<string name="settings_card_alpha">NavBar transparant</string> <string name="settings_card_alpha">NavBar transparant</string>
<string name="appearance_settings">Kustomisasi toolbar</string> <string name="home_android_version">Versi Android</string>
<string name="icon_switch_title">Ubah ikon</string> <string name="home_device_model">Model Perangkat</string>
<string name="icon_switch_summary">Ubah ikon peluncur aplikasi ke ikon KernelSU</string> <string name="settings_disable_su">Nonaktifkan kompatibilitas SU</string>
<string name="icon_switched">Ikon dirubah</string> <string name="settings_disable_su_summary">Nonaktifkan sementara kemampuan aplikasi untuk mendapatkan hak akses root melalui perintah su (proses root yang sedang berjalan tidak akan terpengaruh)</string>
<string name="show_more_module_info">Tampilkan info modul lainnya</string> <string name="more_settings">Setelan lainnya</string>
<string name="show_more_module_info_summary">Pajang info modul tambahan seperti URL pembaruan JSON</string>
<string name="simple_mode">Mode simple</string> <string name="simple_mode">Mode simple</string>
<string name="simple_mode_summary">Sembunyikan papan kartu di beranda</string> <string name="simple_mode_summary">Sembunyikan papan kartu di beranda</string>
<string name="hide_kernel_kernelsu_version">Sembunyikan versi kernel</string> <string name="hide_kernel_kernelsu_version">Sembunyikan versi kernel</string>
@@ -198,6 +165,93 @@
<string name="hide_link_card_summary">Sembunyikan papan kartu URL di halaman awal beranda</string> <string name="hide_link_card_summary">Sembunyikan papan kartu URL di halaman awal beranda</string>
<string name="hide_tag_card">Sembunyikan baris label modul</string> <string name="hide_tag_card">Sembunyikan baris label modul</string>
<string name="hide_tag_card_summary">Sembunyikan label nama folder dan ukuran di kartu modul</string> <string name="hide_tag_card_summary">Sembunyikan label nama folder dan ukuran di kartu modul</string>
<string name="theme_mode">Tema</string>
<string name="theme_follow_system">Mengikuti sistem</string>
<string name="theme_light">Terang</string>
<string name="theme_dark">Hitam</string>
<string name="dynamic_color_title">Warna dinamik</string>
<string name="dynamic_color_summary">Warna dinamik, menggunakan sistem tema</string>
<string name="choose_theme_color">Pilih warna tema</string>
<string name="color_default">Biru</string>
<string name="color_green">Hijau</string>
<string name="color_purple">Ungu</string>
<string name="color_orange">Oren</string>
<string name="color_gray">Abu</string>
<string name="color_yellow">Kuning</string>
<string name="kpm_empty">Tidak ada modul kernel yang terpasang saat ini</string>
<string name="kpm_version">Versi</string>
<string name="kpm_author">Pembuat</string>
<string name="kpm_uninstall">Uninstal</string>
<string name="kpm_uninstall_success">Berhasil di Uninstal</string>
<string name="kpm_uninstall_failed">Gagal Uninstal</string>
<string name="kpm_install_success">Memuat module KPM berhasil</string>
<string name="kpm_install_failed">Memuat module KPM gagal!</string>
<string name="kpm_args">Parameter</string>
<string name="kpm_control">Eksekusi</string>
<string name="home_kpm_version">Versi KPM</string>
<string name="kernel_module_notice">Fungsi-fungsi modul kernel berikut dikembangkan oleh KernelPatch dan dimodifikasi untuk menyertakan fungsi modul kernel dari SukiSU Ultra</string>
<string name="home_ContributionCard_kernelsu">Antusias Untuk SukiSU Ultra</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra akan menjadi cabang KSU yang relatif independen di masa mendatang, tetapi kami tetap menghargai KernelSU dan MKSU resmi dan sebagainya atas kontribusi mereka!</string>
<!-- Kernel Flash Progress Related -->
<!-- Flash Status Related -->
<!-- Slot selection related strings -->
<!-- Error Messages -->
<!-- lkm/gki install -->
<!-- String resources used in SuperUser -->
<string name="appearance_settings">Kustomisasi toolbar</string>
<string name="icon_switch_title">Ubah ikon</string>
<string name="icon_switch_summary">Ubah ikon peluncur aplikasi ke ikon KernelSU</string>
<string name="icon_switched">Ikon dirubah</string>
<!-- KPM display settings -->
<string name="show_kpm_info">Tampilkan fungsi KPM</string> <string name="show_kpm_info">Tampilkan fungsi KPM</string>
<string name="show_kpm_info_summary">Tampilkan fungsi informasi KPM dan menu KPM di bilah navigasi</string> <string name="show_kpm_info_summary">Tampilkan fungsi informasi KPM dan menu KPM di bilah navigasi</string>
<!-- Webui X settings -->
<string name="use_webuix">Pilih jenis webUI untuk digunakan</string>
<string name="engine_auto_select">Otomatis memilih</string>
<string name="engine_force_webuix">Paksa menggunakan WebUI X</string>
<string name="engine_force_ksu">Penggunaan wajib KSU WebUI</string>
<!-- DPI setting related strings -->
<string name="app_dpi_title">Ubah DPI</string>
<string name="app_dpi_summary">Pengaturan DPI hanya untuk aplikasi ini saja</string>
<string name="dpi_size_small">Kecil</string>
<string name="dpi_size_medium">Sedang</string>
<string name="dpi_size_large">Besar</string>
<string name="dpi_size_extra_large">Jumbo</string>
<string name="dpi_size_custom">Kustomisasi</string>
<string name="dpi_apply_settings">Terapkan setelan DPI</string>
<string name="dpi_confirm_title">Konfirmasi perubahan DPI</string>
<string name="dpi_confirm_message">Apa kamu yakin ingin merubah DPI aplikasi dari %1$d ke %2$d?</string>
<string name="dpi_confirm_summary">Aplikasi membutuhkan restar untuk menerapkan opsi DPI ini, perubahan ini tidak mengganggu DPI sistem</string>
<string name="dpi_applied_success">DPI telah di rubah ke %1$d, efektif setelah aplikasi di restar</string>
<!-- Language settings related strings -->
<string name="language_setting">Bahasa Aplikasi</string>
<string name="language_follow_system">Mengikuti sistem</string>
<string name="language_changed">Bahasa dirubah, mulai ulang aplikasi untuk menerapkan</string>
<!-- Flash related -->
<!-- 分类相关 -->
<!-- 排序相关 -->
<!-- 状态相关 -->
<!-- 标签相关 -->
<!-- BottomSheet相关 -->
<!-- SuSFS Configuration -->
<!-- SuSFS Reset Confirmation -->
<!-- SuSFS Toast Messages -->
<!-- SuSFS Settings Item -->
<!-- 开机自启动相关 -->
<!-- SuSFS Tab Titles -->
<!-- SuSFS Path Management -->
<!-- SuSFS Umount Mode -->
<!-- SuSFS Run Umount -->
<!-- SuSFS Reset Categories -->
<!-- SuSFS Path Settings -->
<!-- SuSFS Enabled Features -->
<!-- Feature Labels -->
<!-- 可切换状态 -->
<!-- Settings related strings -->
<string name="show_more_module_info">Tampilkan info modul lainnya</string>
<string name="show_more_module_info_summary">Pajang info modul tambahan seperti URL pembaruan JSON</string>
<!-- SuSFS 自启动相关字符串 -->
<!-- SuSFS Kstat相关字符串 -->
<!-- SuSFS Mount Hiding Control Related Strings -->
<!-- 备份和还原相关字符串 -->
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Non installato</string> <string name="home_not_installed">Non installato</string>
<string name="home_click_to_install">Clicca per installare</string> <string name="home_click_to_install">Clicca per installare</string>
<string name="home_working">In esecuzione</string> <string name="home_working">In esecuzione</string>
<string name="home_working_version">Versione: %d</string> <string name="home_working_version">Versione: %s</string>
<string name="home_unsupported">Non supportato</string> <string name="home_unsupported">Non supportato</string>
<string name="home_unsupported_reason">KernelSU ora supporta solo i kernel GKI</string> <string name="home_unsupported_reason">KernelSU ora supporta solo i kernel GKI</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Contesto SELinux</string> <string name="profile_selinux_context">Contesto SELinux</string>
<string name="profile_umount_modules">Scollega moduli</string> <string name="profile_umount_modules">Scollega moduli</string>
<string name="failed_to_update_app_profile">Aggiornamento App Profile per %s fallito</string> <string name="failed_to_update_app_profile">Aggiornamento App Profile per %s fallito</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Scollega moduli da default</string> <string name="settings_umount_modules_default">Scollega moduli da default</string>
<string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string> <string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -39,7 +39,7 @@
<string name="module">מודולים</string> <string name="module">מודולים</string>
<string name="module_author">יוצר</string> <string name="module_author">יוצר</string>
<string name="about">אודות</string> <string name="about">אודות</string>
<string name="home_working_version">גרסה: %d</string> <string name="home_working_version">גרסה: %s</string>
<string name="reboot">הפעלה מחדש</string> <string name="reboot">הפעלה מחדש</string>
<string name="home_unsupported_reason">KernelSU תומך רק בליבת GKI כעת</string> <string name="home_unsupported_reason">KernelSU תומך רק בליבת GKI כעת</string>
<string name="home_selinux_status">סטטוס SELinux</string> <string name="home_selinux_status">סטטוס SELinux</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">未インストール</string> <string name="home_not_installed">未インストール</string>
<string name="home_click_to_install">タップでインストール</string> <string name="home_click_to_install">タップでインストール</string>
<string name="home_working">動作中</string> <string name="home_working">動作中</string>
<string name="home_working_version">バージョン: %d</string> <string name="home_working_version">バージョン: %s</string>
<string name="home_unsupported">非対応</string> <string name="home_unsupported">非対応</string>
<string name="home_unsupported_reason">カーネルの KernelSU ドライバが未検出です。カーネルが間違ってませんか?</string> <string name="home_unsupported_reason">カーネルの KernelSU ドライバが未検出です。カーネルが間違ってませんか?</string>
<string name="home_kernel">カーネルのバージョン</string> <string name="home_kernel">カーネルのバージョン</string>
@@ -12,6 +12,8 @@
<string name="home_manager_version">マネージャーのバージョン</string> <string name="home_manager_version">マネージャーのバージョン</string>
<string name="home_selinux_status">SELinux のステータス</string> <string name="home_selinux_status">SELinux のステータス</string>
<string name="selinux_status_disabled">無効</string> <string name="selinux_status_disabled">無効</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">不明</string> <string name="selinux_status_unknown">不明</string>
<string name="superuser">スーパーユーザー</string> <string name="superuser">スーパーユーザー</string>
<string name="module_failed_to_enable">%s モジュールを ON にできませんでした</string> <string name="module_failed_to_enable">%s モジュールを ON にできませんでした</string>
@@ -48,7 +50,7 @@
<string name="home_click_to_learn_kernelsu">KernelSU のインストール方法やモジュールの使い方を学習できます。</string> <string name="home_click_to_learn_kernelsu">KernelSU のインストール方法やモジュールの使い方を学習できます。</string>
<string name="home_support_title">支援する</string> <string name="home_support_title">支援する</string>
<string name="home_support_content">KernelSU は今後も無料でオープンソースです。ですが、寄付をして頂けると開発者への貢献になります。</string> <string name="home_support_content">KernelSU は今後も無料でオープンソースです。ですが、寄付をして頂けると開発者への貢献になります。</string>
<string name="about_source_code"><![CDATA[ソースコードは %1$s で確認できます<br/>%2$s チャンネルにご参加ください。]]></string> <string name="about_source_code"><![CDATA[ソースコードは %1$s で確認できます<br/>%2$s チャンネルにご参加ください<br/><br/>アニメキャラのスタンプ付き画像の著作権は%3$sにあり、画像の Brand Intellectual Property は%4$sによって所有され。これらのファイルを使用する前に、%5$sを遵守することに加えて、アートコンテンツを使用するために前の 2 人の作者から許可を得る必要があります。]]></string>
<string name="profile_default">デフォルト</string> <string name="profile_default">デフォルト</string>
<string name="profile_template">テンプレート</string> <string name="profile_template">テンプレート</string>
<string name="profile_custom">カスタム</string> <string name="profile_custom">カスタム</string>
@@ -58,7 +60,7 @@
<string name="profile_selinux_context">SELinux コンテキスト</string> <string name="profile_selinux_context">SELinux コンテキスト</string>
<string name="profile_umount_modules">モジュールのアンマウント</string> <string name="profile_umount_modules">モジュールのアンマウント</string>
<string name="failed_to_update_app_profile">%s のアプリのプロファイルの更新をできませでした</string> <string name="failed_to_update_app_profile">%s のアプリのプロファイルの更新をできませでした</string>
<string name="require_kernel_version" formatted="false">現在の KernelSU のバージョン %d は低すぎるため、マネージャーは正常に動作しません。バージョン %d 以上に更新してください!</string> <string name="require_kernel_version" formatted="false">現在の KernelSU のバージョン %s は低すぎるため、マネージャーは正常に動作しません。バージョン %s 以上に更新してください!</string>
<string name="settings_umount_modules_default">デフォルトでモジュールのマウントを解除する</string> <string name="settings_umount_modules_default">デフォルトでモジュールのマウントを解除する</string>
<string name="settings_umount_modules_default_summary">アプリプロファイルの「モジュールのアンマウント」の共通となるデフォルト値です。 有効にすると、プロファイルセットを持たないアプリのシステムに対するすべてのモジュールの変更が削除されます。</string> <string name="settings_umount_modules_default_summary">アプリプロファイルの「モジュールのアンマウント」の共通となるデフォルト値です。 有効にすると、プロファイルセットを持たないアプリのシステムに対するすべてのモジュールの変更が削除されます。</string>
<string name="settings_susfs_toggle">kprobe フックを無効化</string> <string name="settings_susfs_toggle">kprobe フックを無効化</string>
@@ -78,6 +80,7 @@
<string name="settings_profile_template_summary">アプリプロファイルのローカルおよびオンラインテンプレートを管理します。</string> <string name="settings_profile_template_summary">アプリプロファイルのローカルおよびオンラインテンプレートを管理します。</string>
<string name="app_profile_template_create">テンプレートの作成</string> <string name="app_profile_template_create">テンプレートの作成</string>
<string name="app_profile_template_edit">テンプレートの編集</string> <string name="app_profile_template_edit">テンプレートの編集</string>
<string name="app_profile_template_id">ID</string>
<string name="app_profile_template_id_invalid">無効なテンプレート ID</string> <string name="app_profile_template_id_invalid">無効なテンプレート ID</string>
<string name="app_profile_template_name">名前</string> <string name="app_profile_template_name">名前</string>
<string name="app_profile_template_description">説明</string> <string name="app_profile_template_description">説明</string>
@@ -110,6 +113,7 @@
\n続行しますか</string> \n続行しますか</string>
<string name="install_next">次へ</string> <string name="install_next">次へ</string>
<string name="select_file_tip">%1$s のパーティションイメージを推奨します。</string> <string name="select_file_tip">%1$s のパーティションイメージを推奨します。</string>
<string name="select_file_tip_vendor">(不安定)</string>
<string name="select_kmi">KMI を選択してください</string> <string name="select_kmi">KMI を選択してください</string>
<string name="settings_uninstall">アンインストール</string> <string name="settings_uninstall">アンインストール</string>
<string name="settings_uninstall_temporary">一時的にアンインストールする</string> <string name="settings_uninstall_temporary">一時的にアンインストールする</string>
@@ -164,6 +168,7 @@
<string name="settings_disable_su_summary">su コマンドを使用してアプリが root 権限を取得する動作を一時的に無効化します (既存の root プロセスは影響を受けません)。</string> <string name="settings_disable_su_summary">su コマンドを使用してアプリが root 権限を取得する動作を一時的に無効化します (既存の root プロセスは影響を受けません)。</string>
<string name="module_install_multiple_confirm_with_names">%1$d 個のモジュールをインストールしてもよろしいですか?\n\n%2$s</string> <string name="module_install_multiple_confirm_with_names">%1$d 個のモジュールをインストールしてもよろしいですか?\n\n%2$s</string>
<string name="more_settings">その他の設定</string> <string name="more_settings">その他の設定</string>
<string name="selinux">SELinux</string>
<string name="selinux_enabled">有効</string> <string name="selinux_enabled">有効</string>
<string name="selinux_disabled">無効</string> <string name="selinux_disabled">無効</string>
<string name="simple_mode">シンプルモード</string> <string name="simple_mode">シンプルモード</string>
@@ -201,6 +206,7 @@
<string name="yes">はい</string> <string name="yes">はい</string>
<string name="no">いいえ</string> <string name="no">いいえ</string>
<string name="failed_reboot">再起動に失敗しました</string> <string name="failed_reboot">再起動に失敗しました</string>
<string name="kpm_title">KPM</string>
<string name="kpm_empty">カーネルモジュールは現在インストールされていません</string> <string name="kpm_empty">カーネルモジュールは現在インストールされていません</string>
<string name="kpm_version">バージョン</string> <string name="kpm_version">バージョン</string>
<string name="kpm_author">作者</string> <string name="kpm_author">作者</string>
@@ -321,6 +327,7 @@
<string name="kernel_flashing">カーネルをフラッシュ中</string> <string name="kernel_flashing">カーネルをフラッシュ中</string>
<!-- 分类相关 --> <!-- 分类相关 -->
<string name="category_all_apps">すべて</string> <string name="category_all_apps">すべて</string>
<string name="category_root_apps">Root</string>
<string name="category_custom_apps">カスタム</string> <string name="category_custom_apps">カスタム</string>
<string name="category_default_apps">デフォルト</string> <string name="category_default_apps">デフォルト</string>
<!-- 排序相关 --> <!-- 排序相关 -->
@@ -362,7 +369,6 @@
<string name="susfs_apply">適用</string> <string name="susfs_apply">適用</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">リセットを確認</string> <string name="susfs_reset_confirm_title">リセットを確認</string>
<string name="susfs_reset_confirm">リセットを確認</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">ksu_susfs ファイルが見つかりません</string> <string name="susfs_binary_not_found">ksu_susfs ファイルが見つかりません</string>
<string name="susfs_command_failed">SuSFS コマンドの実行に失敗しました</string> <string name="susfs_command_failed">SuSFS コマンドの実行に失敗しました</string>
@@ -385,12 +391,12 @@
<string name="susfs_tab_try_umount">アンマウントを試す</string> <string name="susfs_tab_try_umount">アンマウントを試す</string>
<string name="susfs_tab_path_settings">パスの設定</string> <string name="susfs_tab_path_settings">パスの設定</string>
<string name="susfs_tab_enabled_features">有効な機能のステータス</string> <string name="susfs_tab_enabled_features">有効な機能のステータス</string>
<!-- SuSFS Dialog Actions -->
<string name="susfs_add">追加</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">SUS パスを追加</string> <string name="susfs_add_sus_path">SUS パスを追加</string>
<string name="susfs_add_sus_mount">SUS マウントを追加</string> <string name="susfs_add_sus_mount">SUS マウントを追加</string>
<string name="susfs_add_try_umount">アンマウントを試すを追加</string> <string name="susfs_add_try_umount">アンマウントを試すを追加</string>
<string name="susfs_sus_path_added_success">SUS パスが正常に追加されました</string>
<string name="susfs_path_not_found_error">パスが見つかりません</string>
<string name="susfs_path_label">パス</string> <string name="susfs_path_label">パス</string>
<string name="susfs_mount_path_label">マウントのパス</string> <string name="susfs_mount_path_label">マウントのパス</string>
<string name="susfs_path_placeholder">例 : /system/addon.d</string> <string name="susfs_path_placeholder">例 : /system/addon.d</string>
@@ -416,6 +422,7 @@
<string name="susfs_reset_mounts_message">すべての SUS マウントの構成が消去されます。続行してもよろしいですか?</string> <string name="susfs_reset_mounts_message">すべての SUS マウントの構成が消去されます。続行してもよろしいですか?</string>
<string name="susfs_reset_umounts_title">リセットしてアンマウントを試す</string> <string name="susfs_reset_umounts_title">リセットしてアンマウントを試す</string>
<string name="susfs_reset_umounts_message">すべてのアンマウント構成がリセットされます。続行してもよろしいですか?</string> <string name="susfs_reset_umounts_message">すべてのアンマウント構成がリセットされます。続行してもよろしいですか?</string>
<string name="susfs_reset_path_title">パスの設定をリセット</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Android データパス</string> <string name="susfs_android_data_path_label">Android データパス</string>
<string name="susfs_sdcard_path_label">SD カードのパス</string> <string name="susfs_sdcard_path_label">SD カードのパス</string>
@@ -453,6 +460,131 @@
<!-- Settings related strings --> <!-- Settings related strings -->
<string name="show_more_module_info">モジュール情報の詳細を表示</string> <string name="show_more_module_info">モジュール情報の詳細を表示</string>
<string name="show_more_module_info_summary">更新用 JSON の URL など追加の情報を表示します。</string> <string name="show_more_module_info_summary">更新用 JSON の URL など追加の情報を表示します。</string>
<string name="susfs_execution_location_label">実行先</string>
<string name="susfs_current_execution_location">現在の実行先: %s</string>
<string name="susfs_execution_location_service">サービス</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">システムサービスの開始後に実行</string>
<string name="susfs_execution_location_post_fs_data_description">ファイルシステムのマウント後にシステムが完全に起動する前に実行をすることで、ブートループが発生する可能性があります。</string>
<string name="susfs_slot_info_title">スロット情報</string>
<string name="susfs_slot_info_description">現在のブートスロット情報の表示と値のコピーをします。</string>
<string name="susfs_current_active_slot">現在のアクティブスロット: %s</string>
<string name="susfs_slot_uname">Uname: %s</string>
<string name="susfs_slot_build_time">ビルド日時: %s</string>
<string name="susfs_slot_current_badge">現在</string>
<string name="susfs_slot_use_uname">Uname を使用する</string>
<string name="susfs_slot_use_build_time">ビルド日時を使用する</string>
<string name="susfs_slot_info_unavailable">スロット情報を取得できません</string>
<!-- SuSFS 自启动相关字符串 --> <!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">SuSFS 自動起動モジュールが有効、モジュールのパス: %s</string>
<string name="susfs_autostart_disabled_success">SuSFS 自動起動モジュールが無効</string>
<!-- SuSFS Kstat相关字符串 --> <!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Kstat の構成</string>
<string name="kstat_static_config_added">Kstat の静的構成を追加しました: %1$s</string>
<string name="kstat_config_removed">Kstat の構成を削除しました: %1$s</string>
<string name="kstat_path_added">Kstat パスを追加しました: %1$s</string>
<string name="kstat_path_removed">Kstat パスを削除しました: %1$s</string>
<string name="kstat_updated">Kstat が更新されました: %1$s</string>
<string name="kstat_full_clone_updated">Kstat のフルクローンが更新されました: %1$s</string>
<string name="add_kstat_statically_title">Kstat 静的構成を追加</string>
<string name="file_or_directory_path_label">ファイルまたはディレクトリのパス</string>
<string name="hint_use_default_value">ヒント: オリジナルの値を使用するには「default」を使用します</string>
<string name="add_kstat_path_title">Kstat のパスを追加</string>
<string name="add">追加</string>
<string name="reset_kstat_config_title">Kstat の構成をリセット</string>
<string name="reset_kstat_config_message">すべての Kstat の構成を消去しますか?この操作は元に戻せません。</string>
<string name="kstat_config_description_title">Kstat の構成の説明</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_statically: ファイル、ディレクトリの静的な状態情報</string>
<string name="kstat_config_description_add">• add_sus_kstat: バインドマウント前にパスを追加して元の状態情報を保存します</string>
<string name="kstat_config_description_update">• update_sus_kstat: ターゲットとなる ino を更新、サイズとブロックは変更しません</string>
<string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: ino のみ更新、他の値はそのままにします</string>
<string name="static_kstat_config">Kstat の静的構成</string>
<string name="kstat_path_management">Kstat パスの管理</string>
<string name="no_kstat_config_message">Kstat の構成が未設定です。上のボタンをタップで追加します。</string>
<!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">SUS マウントの非表示制御</string>
<string name="susfs_hide_mounts_control_description">プロセスの SUS マウントを非表示する動作を制御します。</string>
<string name="susfs_hide_mounts_for_all_procs_label">すべてのプロセスで SUS マウントを非表示</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">有効化すると SUS マウントは KSU プロセスを含むすべてのプロセスから非表示になります。</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">無効化すると SUS マウントは非 KSU プロセスからのみ非表示になり、KSU プロセスはマウントを見ることができます。</string>
<string name="susfs_hide_mounts_all_enabled">すべてのプロセスで SUS マウントの非表示を有効化しました</string>
<string name="susfs_hide_mounts_all_disabled">すべてのプロセスで SUS マウントの非表示を無効化しました</string>
<string name="susfs_hide_mounts_recommendation">画面のロック解除後または service.sh または boot-completed.sh の段階で無効に設定することを推奨します。これにより、KSU プロセスによってマウントされたマウントに依存する一部の root 化されたアプリの問題が解決されるはずです。</string>
<string name="susfs_hide_mounts_current_setting">現在の設定: %s</string>
<string name="susfs_hide_mounts_setting_all">すべてのプロセスを非表示</string>
<string name="susfs_hide_mounts_setting_non_ksu">非 KSU プロセスのみ非表示</string>
<string name="susfs_run">実行</string>
<string name="kernel_simple_kernel">簡潔モードなカーネル バージョン</string>
<string name="kernel_simple_kernel_summary">SukiSU のカーネル バージョンによって表示されるクリーンモードを有効または無効します。</string>
<string name="susfs_android_data_path_set">Android のデータパスが設定されました: %s</string>
<string name="susfs_sdcard_path_set">SD カードのパスは次のように設定済みです: %s</string>
<string name="susfs_path_setup_warning">パスの設定は完全に成功しない可能性がありますが、SUS パスは引き続き追加されます。</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">バックアップ</string>
<string name="susfs_backup_description">SuSFS のすべての設定のバックアップを作成します。バックアップファイルは「すべての設定、パス、構成」が含まれます。</string>
<string name="susfs_backup_create">バックアップを作成</string>
<string name="susfs_backup_success">バックアップの作成に成功しました: %s</string>
<string name="susfs_backup_failed">バックアップの作成に失敗しました: %s</string>
<string name="susfs_backup_file_not_found">バックアップファイルが見つかりません</string>
<string name="susfs_backup_invalid_format">無効なバックアップファイル形式</string>
<string name="susfs_backup_version_mismatch">バックアップバージョンが一致しませんが、復元を試みます。</string>
<string name="susfs_restore_title">復元</string>
<string name="susfs_restore_description">SuSFS の構成をバックアップファイルから復元します。これにより、現在の設定がすべて上書きされます。</string>
<string name="susfs_restore_select_file">バックアップファイルを選択</string>
<string name="susfs_restore_success" formatted="false">デバイス: %s から「%s」に作成されたバックアップから構成が正常に復元されました。</string>
<string name="susfs_restore_failed">復元に失敗しました: %s</string>
<string name="susfs_restore_confirm_title">復元を確認</string>
<string name="susfs_restore_confirm_description">これにより現在の SuSFS 構成がすべて上書きされます。続行してもよろしいですか?</string>
<string name="susfs_restore_confirm">復元</string>
<string name="susfs_backup_info_date">バックアップ日時: %s</string>
<string name="susfs_backup_info_device">デバイス: %s</string>
<string name="susfs_backup_info_version">バージョン: %s</string>
<string name="hide_bl_script">BL スクリプトを非表示</string>
<string name="hide_bl_script_description">ブートローダーのロック解除ステータスを非表示にするスクリプトを有効化します。</string>
<string name="cleanup_residue">残骸をクリーンアップ</string>
<string name="cleanup_residue_description">様々なモジュールや残骸となったツールのファイルとディレクトリをクリーンアップします (誤って削除すると損失や起動の失敗に繋がる可能性があるため、注意して使用してください)</string>
<string name="susfs_edit_sus_path">SUS のパスを編集</string>
<string name="susfs_edit_sus_mount">SUS マウントを編集</string>
<string name="susfs_edit_try_umount">アンマウントを試すを編集</string>
<string name="edit_kstat_statically_title">Kstat 静的構成を編集</string>
<string name="edit_kstat_path_title">Kstat のパスを編集</string>
<string name="susfs_save">保存</string>
<string name="edit">編集</string>
<string name="delete">消去</string>
<string name="update">更新</string>
<string name="kstat_config_updated">Kstat の構成を更新</string>
<string name="kstat_path_updated">Kstat のパスを更新</string>
<string name="susfs_update_full_clone">フルクローンの SuSFS を更新</string>
<string name="umount_zygote_iso_service">Zygote 分離サービスをアンマウント</string>
<string name="umount_zygote_iso_service_description">このオプションを有効化すると、システムの起動時に Zygote 分離サービスのマウントポイントがアンマウントされます。</string>
<string name="umount_zygote_iso_service_enabled">Zygote 分離サービスのアンマウントが有効です</string>
<string name="umount_zygote_iso_service_disabled">Zygote 分離サービスのアンマウントが無効です</string>
<string name="app_paths_section">アプリのパス</string>
<string name="other_paths_section">その他のパス</string>
<string name="add_custom_path">その他</string>
<string name="add_app_path">アプリ</string>
<string name="susfs_add_app_path">追加のアプリパス</string>
<string name="search_apps">アプリを検索</string>
<string name="selected_apps_count">%1$d 個のアプリを選択済み</string>
<string name="already_added_apps_count">%1$d 個のアプリを追加済み</string>
<string name="all_apps_already_added">すべてのアプリが追加されました</string>
<string name="dynamic_sign_title">動的な署名の構成</string>
<string name="dynamic_sign_enabled_summary">有効 (サイズ: %s)</string>
<string name="dynamic_sign_disabled">無効</string>
<string name="enable_dynamic_sign">動的な署名を有効化</string>
<string name="signature_size">署名のサイズ</string>
<string name="signature_hash">署名のハッシュ</string>
<string name="hash_must_be_64_chars">ハッシュは 64 桁の 16 進数の文字列でなければなりません。</string>
<string name="dynamic_sign_set_success">動的な署名の構成が正常に設定されました</string>
<string name="dynamic_sign_set_failed">動的な署名の構成の設定に失敗しました</string>
<string name="invalid_sign_config">無効な署名の構成</string>
<string name="dynamic_sign_disabled_success">動的な署名が無効です</string>
<string name="dynamic_sign_clear_failed">動的な署名の消去に失敗しました</string>
<string name="dynamic_signature">動的</string>
<string name="signature_index">署名 %1$d</string>
<string name="unknown_signature">不明</string>
<string name="multi_manager_list">有効なマネージャー</string>
<string name="no_active_manager">有効なマネージャーがありません</string>
<string name="default_signature">SukiSU</string>
<string name="home_zygisk_implement">Zygisk を実装</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Not installed</string> <string name="home_not_installed">Not installed</string>
<string name="home_click_to_install">Click to install</string> <string name="home_click_to_install">Click to install</string>
<string name="home_working">ಕೆಲಸ ಮಾಡುತ್ತಿದೆ</string> <string name="home_working">ಕೆಲಸ ಮಾಡುತ್ತಿದೆ</string>
<string name="home_working_version">ವರ್ಷನ್: %d</string> <string name="home_working_version">ವರ್ಷನ್: %s</string>
<string name="home_unsupported">ಬೆಂಬಲಿತವಾಗಿಲ್ಲ</string> <string name="home_unsupported">ಬೆಂಬಲಿತವಾಗಿಲ್ಲ</string>
<string name="home_unsupported_reason">KernelSU ಈಗ GKI ಕರ್ನಲ್‌ಗಳನ್ನು ಮಾತ್ರ ಬೆಂಬಲಿಸುತ್ತದೆ</string> <string name="home_unsupported_reason">KernelSU ಈಗ GKI ಕರ್ನಲ್‌ಗಳನ್ನು ಮಾತ್ರ ಬೆಂಬಲಿಸುತ್ತದೆ</string>
<string name="home_kernel">ಕರ್ನಲ್</string> <string name="home_kernel">ಕರ್ನಲ್</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux ಸಂದರ್ಭ</string> <string name="profile_selinux_context">SELinux ಸಂದರ್ಭ</string>
<string name="profile_umount_modules">Umount ಮಾಡ್ಯೂಲ್‌ಗಳು</string> <string name="profile_umount_modules">Umount ಮಾಡ್ಯೂಲ್‌ಗಳು</string>
<string name="failed_to_update_app_profile">%s ಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ</string> <string name="failed_to_update_app_profile">%s ಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">ಡೀಫಾಲ್ಟ್ ಆಗಿ Umount ಮಾಡ್ಯೂಲ್</string> <string name="settings_umount_modules_default">ಡೀಫಾಲ್ಟ್ ಆಗಿ Umount ಮಾಡ್ಯೂಲ್</string>
<string name="settings_umount_modules_default_summary">ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್‌ಗಳಲ್ಲಿ \"Umount ಮಾಡ್ಯೂಲ್\" ಗಾಗಿ ಜಾಗತಿಕ ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯ. ಸಕ್ರಿಯಗೊಳಿಸಿದರೆ, ಪ್ರೊಫೈಲ್ ಸೆಟ್ ಅನ್ನು ಹೊಂದಿರದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಸಿಸ್ಟಮ್‌ಗೆ ಎಲ್ಲಾ ಮಾಡ್ಯೂಲ್ ಮಾರ್ಪಾಡುಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ.</string> <string name="settings_umount_modules_default_summary">ಅಪ್ಲಿಕೇಶನ್ ಪ್ರೊಫೈಲ್‌ಗಳಲ್ಲಿ \"Umount ಮಾಡ್ಯೂಲ್\" ಗಾಗಿ ಜಾಗತಿಕ ಡೀಫಾಲ್ಟ್ ಮೌಲ್ಯ. ಸಕ್ರಿಯಗೊಳಿಸಿದರೆ, ಪ್ರೊಫೈಲ್ ಸೆಟ್ ಅನ್ನು ಹೊಂದಿರದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಸಿಸ್ಟಮ್‌ಗೆ ಎಲ್ಲಾ ಮಾಡ್ಯೂಲ್ ಮಾರ್ಪಾಡುಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">설치되지 않음</string> <string name="home_not_installed">설치되지 않음</string>
<string name="home_click_to_install">이 곳을 눌러 설치하기</string> <string name="home_click_to_install">이 곳을 눌러 설치하기</string>
<string name="home_working">정상 작동 중</string> <string name="home_working">정상 작동 중</string>
<string name="home_working_version">버전: %d</string> <string name="home_working_version">버전: %s</string>
<string name="home_unsupported">지원되지 않음</string> <string name="home_unsupported">지원되지 않음</string>
<string name="home_unsupported_reason">KernelSU는 현재 GKI 커널만 지원합니다</string> <string name="home_unsupported_reason">KernelSU는 현재 GKI 커널만 지원합니다</string>
<string name="home_kernel">커널</string> <string name="home_kernel">커널</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux 컨텍스트</string> <string name="profile_selinux_context">SELinux 컨텍스트</string>
<string name="profile_umount_modules">모듈 사용 해제</string> <string name="profile_umount_modules">모듈 사용 해제</string>
<string name="failed_to_update_app_profile">%s에 대한 앱 프로필 업데이트 실패</string> <string name="failed_to_update_app_profile">%s에 대한 앱 프로필 업데이트 실패</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">기본값으로 모듈 사용 해제</string> <string name="settings_umount_modules_default">기본값으로 모듈 사용 해제</string>
<string name="settings_umount_modules_default_summary">앱 프로필 메뉴의 \"모듈 마운트 해제\" 설정에 대한 전역 기본값을 설정합니다. 활성화 시, 개별 프로필이 설정되지 않은 앱은 시스템에 대한 모듈의 모든 수정사항이 적용되지 않습니다.</string> <string name="settings_umount_modules_default_summary">앱 프로필 메뉴의 \"모듈 마운트 해제\" 설정에 대한 전역 기본값을 설정합니다. 활성화 시, 개별 프로필이 설정되지 않은 앱은 시스템에 대한 모듈의 모든 수정사항이 적용되지 않습니다.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Neįdiegta</string> <string name="home_not_installed">Neįdiegta</string>
<string name="home_click_to_install">Spustelėkite norėdami įdiegti</string> <string name="home_click_to_install">Spustelėkite norėdami įdiegti</string>
<string name="home_working">Veikia</string> <string name="home_working">Veikia</string>
<string name="home_working_version">Versija: %d</string> <string name="home_working_version">Versija: %s</string>
<string name="home_unsupported">Nepalaikoma</string> <string name="home_unsupported">Nepalaikoma</string>
<string name="home_unsupported_reason">KernelSU dabar palaiko tik GKI branduolius</string> <string name="home_unsupported_reason">KernelSU dabar palaiko tik GKI branduolius</string>
<string name="home_kernel">Branduolys</string> <string name="home_kernel">Branduolys</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontekstas</string> <string name="profile_selinux_context">SELinux kontekstas</string>
<string name="profile_umount_modules">Atjungti modulius</string> <string name="profile_umount_modules">Atjungti modulius</string>
<string name="failed_to_update_app_profile">Nepavyko atnaujinti programos profilio %s</string> <string name="failed_to_update_app_profile">Nepavyko atnaujinti programos profilio %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Atjungti modulius pagal numatytuosius parametrus</string> <string name="settings_umount_modules_default">Atjungti modulius pagal numatytuosius parametrus</string>
<string name="settings_umount_modules_default_summary">Visuotinė numatytoji „Modulių atjungimo“ reikšmė programų profiliuose. Jei įjungta, ji pašalins visus sistemos modulio pakeitimus programoms, kurios neturi profilio.</string> <string name="settings_umount_modules_default_summary">Visuotinė numatytoji „Modulių atjungimo“ reikšmė programų profiliuose. Jei įjungta, ji pašalins visus sistemos modulio pakeitimus programoms, kurios neturi profilio.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nav ieinstalēts</string> <string name="home_not_installed">Nav ieinstalēts</string>
<string name="home_click_to_install">Noklikšķiniet, lai instalētu</string> <string name="home_click_to_install">Noklikšķiniet, lai instalētu</string>
<string name="home_working">Darbojas</string> <string name="home_working">Darbojas</string>
<string name="home_working_version">Versija: %d</string> <string name="home_working_version">Versija: %s</string>
<string name="home_unsupported">Neatbalstīts</string> <string name="home_unsupported">Neatbalstīts</string>
<string name="home_unsupported_reason">KernelSU atbalsta tikai GKI kodolus</string> <string name="home_unsupported_reason">KernelSU atbalsta tikai GKI kodolus</string>
<string name="home_kernel">Kodols</string> <string name="home_kernel">Kodols</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux konteksts</string> <string name="profile_selinux_context">SELinux konteksts</string>
<string name="profile_umount_modules">Atvienot moduļus</string> <string name="profile_umount_modules">Atvienot moduļus</string>
<string name="failed_to_update_app_profile">Neizdevās atjaunināt lietotnes profilu %s</string> <string name="failed_to_update_app_profile">Neizdevās atjaunināt lietotnes profilu %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Pēc noklusējuma atvienot moduļus</string> <string name="settings_umount_modules_default">Pēc noklusējuma atvienot moduļus</string>
<string name="settings_umount_modules_default_summary">Globālā noklusējuma vērtība vienumam “Atvienot moduļus” lietotņu profilos. Ja tas ir iespējots, lietojumprogrammām, kurām nav iestatīts profils, tiks noņemtas visas sistēmas moduļu modifikācijas.</string> <string name="settings_umount_modules_default_summary">Globālā noklusējuma vērtība vienumam “Atvienot moduļus” lietotņu profilos. Ja tas ir iespējots, lietojumprogrammām, kurām nav iestatīts profils, tiks noņemtas visas sistēmas moduļu modifikācijas.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">इंस्टॉल केले नाही</string> <string name="home_not_installed">इंस्टॉल केले नाही</string>
<string name="home_click_to_install">इंस्टॉल साठी क्लिक करा</string> <string name="home_click_to_install">इंस्टॉल साठी क्लिक करा</string>
<string name="home_working">कार्यरत</string> <string name="home_working">कार्यरत</string>
<string name="home_working_version">आवृत्ती: %d</string> <string name="home_working_version">आवृत्ती: %s</string>
<string name="home_unsupported">असमर्थित</string> <string name="home_unsupported">असमर्थित</string>
<string name="home_unsupported_reason">KernelSU आता फक्त GKI कर्नलचे समर्थन करते</string> <string name="home_unsupported_reason">KernelSU आता फक्त GKI कर्नलचे समर्थन करते</string>
<string name="home_kernel">कर्नल</string> <string name="home_kernel">कर्नल</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux संदर्भ</string> <string name="profile_selinux_context">SELinux संदर्भ</string>
<string name="profile_umount_modules">उमाउंट मॉड्यूल्स</string> <string name="profile_umount_modules">उमाउंट मॉड्यूल्स</string>
<string name="failed_to_update_app_profile">%s साठी अॅप प्रोफाइल अपडेट करण्यात अयशस्वी</string> <string name="failed_to_update_app_profile">%s साठी अॅप प्रोफाइल अपडेट करण्यात अयशस्वी</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">डीफॉल्टनुसार मॉड्यूल्स उमाउंट करा</string> <string name="settings_umount_modules_default">डीफॉल्टनुसार मॉड्यूल्स उमाउंट करा</string>
<string name="settings_umount_modules_default_summary">अॅप प्रोफाइलमधील \"उमाउंट मॉड्यूल्स\" साठी जागतिक डीफॉल्ट मूल्य. सक्षम असल्यास, ते प्रोफाइल सेट नसलेल्या ॲप्लिकेशनचे सिस्टममधील सर्व मॉड्यूल बदल काढून टाकेल.</string> <string name="settings_umount_modules_default_summary">अॅप प्रोफाइलमधील \"उमाउंट मॉड्यूल्स\" साठी जागतिक डीफॉल्ट मूल्य. सक्षम असल्यास, ते प्रोफाइल सेट नसलेल्या ॲप्लिकेशनचे सिस्टममधील सर्व मॉड्यूल बदल काढून टाकेल.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Tidak terpasang</string> <string name="home_not_installed">Tidak terpasang</string>
<string name="home_click_to_install">Tekan untuk memasang</string> <string name="home_click_to_install">Tekan untuk memasang</string>
<string name="home_working">Berjalan</string> <string name="home_working">Berjalan</string>
<string name="home_working_version">Versi: %d</string> <string name="home_working_version">Versi: %s</string>
<string name="home_unsupported">Tidak Disokong</string> <string name="home_unsupported">Tidak Disokong</string>
<string name="home_unsupported_reason">KernelSU ketika ini hanya menyokong kernel GKI</string> <string name="home_unsupported_reason">KernelSU ketika ini hanya menyokong kernel GKI</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux context</string> <string name="profile_selinux_context">SELinux context</string>
<string name="profile_umount_modules">Umount modules</string> <string name="profile_umount_modules">Umount modules</string>
<string name="failed_to_update_app_profile">Failed to update App Profile for %s</string> <string name="failed_to_update_app_profile">Failed to update App Profile for %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount modules by default</string> <string name="settings_umount_modules_default">Umount modules by default</string>
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string> <string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Niet geïnstalleerd</string> <string name="home_not_installed">Niet geïnstalleerd</string>
<string name="home_click_to_install">Klik om te installeren</string> <string name="home_click_to_install">Klik om te installeren</string>
<string name="home_working">Werkend</string> <string name="home_working">Werkend</string>
<string name="home_working_version">Versie: %d</string> <string name="home_working_version">Versie: %s</string>
<string name="home_unsupported">Niet ondersteund</string> <string name="home_unsupported">Niet ondersteund</string>
<string name="home_unsupported_reason">KernelSU ondersteunt alleen GKI kernels</string> <string name="home_unsupported_reason">KernelSU ondersteunt alleen GKI kernels</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux context</string> <string name="profile_selinux_context">SELinux context</string>
<string name="profile_umount_modules">Ontkoppel modules</string> <string name="profile_umount_modules">Ontkoppel modules</string>
<string name="failed_to_update_app_profile">Mislukt om App Profiel te updaten voor %s</string> <string name="failed_to_update_app_profile">Mislukt om App Profiel te updaten voor %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Ontkoppel standaard de modules</string> <string name="settings_umount_modules_default">Ontkoppel standaard de modules</string>
<string name="settings_umount_modules_default_summary">De globale standaardwaarde voor \"Umount modules\" in App Profile. Als dit is ingeschakeld, worden alle modulewijzigingen in het systeem verwijderd voor apps waarvoor geen profiel is ingesteld.</string> <string name="settings_umount_modules_default_summary">De globale standaardwaarde voor \"Umount modules\" in App Profile. Als dit is ingeschakeld, worden alle modulewijzigingen in het systeem verwijderd voor apps waarvoor geen profiel is ingesteld.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nie zainstalowano</string> <string name="home_not_installed">Nie zainstalowano</string>
<string name="home_click_to_install">Kliknij, aby zainstalować</string> <string name="home_click_to_install">Kliknij, aby zainstalować</string>
<string name="home_working">Działa</string> <string name="home_working">Działa</string>
<string name="home_working_version">Wersja: %d</string> <string name="home_working_version">Wersja: %s</string>
<string name="home_unsupported">Nieobsługiwany</string> <string name="home_unsupported">Nieobsługiwany</string>
<string name="home_unsupported_reason">KernelSU obsługuje obecnie tylko jądra GKI</string> <string name="home_unsupported_reason">KernelSU obsługuje obecnie tylko jądra GKI</string>
<string name="home_kernel">Jądro</string> <string name="home_kernel">Jądro</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Kontekst SELinux</string> <string name="profile_selinux_context">Kontekst SELinux</string>
<string name="profile_umount_modules">Odmontuj moduły</string> <string name="profile_umount_modules">Odmontuj moduły</string>
<string name="failed_to_update_app_profile">Nie udało się zaktualizować profilu aplikacji dla %s</string> <string name="failed_to_update_app_profile">Nie udało się zaktualizować profilu aplikacji dla %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Domyślnie odmontuj moduły</string> <string name="settings_umount_modules_default">Domyślnie odmontuj moduły</string>
<string name="settings_umount_modules_default_summary">Globalna wartość domyślna opcji \"Odmontuj moduły\" w profilu aplikacji. Jeśli jest włączona, wycofuje wszystkie modyfikacje dokonane przez moduły dla aplikacji, które nie mają ustawionego profilu.</string> <string name="settings_umount_modules_default_summary">Globalna wartość domyślna opcji \"Odmontuj moduły\" w profilu aplikacji. Jeśli jest włączona, wycofuje wszystkie modyfikacje dokonane przez moduły dla aplikacji, które nie mają ustawionego profilu.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Não instalado</string> <string name="home_not_installed">Não instalado</string>
<string name="home_click_to_install">Clique para instalar</string> <string name="home_click_to_install">Clique para instalar</string>
<string name="home_working">Em execução</string> <string name="home_working">Em execução</string>
<string name="home_working_version">Versão: %d</string> <string name="home_working_version">Versão: %s</string>
<string name="home_unsupported">Sem suporte</string> <string name="home_unsupported">Sem suporte</string>
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string> <string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Não instalado</string> <string name="home_not_installed">Não instalado</string>
<string name="home_click_to_install">Clique para instalar</string> <string name="home_click_to_install">Clique para instalar</string>
<string name="home_working">Funcionando</string> <string name="home_working">Funcionando</string>
<string name="home_working_version">Versão: %d</string> <string name="home_working_version">Versão: %s</string>
<string name="home_unsupported">Sem suporte</string> <string name="home_unsupported">Sem suporte</string>
<string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string> <string name="home_unsupported_reason">KernelSU suporta apenas kernels GKI agora</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">contexto SELinux</string> <string name="profile_selinux_context">contexto SELinux</string>
<string name="profile_umount_modules">Desativar modulos</string> <string name="profile_umount_modules">Desativar modulos</string>
<string name="failed_to_update_app_profile">Falha ao atualizar o perfil do aplicativo para %s</string> <string name="failed_to_update_app_profile">Falha ao atualizar o perfil do aplicativo para %s</string>
<string name="require_kernel_version" formatted="false">A versão atual do KernelSU %d é muito baixa para o gerenciador funcionar corretamente. Atualize para a versão %d ou superior!</string> <string name="require_kernel_version" formatted="false">A versão atual do KernelSU %s é muito baixa para o gerenciador funcionar corretamente. Atualize para a versão %s ou superior!</string>
<string name="settings_umount_modules_default">Módulos desativados por padrão</string> <string name="settings_umount_modules_default">Módulos desativados por padrão</string>
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Módulos Umount\" em Perfis de Aplicativos. Se ativado, removerá todas as modificações de módulo do sistema para aplicativos que não possuem um Perfil definido.</string> <string name="settings_umount_modules_default_summary">O valor padrão global para \"Módulos Umount\" em Perfis de Aplicativos. Se ativado, removerá todas as modificações de módulo do sistema para aplicativos que não possuem um Perfil definido.</string>
<string name="settings_susfs_toggle">Desabilitar ganchos de \"Kprobe\"</string> <string name="settings_susfs_toggle">Desabilitar ganchos de \"Kprobe\"</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Nu este instalat</string> <string name="home_not_installed">Nu este instalat</string>
<string name="home_click_to_install">Click pentru a instala</string> <string name="home_click_to_install">Click pentru a instala</string>
<string name="home_working">Funcționează</string> <string name="home_working">Funcționează</string>
<string name="home_working_version">Versiune: %d</string> <string name="home_working_version">Versiune: %s</string>
<string name="home_unsupported">Necompatibil</string> <string name="home_unsupported">Necompatibil</string>
<string name="home_unsupported_reason">KernelSU suportă doar nuclee GKI acum</string> <string name="home_unsupported_reason">KernelSU suportă doar nuclee GKI acum</string>
<string name="home_kernel">Nucleu</string> <string name="home_kernel">Nucleu</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Context SELinux</string> <string name="profile_selinux_context">Context SELinux</string>
<string name="profile_umount_modules">Module u-montate</string> <string name="profile_umount_modules">Module u-montate</string>
<string name="failed_to_update_app_profile">Nu s-a putut actualiza profilul aplicației pentru %s</string> <string name="failed_to_update_app_profile">Nu s-a putut actualiza profilul aplicației pentru %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">U-montează modulele în mod implicit</string> <string name="settings_umount_modules_default">U-montează modulele în mod implicit</string>
<string name="settings_umount_modules_default_summary">Valoarea implicită globală pentru „Module u-montate” în Profilurile aplicațiilor. Dacă este activat, va elimina toate modificările modulelor aduse sistemului pentru aplicațiile care nu au un profil setat.</string> <string name="settings_umount_modules_default_summary">Valoarea implicită globală pentru „Module u-montate” în Profilurile aplicațiilor. Dacă este activat, va elimina toate modificările modulelor aduse sistemului pentru aplicațiile care nu au un profil setat.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Не установлен</string> <string name="home_not_installed">Не установлен</string>
<string name="home_click_to_install">Нажмите, чтобы установить</string> <string name="home_click_to_install">Нажмите, чтобы установить</string>
<string name="home_working">Работает</string> <string name="home_working">Работает</string>
<string name="home_working_version">Версия: %d</string> <string name="home_working_version">Версия: %s</string>
<string name="home_unsupported">Не поддерживается</string> <string name="home_unsupported">Не поддерживается</string>
<string name="home_unsupported_reason">Драйвера KernelSU не найдены в ядре, не то ядро?</string> <string name="home_unsupported_reason">Драйвера KernelSU не найдены в ядре, не то ядро?</string>
<string name="home_kernel">Ядро</string> <string name="home_kernel">Ядро</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">Контекст SELinux</string> <string name="profile_selinux_context">Контекст SELinux</string>
<string name="profile_umount_modules">Размонтировать модули</string> <string name="profile_umount_modules">Размонтировать модули</string>
<string name="failed_to_update_app_profile">Не удалось обновить профиль приложения для %s</string> <string name="failed_to_update_app_profile">Не удалось обновить профиль приложения для %s</string>
<string name="require_kernel_version" formatted="false">Текущая версия KernelSU %d слишком низкая для правильной работы менеджера. Пожалуйста, обновите до версии %d или выше!</string> <string name="require_kernel_version" formatted="false">Текущая версия KernelSU %s слишком низкая для правильной работы менеджера. Пожалуйста, обновите до версии %s или выше!</string>
<string name="settings_umount_modules_default">Размонтировать модули по умолчанию</string> <string name="settings_umount_modules_default">Размонтировать модули по умолчанию</string>
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Размонтировать модули\" в профиле приложения. При включении будут удалены все модификации модулей в системе для приложений, у которых не задан профиль</string> <string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Размонтировать модули\" в профиле приложения. При включении будут удалены все модификации модулей в системе для приложений, у которых не задан профиль</string>
<string name="settings_susfs_toggle">Отключить kprobe хуки</string> <string name="settings_susfs_toggle">Отключить kprobe хуки</string>
@@ -113,6 +113,7 @@
\n Продолжить?</string> \n Продолжить?</string>
<string name="install_next">Далее</string> <string name="install_next">Далее</string>
<string name="select_file_tip">Образ раздела %1$s рекомендуется</string> <string name="select_file_tip">Образ раздела %1$s рекомендуется</string>
<string name="select_file_tip_vendor">(нестабильный)</string>
<string name="select_kmi">Выбрать KMI</string> <string name="select_kmi">Выбрать KMI</string>
<string name="settings_uninstall">Удалить</string> <string name="settings_uninstall">Удалить</string>
<string name="settings_uninstall_temporary">Удалить на время</string> <string name="settings_uninstall_temporary">Удалить на время</string>
@@ -178,8 +179,12 @@
<string name="hide_other_info_summary">Скрывать информацию о количестве приложений с рут-доступом, модулей и KPM-модулей на главной странице</string> <string name="hide_other_info_summary">Скрывать информацию о количестве приложений с рут-доступом, модулей и KPM-модулей на главной странице</string>
<string name="hide_susfs_status">Скрыть статус SuSFS</string> <string name="hide_susfs_status">Скрыть статус SuSFS</string>
<string name="hide_susfs_status_summary">Скрывать информацию о статусе SuSFS на главной странице</string> <string name="hide_susfs_status_summary">Скрывать информацию о статусе SuSFS на главной странице</string>
<string name="hide_zygisk_implement">Скрыть статус Zygisk</string>
<string name="hide_zygisk_implement_summary">Скрывать информацию об имплементации Zygisk на главной странице</string>
<string name="hide_link_card">Скрыть карточки со ссылками</string> <string name="hide_link_card">Скрыть карточки со ссылками</string>
<string name="hide_link_card_summary">Скрывать карточки со ссылками на главной странице</string> <string name="hide_link_card_summary">Скрывать карточки со ссылками на главной странице</string>
<string name="hide_tag_card">Скрыть строки модуля</string>
<string name="hide_tag_card_summary">Скрывать имя пакета и размер в карточке модуля</string>
<string name="theme_mode">Тема</string> <string name="theme_mode">Тема</string>
<string name="theme_follow_system">Как в системе</string> <string name="theme_follow_system">Как в системе</string>
<string name="theme_light">Светлая</string> <string name="theme_light">Светлая</string>
@@ -251,7 +256,7 @@
<string name="horizon_flashing">Прошивка ядра…</string> <string name="horizon_flashing">Прошивка ядра…</string>
<string name="horizon_flash_complete_status">Прошивка завершена</string> <string name="horizon_flash_complete_status">Прошивка завершена</string>
<!-- Slot selection related strings --> <!-- Slot selection related strings -->
<string name="select_slot_title">Выбрать слот Flash</string> <string name="select_slot_title">Выберите слот для прошивки</string>
<string name="select_slot_description">Пожалуйста, выберите целевой слот для прошивки загрузки</string> <string name="select_slot_description">Пожалуйста, выберите целевой слот для прошивки загрузки</string>
<string name="slot_a">Слот A</string> <string name="slot_a">Слот A</string>
<string name="slot_b">Слот B</string> <string name="slot_b">Слот B</string>
@@ -358,12 +363,14 @@
<string name="susfs_config_description_text">Эта функция позволяет вам настраивать переменную uname для SuSFS. Впишите значение и нажмите \"Применить\" для изменения.</string> <string name="susfs_config_description_text">Эта функция позволяет вам настраивать переменную uname для SuSFS. Впишите значение и нажмите \"Применить\" для изменения.</string>
<string name="susfs_uname_label">Значение uname</string> <string name="susfs_uname_label">Значение uname</string>
<string name="susfs_uname_placeholder">Пожалуйста, введите пользовательское значение uname</string> <string name="susfs_uname_placeholder">Пожалуйста, введите пользовательское значение uname</string>
<string name="susfs_build_time_label">Подмена времени сборки</string>
<string name="susfs_build_time_placeholder">Пожалуйста, введите значение для подмены времени сборки</string>
<string name="susfs_current_value">Текущее значение: %s</string> <string name="susfs_current_value">Текущее значение: %s</string>
<string name="susfs_current_build_time">Текущее время сборки: %s</string>
<string name="susfs_reset_to_default">Значение по умолчанию</string> <string name="susfs_reset_to_default">Значение по умолчанию</string>
<string name="susfs_apply">Применить</string> <string name="susfs_apply">Применить</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">Подтвердить сброс</string> <string name="susfs_reset_confirm_title">Подтвердить сброс</string>
<string name="susfs_reset_confirm">Подтвердить сброс</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">Не удалось найти файл ksu_susfs</string> <string name="susfs_binary_not_found">Не удалось найти файл ksu_susfs</string>
<string name="susfs_command_failed">Выполнение команды SuSFS не удалось</string> <string name="susfs_command_failed">Выполнение команды SuSFS не удалось</string>
@@ -372,17 +379,214 @@
<!-- SuSFS Settings Item --> <!-- SuSFS Settings Item -->
<string name="susfs_config_setting_title">Конфигурация SuSFS</string> <string name="susfs_config_setting_title">Конфигурация SuSFS</string>
<!-- 开机自启动相关 --> <!-- 开机自启动相关 -->
<string name="susfs_autostart_title">Автозапуск</string>
<string name="susfs_autostart_description">Автоматически применять все конфигурации не по умолчанию при перезагрузке</string>
<string name="susfs_autostart_requirement">Для включения необходимо добавить конфигурацию</string>
<string name="susfs_autostart_enable_failed">Не удалось включить автозапуск</string>
<string name="susfs_autostart_disable_failed">Не удалось отключить автозапуск</string>
<string name="susfs_autostart_error">Ошибка автозапуска конфигурации: %s</string>
<string name="susfs_no_config_to_autostart">Нет доступных конфигураций для автозапуска</string>
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions --> <string name="susfs_tab_basic_settings">Базовые настройки</string>
<string name="susfs_tab_sus_paths">SUS пути</string>
<string name="susfs_tab_sus_mounts">SUS монтирование</string>
<string name="susfs_tab_try_umount">Попробовать размонтировать</string>
<string name="susfs_tab_path_settings">Настройки пути</string>
<string name="susfs_tab_enabled_features">Статус включённых функций</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">Добавить SUS путь</string>
<string name="susfs_add_sus_mount">Добавить SUS монтирование</string>
<string name="susfs_add_try_umount">Добавить попробовать размонтировать</string>
<string name="susfs_sus_path_added_success">Путь SUS успешно добавлен</string>
<string name="susfs_path_not_found_error">Ошибка пути</string>
<string name="susfs_path_label">Путь</string>
<string name="susfs_mount_path_label">Путь монтирования</string>
<string name="susfs_path_placeholder">например: /system/addon.d</string>
<string name="susfs_no_paths_configured">SUS пути не настроены</string>
<string name="susfs_no_mounts_configured">SUS монтирование не настроено</string>
<string name="susfs_no_umounts_configured">Попытка размонтировать не настроена</string>
<!-- SuSFS Umount Mode --> <!-- SuSFS Umount Mode -->
<string name="susfs_umount_mode_label">Режим размонтирования</string>
<string name="susfs_umount_mode_normal">Обычное размонтирование (0)</string>
<string name="susfs_umount_mode_detach">Размонтирование отсоединением (1)</string>
<string name="susfs_umount_mode_normal_short">Нормальный</string>
<string name="susfs_umount_mode_detach_short">Отсоединить</string>
<string name="susfs_umount_mode_display">Режим: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">Попытка размонтировать путь успешно добавлена: %s</string>
<string name="susfs_try_umount_added_saved">Попытка размонтировать путь успешно сохранена: %s</string>
<!-- SuSFS Run Umount --> <!-- SuSFS Run Umount -->
<string name="susfs_run_umount_confirm_title">Подтверждение запуска попробовать размонтировать</string>
<string name="susfs_run_umount_confirm_message">Это немедленно выполнит все настроенные операции размонтирования. Вы уверены, что хотите продолжить?</string>
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">Сбросить SUS пути</string>
<string name="susfs_reset_paths_message">Это очистит все конфигурации пути SUS. Вы уверены, что хотите продолжить?</string>
<string name="susfs_reset_mounts_title">Сброс SUS монтирования</string>
<string name="susfs_reset_mounts_message">Это очистит все конфигурации SUS монтирования. Вы уверены, что хотите продолжить?</string>
<string name="susfs_reset_umounts_title">Сбросить Umount</string>
<string name="susfs_reset_umounts_message">Это очистит все конфигурации размонтирования. Вы уверены, что хотите продолжить?</string>
<string name="susfs_reset_path_title">Сбросить настройки пути</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Путь к данным Android</string>
<string name="susfs_sdcard_path_label">Путь к SD-карте</string>
<string name="susfs_set_android_data_path">Задать путь к данным Android</string>
<string name="susfs_set_sdcard_path">Задать путь к SD-карте</string>
<!-- SuSFS Enabled Features --> <!-- SuSFS Enabled Features -->
<string name="susfs_enabled_features_description">Показывать текущее состояние функций SuSFS</string>
<string name="susfs_no_features_found">Информация о состоянии объектов не найдена</string>
<string name="susfs_feature_enabled">Включено</string>
<string name="susfs_feature_disabled">Выключено</string>
<!-- Feature Labels --> <!-- Feature Labels -->
<string name="sus_path_feature_label">Поддержка SUS пути</string>
<string name="sus_mount_feature_label">Поддержка SUS монтирования</string>
<string name="try_umount_feature_label">Поддержка размонтирования</string>
<string name="spoof_uname_feature_label">Поддержка подмены uname</string>
<string name="spoof_cmdline_feature_label">Подмена Cmdline/Bootconfig</string>
<string name="open_redirect_feature_label">Поддержка Open Redirect</string>
<string name="enable_log_feature_label">Поддержка логов</string>
<string name="auto_default_mount_feature_label">Автомонтирование по умолчанию</string>
<string name="auto_bind_mount_feature_label">Автоматическое бинд монтирование</string>
<string name="auto_try_umount_bind_feature_label">Автоматически попробовать размонтировать привязать монтировать</string>
<string name="hide_symbols_feature_label">Скрытие KSU SUSFS Symbols</string>
<string name="magic_mount_feature_label">Поддержка Magic Mount</string>
<string name="sus_kstat_feature_label">Поддержка SUS Kstat</string>
<string name="sus_su_feature_label">Функция переключения режима SUS SU</string>
<!-- 可切换状态 --> <!-- 可切换状态 -->
<string name="susfs_feature_configurable">Настраиваемые функции SuSFS</string>
<string name="susfs_enable_log_label">SuSFS включить лог</string>
<string name="susfs_log_config_description">Включить или отключить логирование для SuSFS</string>
<string name="susfs_log_config_title">SuSFS настройка логирования</string>
<string name="susfs_log_enabled">Включить логирование SuSFS</string>
<string name="susfs_log_disabled">Выключить логирование SuSFS</string>
<string name="module_update_json">JSON обновления</string>
<string name="module_update_json_copied">JSON ссылка обновления скопирована в буфер обмена</string>
<!-- Settings related strings --> <!-- Settings related strings -->
<string name="show_more_module_info">Показать больше информации о модуле</string>
<string name="show_more_module_info_summary">Показывать доп. информацию о модулях, такую как JSON ссылку для обновления</string>
<string name="susfs_execution_location_label">Место выполнения</string>
<string name="susfs_current_execution_location">Текущее место выполнения: %s</string>
<string name="susfs_execution_location_service">Сервис</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">Выполнить после запуска системных сервисов</string>
<string name="susfs_execution_location_post_fs_data_description">Выполнить после монтирования файловой системы, но перед полной загрузкой. Может вызвать бутлуп</string>
<string name="susfs_slot_info_title">Информация о слоте</string>
<string name="susfs_slot_info_description">Просмотреть информацию о текущем слоте загрузки и скопировать значения</string>
<string name="susfs_current_active_slot">Текущий слот: %s</string>
<string name="susfs_slot_uname">Uname: %s</string>
<string name="susfs_slot_build_time">Время сборки: %s</string>
<string name="susfs_slot_current_badge">Текущее</string>
<string name="susfs_slot_use_uname">Использовать Uname</string>
<string name="susfs_slot_use_build_time">Использовать время сборки</string>
<string name="susfs_slot_info_unavailable">Не удается получить информацию о слоте</string>
<!-- SuSFS 自启动相关字符串 --> <!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">SuSFS автозапуск модуля включен, путь к модулям: %s</string>
<string name="susfs_autostart_disabled_success">SuSFS модуль автозапуска отключен</string>
<!-- SuSFS Kstat相关字符串 --> <!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Конфигурация Kstat</string>
<string name="kstat_static_config_added">Добавлена статическая конфигурация Kstat: %1$s</string>
<string name="kstat_config_removed">Конфигурация Kstat удалена: %1$s</string>
<string name="kstat_path_added">Путь к Kstat добавлен: %1$s</string>
<string name="kstat_path_removed">Путь к Kstat удалён: %1$s</string>
<string name="kstat_updated">Kstat обновлен: %1$s</string>
<string name="kstat_full_clone_updated">Полный клон Kstat обновлён: %1$s</string>
<string name="add_kstat_statically_title">Добавить статическую конфигурацию Kstat</string>
<string name="file_or_directory_path_label">Путь к файлу/папке</string>
<string name="hint_use_default_value">Подсказка: Вы можете использовать «по умолчанию» для использования оригинального значения</string>
<string name="add_kstat_path_title">Добавить путь Kstat</string>
<string name="add">Добавить</string>
<string name="reset_kstat_config_title">Сбросить конфигурацию Kstat</string>
<string name="reset_kstat_config_message">Вы уверены, что хотите очистить все конфигурации Kstat? Это действие нельзя отменить.</string>
<string name="kstat_config_description_title">Описание конфигурации Kstat</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_staticall: Статическая статистика информации о файлах/директориях</string>
<string name="kstat_config_description_add">• add_sus_kstat: Добавить путь перед привязкой, сохраняя исходную статистику</string>
<string name="kstat_config_description_update">• update_sus_kstat: Обновление цели, сохранение размера и блоков без изменений</string>
<string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: Обновление только новых, сохранить другие исходные значения</string>
<string name="static_kstat_config">Статическая конфигурация Kstat</string>
<string name="kstat_path_management">Управление путями Kstat</string>
<string name="no_kstat_config_message">Пока нет конфигурации Kstat, нажмите кнопку выше, чтобы добавить</string>
<!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">Контроль скрытия SUS монтирования</string>
<string name="susfs_hide_mounts_control_description">Управление режимом скрытия SUS монтирования для процессов</string>
<string name="susfs_hide_mounts_for_all_procs_label">Скрыть монтирования SUS для всех процессов</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">Когда включено, монтирования SUS будут скрыты от всех процессов, включая процессы KSU</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">Если отключено, монтирования SUS будут скрываться только из процессов, не связанных с KSU, процессы KSU могут видеть монтирования</string>
<string name="susfs_hide_mounts_all_enabled">Включено скрытие монтирования SUS для всех процессов</string>
<string name="susfs_hide_mounts_all_disabled">Отключено скрытие монтирования SUS для всех процессов</string>
<string name="susfs_hide_mounts_recommendation">Рекомендуется отключить после разблокировки экрана или во время service.sh или boot-completed.sh, так как это должно исправить проблему на некоторых root-приложениях, которые опираются на монтирование, смонтированное процессом KSU</string>
<string name="susfs_hide_mounts_current_setting">Текущие настройки: %s</string>
<string name="susfs_hide_mounts_setting_all">Скрыть для всех процессов</string>
<string name="susfs_hide_mounts_setting_non_ksu">Скрыть только для процессов, не связанных с KSU</string>
<string name="susfs_run">Запустить</string>
<string name="kernel_simple_kernel">Скрыть доп. информацию о ядре</string>
<string name="kernel_simple_kernel_summary">Включить или отключить чистый режим, отображаемой версии ядра SukiSU</string>
<string name="susfs_android_data_path_set">Путь к данным Android был установлен на: %s</string>
<string name="susfs_sdcard_path_set">Путь к SD-карте был установлен на: %s</string>
<string name="susfs_path_setup_warning">Установка пути может быть не вполне успешной, но SUS пути будут добавлены</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">Резервное копирование</string>
<string name="susfs_backup_description">Создайте резервную копию всех конфигураций SuSFS. Файл резервной копии будет содержать все настройки, пути и конфигурации.</string>
<string name="susfs_backup_create">Создать резервную копию</string>
<string name="susfs_backup_success">Резервная копия успешно создана: %s</string>
<string name="susfs_backup_failed">Не удалось создать резервную копию: %s</string>
<string name="susfs_backup_file_not_found">Файл резервной копии не найден</string>
<string name="susfs_backup_invalid_format">Неверный формат файла резервной копии</string>
<string name="susfs_backup_version_mismatch">Несоответствие версии резервного копирования</string>
<string name="susfs_restore_title">Восстановить</string>
<string name="susfs_restore_description">Восстановить настройки SuSFS из файла резервной копии. Это перезапишет все текущие настройки.</string>
<string name="susfs_restore_select_file">Выберите файл резервной копии</string>
<string name="susfs_restore_success" formatted="false">Конфигурация успешно восстановлена из резервной копии, созданной на %s с устройства: %s</string>
<string name="susfs_restore_failed">Ошибка восстановления: %s</string>
<string name="susfs_restore_confirm_title">Подтвердить восстановление</string>
<string name="susfs_restore_confirm_description">Это очистит все конфигурации размонтирования. Вы уверены, что хотите продолжить?</string>
<string name="susfs_restore_confirm">Восстановление</string>
<string name="susfs_backup_info_date">Дата резервного копирования: %s</string>
<string name="susfs_backup_info_device">Устройство: %s</string>
<string name="susfs_backup_info_version">Версия: %s</string>
<string name="hide_bl_script">Скрыть BL скрипт</string>
<string name="hide_bl_script_description">Включить скрипт Hide Bootloader Unlock Status</string>
<string name="cleanup_residue">Очистка</string>
<string name="cleanup_residue_description">Очистка остаточных файлов и каталогов различных модулей и инструментов (может быть удален по ошибке, в результате потери и неспособности начаться, используйте с осторожностью)</string>
<string name="susfs_edit_sus_path">Редактировать путь SUS</string>
<string name="susfs_edit_sus_mount">Редактировать точку монтирования SUS</string>
<string name="susfs_edit_try_umount">Изменить попробовать размонтировать</string>
<string name="edit_kstat_statically_title">Изменить статическую конфигурацию Kstat</string>
<string name="edit_kstat_path_title">Редактировать путь Kstat</string>
<string name="susfs_save">Сохранить</string>
<string name="edit">Редактировать</string>
<string name="delete">Удалить</string>
<string name="update">Обновить</string>
<string name="kstat_config_updated">Обновить конфиг Kstat</string>
<string name="kstat_path_updated">Обновить путь Kstat</string>
<string name="susfs_update_full_clone">Полное обновление клона SuSFS</string>
<string name="umount_zygote_iso_service">Размонтировать сервис изоляции Zygote</string>
<string name="umount_zygote_iso_service_description">Включите эту опцию, чтобы размонтировать точки монтирования Zygote при запуске системы</string>
<string name="umount_zygote_iso_service_enabled">Размонтирование служб Zygote включено</string>
<string name="umount_zygote_iso_service_disabled">Размонтирование служб Zygote выключено</string>
<string name="app_paths_section">Путь к приложению</string>
<string name="other_paths_section">Другие пути</string>
<string name="add_custom_path">Другое</string>
<string name="add_app_path">Приложение</string>
<string name="susfs_add_app_path">Добавить путь приложения</string>
<string name="search_apps">Поиск приложений</string>
<string name="selected_apps_count">Выбрано %1$d приложений</string>
<string name="already_added_apps_count">%1$d приложений уже добавлено</string>
<string name="all_apps_already_added">Все приложения были добавлены</string>
<string name="dynamic_sign_title">Конфигурация динамической подписи</string>
<string name="dynamic_sign_enabled_summary">Включено (размер: %s)</string>
<string name="dynamic_sign_disabled">Выключено</string>
<string name="enable_dynamic_sign">Включить динамическую подпись</string>
<string name="signature_size">Размер подписи</string>
<string name="signature_hash">Хэш подписи</string>
<string name="hash_must_be_64_chars">Хеш должен содержать 64 шестнадцатеричных символа</string>
<string name="dynamic_sign_set_success">Конфигурация динамической подписи успешно установлена</string>
<string name="dynamic_sign_set_failed">Не удалось установить конфигурацию динамической подписи</string>
<string name="invalid_sign_config">Неверная конфигурация подписи</string>
<string name="dynamic_sign_disabled_success">Динамическая подпись отключена</string>
<string name="dynamic_sign_clear_failed">Не удалось очистить динамическую подпись</string>
<string name="dynamic_signature">Динамическая</string>
<string name="signature_index">Подпись %1$d</string>
<string name="unknown_signature">Неизвестно</string>
<string name="multi_manager_list">Активный менеджер</string>
<string name="no_active_manager">Нет активного менеджера</string>
<string name="default_signature">SukiSU</string>
<string name="home_zygisk_implement">Реализация Zygisk</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Ni nameščeno</string> <string name="home_not_installed">Ni nameščeno</string>
<string name="home_click_to_install">Klikni za namestitev</string> <string name="home_click_to_install">Klikni za namestitev</string>
<string name="home_working">V obdelavi</string> <string name="home_working">V obdelavi</string>
<string name="home_working_version">Verzija: %d</string> <string name="home_working_version">Verzija: %s</string>
<string name="home_unsupported">Ne podpira</string> <string name="home_unsupported">Ne podpira</string>
<string name="home_unsupported_reason">KernelSU podpira samo GKI kernele</string> <string name="home_unsupported_reason">KernelSU podpira samo GKI kernele</string>
<string name="home_kernel">Kernel</string> <string name="home_kernel">Kernel</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux kontekst</string> <string name="profile_selinux_context">SELinux kontekst</string>
<string name="profile_umount_modules">Izvrzi module</string> <string name="profile_umount_modules">Izvrzi module</string>
<string name="failed_to_update_app_profile">Napaka pri posodobitvi aplikacijskega profila za %s</string> <string name="failed_to_update_app_profile">Napaka pri posodobitvi aplikacijskega profila za %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Po privzetem izvrzi module</string> <string name="settings_umount_modules_default">Po privzetem izvrzi module</string>
<string name="settings_umount_modules_default_summary">Globalno privzeta vrednost za \"Izvrzi module\" v aplikacijskih profilih. Če je omogočena, bo to odstranilo vse sistemske modifikacije modulov za aplikacije, ki nimajo nastavljenega profila.</string> <string name="settings_umount_modules_default_summary">Globalno privzeta vrednost za \"Izvrzi module\" v aplikacijskih profilih. Če je omogočena, bo to odstranilo vse sistemske modifikacije modulov za aplikacije, ki nimajo nastavljenega profila.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -3,7 +3,7 @@
<string name="home_click_to_install">Додирните да бисте инсталирали</string> <string name="home_click_to_install">Додирните да бисте инсталирали</string>
<string name="home">Почетна</string> <string name="home">Почетна</string>
<string name="home_not_installed">Није инсталирано</string> <string name="home_not_installed">Није инсталирано</string>
<string name="home_working_version">Верзија: %d</string> <string name="home_working_version">Верзија: %s</string>
<string name="home_working">Ради</string> <string name="home_working">Ради</string>
<string name="save_log">Сачувај Дневнике</string> <string name="save_log">Сачувај Дневнике</string>
</resources> </resources>

View File

@@ -14,6 +14,6 @@
<string name="home_not_installed">ఇన్‌స్టాల్ చేయలేదు</string> <string name="home_not_installed">ఇన్‌స్టాల్ చేయలేదు</string>
<string name="home_click_to_install">ఇన్‌స్టాల్ చేయడానికి క్లిక్ చేయండి</string> <string name="home_click_to_install">ఇన్‌స్టాల్ చేయడానికి క్లిక్ చేయండి</string>
<string name="home_working">పని చేస్తోంది</string> <string name="home_working">పని చేస్తోంది</string>
<string name="home_working_version">వెర్షన్: %d</string> <string name="home_working_version">వెర్షన్: %s</string>
<string name="save_log">లాగ్‌లు సేవ్ చేయండి</string> <string name="save_log">లాగ్‌లు సేవ్ చేయండి</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">ยังไม่ได้ติดตั้ง</string> <string name="home_not_installed">ยังไม่ได้ติดตั้ง</string>
<string name="home_click_to_install">กดเพื่อติดตั้ง</string> <string name="home_click_to_install">กดเพื่อติดตั้ง</string>
<string name="home_working">กำลังทำงาน</string> <string name="home_working">กำลังทำงาน</string>
<string name="home_working_version">เวอร์ชัน: %d</string> <string name="home_working_version">เวอร์ชัน: %s</string>
<string name="home_unsupported">ไม่รองรับ</string> <string name="home_unsupported">ไม่รองรับ</string>
<string name="home_unsupported_reason">ตอนนี้ KernelSU รองรับเคอร์เนลประเภท GKI เท่านั้น</string> <string name="home_unsupported_reason">ตอนนี้ KernelSU รองรับเคอร์เนลประเภท GKI เท่านั้น</string>
<string name="home_kernel">เคอร์เนล</string> <string name="home_kernel">เคอร์เนล</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">บริบท SELinux</string> <string name="profile_selinux_context">บริบท SELinux</string>
<string name="profile_umount_modules">Umount โมดูล</string> <string name="profile_umount_modules">Umount โมดูล</string>
<string name="failed_to_update_app_profile">ไม่สามารถอัปเดตโปรไฟล์แอปสำหรับ %s ได้</string> <string name="failed_to_update_app_profile">ไม่สามารถอัปเดตโปรไฟล์แอปสำหรับ %s ได้</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">The current KernelSU version %s is too low for the manager to work properly. Please upgrade to version %s or higher!</string>
<string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string> <string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string>
<string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string> <string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Disable kprobe hooks</string>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Yüklü değil</string> <string name="home_not_installed">Yüklü değil</string>
<string name="home_click_to_install">Yüklemek için tıklayın</string> <string name="home_click_to_install">Yüklemek için tıklayın</string>
<string name="home_working">Çalışıyor</string> <string name="home_working">Çalışıyor</string>
<string name="home_working_version">Sürüm: %d</string> <string name="home_working_version">Sürüm: %s</string>
<string name="home_unsupported">Desteklenmiyor</string> <string name="home_unsupported">Desteklenmiyor</string>
<string name="home_unsupported_reason">Kernel\'inizde KernelSU sürücüsü algılanmadı, yanlış çekirdek mi?</string> <string name="home_unsupported_reason">Kernel\'inizde KernelSU sürücüsü algılanmadı, yanlış çekirdek mi?</string>
<string name="home_kernel">Kernel sürümü</string> <string name="home_kernel">Kernel sürümü</string>
@@ -36,8 +36,8 @@
<string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinizden emin misiniz?</string> <string name="module_uninstall_confirm">%s modülünü kaldırmak istediğinizden emin misiniz?</string>
<string name="module_uninstall_success">%s kaldırıldı</string> <string name="module_uninstall_success">%s kaldırıldı</string>
<string name="module_uninstall_failed">Kaldırılamadı: %s</string> <string name="module_uninstall_failed">Kaldırılamadı: %s</string>
<string name="module_version">Version</string> <string name="module_version">Sürüm</string>
<string name="module_author">Author</string> <string name="module_author">Geliştirici</string>
<string name="refresh">Yenile</string> <string name="refresh">Yenile</string>
<string name="show_system_apps">Sistem uygulamalarını göster</string> <string name="show_system_apps">Sistem uygulamalarını göster</string>
<string name="hide_system_apps">Sistem uygulamalarını gizle</string> <string name="hide_system_apps">Sistem uygulamalarını gizle</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux bağlamı</string> <string name="profile_selinux_context">SELinux bağlamı</string>
<string name="profile_umount_modules">Modülleri bağlamayı kaldır</string> <string name="profile_umount_modules">Modülleri bağlamayı kaldır</string>
<string name="failed_to_update_app_profile">%s için Uygulama Profili güncellenemedi</string> <string name="failed_to_update_app_profile">%s için Uygulama Profili güncellenemedi</string>
<string name="require_kernel_version" formatted="false">Mevcut KernelSU sürümü %d, yöneticinin düzgün çalışması için çok düşük. Lütfen sürüm %d veya daha yüksek bir sürüme yükseltin!</string> <string name="require_kernel_version" formatted="false">Mevcut KernelSU sürümü %s, yöneticinin düzgün çalışması için çok düşük. Lütfen sürüm %s veya daha yüksek bir sürüme yükseltin!</string>
<string name="settings_umount_modules_default">Modülleri varsayılan olarak bağlamayı kaldır</string> <string name="settings_umount_modules_default">Modülleri varsayılan olarak bağlamayı kaldır</string>
<string name="settings_umount_modules_default_summary">Uygulama Profilindeki \"Modülleri bağlamayı kaldır\" için küresel varsayılan değer. Etkinleştirilirse, profil ayarlanmamış uygulamalar için sistemdeki tüm modül değişikliklerini kaldırır.</string> <string name="settings_umount_modules_default_summary">Uygulama Profilindeki \"Modülleri bağlamayı kaldır\" için küresel varsayılan değer. Etkinleştirilirse, profil ayarlanmamış uygulamalar için sistemdeki tüm modül değişikliklerini kaldırır.</string>
<string name="settings_susfs_toggle">Kprobe kancalarını devre dışı bırak</string> <string name="settings_susfs_toggle">Kprobe kancalarını devre dışı bırak</string>
@@ -101,7 +101,7 @@
<string name="settings_check_update">Güncelleme kontrolü</string> <string name="settings_check_update">Güncelleme kontrolü</string>
<string name="settings_check_update_summary">Uygulama açıldığında otomatik olarak güncellemeleri kontrol et</string> <string name="settings_check_update_summary">Uygulama açıldığında otomatik olarak güncellemeleri kontrol et</string>
<string name="grant_root_failed">Root yetkisi verilemedi!</string> <string name="grant_root_failed">Root yetkisi verilemedi!</string>
<string name="action">Action</string> <string name="action">Eylem</string>
<string name="close">Kapat</string> <string name="close">Kapat</string>
<string name="enable_web_debugging">WebView hata ayıklama etkinleştir</string> <string name="enable_web_debugging">WebView hata ayıklama etkinleştir</string>
<string name="enable_web_debugging_summary">WebUI\'yi hata ayıklamak için kullanılabilir. Sadece ihtiyaç duyulduğunda etkinleştirin.</string> <string name="enable_web_debugging_summary">WebUI\'yi hata ayıklamak için kullanılabilir. Sadece ihtiyaç duyulduğunda etkinleştirin.</string>
@@ -111,6 +111,7 @@
<string name="install_inactive_slot_warning">Cihazınız, yeniden başlatma sonrasında **ZORUNLU** olarak mevcut etkin olmayan yuvaya önyükleme yapacaktır!\nSadece OTA tamamlandıktan sonra bu seçeneği kullanın.\nDevam etmek istiyor musunuz?</string> <string name="install_inactive_slot_warning">Cihazınız, yeniden başlatma sonrasında **ZORUNLU** olarak mevcut etkin olmayan yuvaya önyükleme yapacaktır!\nSadece OTA tamamlandıktan sonra bu seçeneği kullanın.\nDevam etmek istiyor musunuz?</string>
<string name="install_next">İleri</string> <string name="install_next">İleri</string>
<string name="select_file_tip">%1$s bölüm görüntüsü önerilir</string> <string name="select_file_tip">%1$s bölüm görüntüsü önerilir</string>
<string name="select_file_tip_vendor">(kararsız)</string>
<string name="select_kmi">KMI seçin</string> <string name="select_kmi">KMI seçin</string>
<string name="settings_uninstall">Kaldır</string> <string name="settings_uninstall">Kaldır</string>
<string name="settings_uninstall_temporary">Geçici olarak kaldır</string> <string name="settings_uninstall_temporary">Geçici olarak kaldır</string>
@@ -206,7 +207,7 @@
<string name="kpm_title">KPM</string> <string name="kpm_title">KPM</string>
<string name="kpm_empty">Şu anda yüklü çekirdek modülü yok</string> <string name="kpm_empty">Şu anda yüklü çekirdek modülü yok</string>
<string name="kpm_version">Sürüm</string> <string name="kpm_version">Sürüm</string>
<string name="kpm_author">Author</string> <string name="kpm_author">Geliştirici</string>
<string name="kpm_uninstall">Kaldır</string> <string name="kpm_uninstall">Kaldır</string>
<string name="kpm_uninstall_success">Başarıyla kaldırıldı</string> <string name="kpm_uninstall_success">Başarıyla kaldırıldı</string>
<string name="kpm_uninstall_failed">Kaldırılamadı</string> <string name="kpm_uninstall_failed">Kaldırılamadı</string>
@@ -266,7 +267,7 @@
<string name="flash_failed_message">Flash\'lama başarısız</string> <string name="flash_failed_message">Flash\'lama başarısız</string>
<!-- lkm/gki install --> <!-- lkm/gki install -->
<string name="Lkm_install_methods">LKM onarımı/yükle</string> <string name="Lkm_install_methods">LKM onarımı/yükle</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string> <string name="GKI_install_methods">AnyKernel3 Flaşlama</string>
<string name="kernel_version_log">Çekirdek sürümü%1$s</string> <string name="kernel_version_log">Çekirdek sürümü%1$s</string>
<string name="tool_version_log">Kullanılan yama aracı%1$s</string> <string name="tool_version_log">Kullanılan yama aracı%1$s</string>
<string name="configuration">Yapılandır</string> <string name="configuration">Yapılandır</string>
@@ -338,7 +339,6 @@
<!-- 状态相关 --> <!-- 状态相关 -->
<string name="no_apps_in_category">Bu kategoride uygulama yok</string> <string name="no_apps_in_category">Bu kategoride uygulama yok</string>
<!-- 标签相关 --> <!-- 标签相关 -->
<!-- FAB菜单相关 -->
<string name="deny_authorization">Yetkilendirme reddedildi</string> <string name="deny_authorization">Yetkilendirme reddedildi</string>
<string name="grant_authorization">Yetki verildi</string> <string name="grant_authorization">Yetki verildi</string>
<string name="unmount_modules">Modül Bağlantıları Kaldırılıyor</string> <string name="unmount_modules">Modül Bağlantıları Kaldırılıyor</string>
@@ -359,7 +359,7 @@
<string name="susfs_config_description_text">Bu özellik, SuSFS uname değerini ve build time spoofing\'i özelleştirmenize olanak tanır. Ayarlamak istediğiniz değerleri girin ve uygulayın.</string> <string name="susfs_config_description_text">Bu özellik, SuSFS uname değerini ve build time spoofing\'i özelleştirmenize olanak tanır. Ayarlamak istediğiniz değerleri girin ve uygulayın.</string>
<string name="susfs_uname_label">Uname Değeri</string> <string name="susfs_uname_label">Uname Değeri</string>
<string name="susfs_uname_placeholder">Lütfen özel uname değeri girin</string> <string name="susfs_uname_placeholder">Lütfen özel uname değeri girin</string>
<string name="susfs_build_time_label">Build Time Spoofing</string> <string name="susfs_build_time_label">Derleme Zamanı Sahteciliği</string>
<string name="susfs_build_time_placeholder">Lütfen build time spoofing değeri girin</string> <string name="susfs_build_time_placeholder">Lütfen build time spoofing değeri girin</string>
<string name="susfs_current_value">Mevcut değer: %s</string> <string name="susfs_current_value">Mevcut değer: %s</string>
<string name="susfs_current_build_time">Mevcut build time: %s</string> <string name="susfs_current_build_time">Mevcut build time: %s</string>
@@ -367,7 +367,6 @@
<string name="susfs_apply">Uygula</string> <string name="susfs_apply">Uygula</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">Sıfırlamayı Onayla</string> <string name="susfs_reset_confirm_title">Sıfırlamayı Onayla</string>
<string name="susfs_reset_confirm">Sıfırlamayı Onayla</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">ksu_susfs dosyası bulunamadı</string> <string name="susfs_binary_not_found">ksu_susfs dosyası bulunamadı</string>
<string name="susfs_command_failed">SuSFS komut çalıştırma başarısız</string> <string name="susfs_command_failed">SuSFS komut çalıştırma başarısız</string>
@@ -390,12 +389,12 @@
<string name="susfs_tab_try_umount">Bağlamayı Kaldırmayı Dene</string> <string name="susfs_tab_try_umount">Bağlamayı Kaldırmayı Dene</string>
<string name="susfs_tab_path_settings">Yol Ayarları</string> <string name="susfs_tab_path_settings">Yol Ayarları</string>
<string name="susfs_tab_enabled_features">Etkinleştirilen Özellikler Durumu</string> <string name="susfs_tab_enabled_features">Etkinleştirilen Özellikler Durumu</string>
<!-- SuSFS Dialog Actions -->
<string name="susfs_add">Ekle</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">SUS Yolu Ekle</string> <string name="susfs_add_sus_path">SUS Yolu Ekle</string>
<string name="susfs_add_sus_mount">SUS Bağlama Noktası Ekle</string> <string name="susfs_add_sus_mount">SUS Bağlama Noktası Ekle</string>
<string name="susfs_add_try_umount">Bağlamayı Kaldırmayı Dene Ekle</string> <string name="susfs_add_try_umount">Bağlamayı Kaldırmayı Dene Ekle</string>
<string name="susfs_sus_path_added_success">SUS yolu başarıyla eklendi</string>
<string name="susfs_path_not_found_error">Yol bulunamadı hatası</string>
<string name="susfs_path_label">Yol</string> <string name="susfs_path_label">Yol</string>
<string name="susfs_mount_path_label">Bağlama Yolu</string> <string name="susfs_mount_path_label">Bağlama Yolu</string>
<string name="susfs_path_placeholder">örn.: /system/addon.d</string> <string name="susfs_path_placeholder">örn.: /system/addon.d</string>
@@ -421,6 +420,7 @@
<string name="susfs_reset_mounts_message">Bu, tüm SUS bağlama noktası yapılandırmalarını temizleyecektir. Devam etmek istiyor musunuz?</string> <string name="susfs_reset_mounts_message">Bu, tüm SUS bağlama noktası yapılandırmalarını temizleyecektir. Devam etmek istiyor musunuz?</string>
<string name="susfs_reset_umounts_title">Bağlamayı Kaldırmayı Dene Sıfırla</string> <string name="susfs_reset_umounts_title">Bağlamayı Kaldırmayı Dene Sıfırla</string>
<string name="susfs_reset_umounts_message">Bu, tüm bağlamayı kaldırmayı dene yapılandırmalarını temizleyecektir. Devam etmek istiyor musunuz?</string> <string name="susfs_reset_umounts_message">Bu, tüm bağlamayı kaldırmayı dene yapılandırmalarını temizleyecektir. Devam etmek istiyor musunuz?</string>
<string name="susfs_reset_path_title">Yol Ayarlarını Sıfırla</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Android Veri Yolu</string> <string name="susfs_android_data_path_label">Android Veri Yolu</string>
<string name="susfs_sdcard_path_label">SD Kart Yolu</string> <string name="susfs_sdcard_path_label">SD Kart Yolu</string>
@@ -458,4 +458,131 @@
<!-- Settings related strings --> <!-- Settings related strings -->
<string name="show_more_module_info">Daha Fazla Modül Bilgisi Göster</string> <string name="show_more_module_info">Daha Fazla Modül Bilgisi Göster</string>
<string name="show_more_module_info_summary">Güncelleme JSON URL\'leri gibi ek modül bilgilerini göster</string> <string name="show_more_module_info_summary">Güncelleme JSON URL\'leri gibi ek modül bilgilerini göster</string>
<string name="susfs_execution_location_label">Çalıştırma Konumu</string>
<string name="susfs_current_execution_location">Mevcut çalıştırma konumu: %s</string>
<string name="susfs_execution_location_service">Servis</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">Sistem servisleri başladıktan sonra çalıştır</string>
<string name="susfs_execution_location_post_fs_data_description">Dosya sistemi bağlandıktan sonra ancak sistem tam olarak önyüklenmeden önce çalıştır, önyükleme döngüsüne neden olabilir</string>
<string name="susfs_slot_info_title">Bölüm Bilgisi</string>
<string name="susfs_slot_info_description">Mevcut önyükleme bölümü bilgisini görüntüleyin ve değerleri kopyalayın</string>
<string name="susfs_current_active_slot">Mevcut Aktif Bölüm: %s</string>
<string name="susfs_slot_uname">Uname: %s</string>
<string name="susfs_slot_build_time">Derleme Zamanı: %s</string>
<string name="susfs_slot_current_badge">Mevcut</string>
<string name="susfs_slot_use_uname">Uname Kullan</string>
<string name="susfs_slot_use_build_time">Derleme Zamanı Kullan</string>
<string name="susfs_slot_info_unavailable">Bölüm bilgisi alınamıyor</string>
<!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">SuSFS otomatik başlatma modülü etkinleştirildi, modül yolu: %s</string>
<string name="susfs_autostart_disabled_success">SuSFS otomatik başlatma modülü devre dışı bırakıldı</string>
<!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Kstat Yapılandırması</string>
<string name="kstat_static_config_added">Kstat statik yapılandırması eklendi: %1$s</string>
<string name="kstat_config_removed">Kstat yapılandırması kaldırıldı: %1$s</string>
<string name="kstat_path_added">Kstat yolu eklendi: %1$s</string>
<string name="kstat_path_removed">Kstat yolu kaldırıldı: %1$s</string>
<string name="kstat_updated">Kstat güncellendi: %1$s</string>
<string name="kstat_full_clone_updated">Kstat tam klonu güncellendi: %1$s</string>
<string name="add_kstat_statically_title">Kstat Statik Yapılandırması Ekle</string>
<string name="file_or_directory_path_label">Dosya/Dizin Yolu</string>
<string name="hint_use_default_value">İpucu: Orijinal değeri kullanmak için ”default“ kullanabilirsiniz</string>
<string name="add_kstat_path_title">Kstat Yolu Ekle</string>
<string name="add">Ekle</string>
<string name="reset_kstat_config_title">Kstat Yapılandırmasını Sıfırla</string>
<string name="reset_kstat_config_message">Tüm Kstat yapılandırmalarını temizlemek istediğinizden emin misiniz? Bu işlem geri alınamaz.</string>
<string name="kstat_config_description_title">Kstat Yapılandırma Açıklaması</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_statically: Dosyaların/dizinlerin statik stat bilgisi</string>
<string name="kstat_config_description_add">• add_sus_kstat: Bind bağlamadan önce yol ekle, orijinal stat bilgisini sakla</string>
<string name="kstat_config_description_update">• update_sus_kstat: Hedef ino\'yu güncelle, boyut ve blokları değiştirmeden bırak</string>
<string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: Sadece ino\'yu güncelle, diğer orijinal değerleri koru</string>
<string name="static_kstat_config">Statik Kstat Yapılandırması</string>
<string name="kstat_path_management">Kstat Yol Yönetimi</string>
<string name="no_kstat_config_message">Henüz Kstat yapılandırması yok, eklemek için yukarıdaki düğmeye tıklayın</string>
<!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">SUS Bağlama Noktası Gizleme Kontrolü</string>
<string name="susfs_hide_mounts_control_description">İşlemler için SUS bağlama noktalarının gizleme davranışını kontrol et</string>
<string name="susfs_hide_mounts_for_all_procs_label">Tüm işlemler için SUS bağlama noktalarını gizle</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">Etkinleştirildiğinde, SUS bağlama noktaları KSU işlemleri dahil tüm işlemlerden gizlenir</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">Devre dışı bırakıldığında, SUS bağlama noktaları sadece KSU dışı işlemlerden gizlenir, KSU işlemleri bağlama noktalarını görebilir</string>
<string name="susfs_hide_mounts_all_enabled">Tüm işlemler için SUS bağlama noktalarını gizleme etkinleştirildi</string>
<string name="susfs_hide_mounts_all_disabled">Tüm işlemler için SUS bağlama noktalarını gizleme devre dışı bırakıldı</string>
<string name="susfs_hide_mounts_recommendation">Ekran kilidi açıldıktan sonra veya service.sh ya da boot-completed.sh aşamasında devre dışı bırakılması önerilir, çünkü bu, KSU işlemi tarafından bağlanan bağlama noktalarına dayanan bazı rootlu uygulamalardaki sorunu çözmelidir</string>
<string name="susfs_hide_mounts_current_setting">Mevcut ayar: %s</string>
<string name="susfs_hide_mounts_setting_all">Tüm işlemler için gizle</string>
<string name="susfs_hide_mounts_setting_non_ksu">Sadece KSU dışı işlemler için gizle</string>
<string name="susfs_run">Çalıştır</string>
<string name="kernel_simple_kernel">Çekirdek Sürümü Özet Modu</string>
<string name="kernel_simple_kernel_summary">SukiSU çekirdek sürümünün gösterdiği sade modu etkinleştirin veya devre dışı bırakın</string>
<string name="susfs_android_data_path_set">Android Veri yolu şuna ayarlandı: %s</string>
<string name="susfs_sdcard_path_set">SD kart yolu şuna ayarlandı: %s</string>
<string name="susfs_path_setup_warning">Yol kurulumu tam olarak başarılı olmayabilir, ancak SUS yolları eklenmeye devam edecektir</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">Yedekleme</string>
<string name="susfs_backup_description">Tüm SuSFS yapılandırmalarının bir yedeğini oluşturun. Yedekleme dosyası tüm ayarları, yolları ve yapılandırmaları içerecektir.</string>
<string name="susfs_backup_create">Yedek Oluştur</string>
<string name="susfs_backup_success">Yedek başarıyla oluşturuldu: %s</string>
<string name="susfs_backup_failed">Yedek oluşturma başarısız: %s</string>
<string name="susfs_backup_file_not_found">Yedekleme dosyası bulunamadı</string>
<string name="susfs_backup_invalid_format">Geçersiz yedekleme dosyası formatı</string>
<string name="susfs_backup_version_mismatch">Yedekleme sürümü uyuşmuyor, ancak geri yüklemeye çalışılacak</string>
<string name="susfs_restore_title">Geri Yükle</string>
<string name="susfs_restore_description">SuSFS yapılandırmalarını bir yedekleme dosyasından geri yükleyin. Bu, tüm mevcut ayarların üzerine yazacaktır.</string>
<string name="susfs_restore_select_file">Yedekleme Dosyası Seç</string>
<string name="susfs_restore_success" formatted="false">%s tarihinde %s cihazından oluşturulan yedekten yapılandırma başarıyla geri yüklendi</string>
<string name="susfs_restore_failed">Geri yükleme başarısız: %s</string>
<string name="susfs_restore_confirm_title">Geri Yüklemeyi Onayla</string>
<string name="susfs_restore_confirm_description">Bu, tüm mevcut SuSFS yapılandırmalarının üzerine yazacaktır. Devam etmek istediğinizden emin misiniz?</string>
<string name="susfs_restore_confirm">Geri Yükle</string>
<string name="susfs_backup_info_date">Yedekleme Tarihi: %s</string>
<string name="susfs_backup_info_device">Cihaz: %s</string>
<string name="susfs_backup_info_version">Sürüm: %s</string>
<string name="hide_bl_script">BL Betiğini Gizle</string>
<string name="hide_bl_script_description">Önyükleyici Kilidi Açık Durumunu Gizleme Betiklerini Etkinleştir</string>
<string name="cleanup_residue">Kalıntıları Temizle</string>
<string name="cleanup_residue_description">Çeşitli modüllerin ve araçların kalıntı dosyalarını ve dizinlerini temizleyin (yanlışlıkla silinerek kayba ve başlatılamamaya neden olabilir, dikkatli kullanın)</string>
<string name="susfs_edit_sus_path">SUS Yolunu Düzenle</string>
<string name="susfs_edit_sus_mount">SUS Bağlama Noktasını Düzenle</string>
<string name="susfs_edit_try_umount">Ayırmayı Deneme Yolunu Düzenle</string>
<string name="edit_kstat_statically_title">Kstat Statik Yapılandırmasını Düzenle</string>
<string name="edit_kstat_path_title">Kstat Yolunu Düzenle</string>
<string name="susfs_save">Kaydet</string>
<string name="edit">Düzenle</string>
<string name="delete">Sil</string>
<string name="update">Güncelle</string>
<string name="kstat_config_updated">Kstat yapılandırması güncellendi</string>
<string name="kstat_path_updated">Kstat yolu güncellendi</string>
<string name="susfs_update_full_clone">Susfs tam klon güncellemesi</string>
<string name="umount_zygote_iso_service">Zygote İzolasyon Servisi Bağlantısını Kes</string>
<string name="umount_zygote_iso_service_description">Sistem başlangıcında Zygote izolasyon servisi bağlama noktalarının bağlantısını kesmek için bu seçeneği etkinleştirin</string>
<string name="umount_zygote_iso_service_enabled">Zygote izolasyon servisi bağlantı kesme etkinleştirildi</string>
<string name="umount_zygote_iso_service_disabled">Zygote izolasyon servisi bağlantı kesme devre dışı bırakıldı</string>
<string name="app_paths_section">Uygulama Yolu</string>
<string name="other_paths_section">Diğer yollar</string>
<string name="add_custom_path">Diğer</string>
<string name="add_app_path">Uygulama</string>
<string name="susfs_add_app_path">Uygulama Yolu Ekle</string>
<string name="search_apps">Uygulama Ara</string>
<string name="selected_apps_count">%1$d uygulama seçildi</string>
<string name="already_added_apps_count">%1$d uygulama zaten eklendi</string>
<string name="all_apps_already_added">Tüm uygulamalar eklendi</string>
<string name="dynamic_sign_title">Dinamik İmza Yapılandırması</string>
<string name="dynamic_sign_enabled_summary">Etkin (Boyut: %s)</string>
<string name="dynamic_sign_disabled">Devre Dışı</string>
<string name="enable_dynamic_sign">Dinamik İmzayı Etkinleştir</string>
<string name="signature_size">İmza Boyutu</string>
<string name="signature_hash">İmza Hash</string>
<string name="hash_must_be_64_chars">Hash, 64 adet onaltılık karakterden oluşmalıdır</string>
<string name="dynamic_sign_set_success">Dinamik imza yapılandırması başarıyla ayarlandı</string>
<string name="dynamic_sign_set_failed">Dinamik imza yapılandırması ayarlanamadı</string>
<string name="invalid_sign_config">Geçersiz imza yapılandırması</string>
<string name="dynamic_sign_disabled_success">Dinamik imza devre dışı bırakıldı</string>
<string name="dynamic_sign_clear_failed">Dinamik imza temizlenemedi</string>
<string name="dynamic_signature">Dinamik</string>
<string name="signature_index">İmza %1$d</string>
<string name="unknown_signature">Bilinmiyor</string>
<string name="multi_manager_list">Aktif Yönetici</string>
<string name="no_active_manager">Aktif yönetici yok</string>
<string name="default_signature">SukiSU</string>
<string name="home_zygisk_implement">Zygisk uygulaması</string>
</resources> </resources>

View File

@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name" translatable="false">SukiSU Ultra</string>
<string name="home">Головна</string> <string name="home">Головна</string>
<string name="home_not_installed">Не встановлено</string> <string name="home_not_installed">Не встановлено</string>
<string name="home_click_to_install">Натисніть щоб встановити</string> <string name="home_click_to_install">Натисніть, щоб встановити</string>
<string name="home_working">Працює</string> <string name="home_working">Працює</string>
<string name="home_working_version">Версія: %d</string> <string name="home_working_version">Версія: %s</string>
<string name="home_unsupported">Не підтримується</string> <string name="home_unsupported">Не підтримується</string>
<string name="home_unsupported_reason">KernelSU підтримує лише GKI ядра на данний момент</string> <string name="home_unsupported_reason">Драйвер KernelSU не виявлено у вашому ядрі. Можливо, у вас неправильне ядро.</string>
<string name="home_kernel">Ядро</string> <string name="home_kernel">Версія ядра</string>
<string name="home_susfs_version">SuSFS Version</string> <string name="home_susfs_version">Версія SuSFS</string>
<string name="home_manager_version">Версія менеджера</string> <string name="home_manager_version">Версія менеджера</string>
<string name="home_selinux_status">Статус SELinux</string> <string name="home_selinux_status">Статус SELinux</string>
<string name="selinux_status_disabled">Вимкнено</string> <string name="selinux_status_disabled">Вимкнено</string>
@@ -20,353 +21,526 @@
<string name="module_failed_to_disable">Не вдалося вимкнути модуль: %s</string> <string name="module_failed_to_disable">Не вдалося вимкнути модуль: %s</string>
<string name="module_empty">Немає встановлених модулів</string> <string name="module_empty">Немає встановлених модулів</string>
<string name="module">Модулі</string> <string name="module">Модулі</string>
<string name="module_sort_action_first">Sort (Action first)</string> <string name="module_sort_action_first">Сортувати (Спочатку дії)</string>
<string name="module_sort_enabled_first">Sort (Enabled first)</string> <string name="module_sort_enabled_first">Сортувати (Спочатку ввімкнені)</string>
<string name="uninstall">Видалити</string> <string name="uninstall">Видалити</string>
<string name="module_install">Встановити</string> <string name="module_install">Встановити</string>
<string name="install">Встановити</string> <string name="install">Встановити</string>
<string name="reboot">Перезавантажити</string> <string name="reboot">Перезавантажити</string>
<string name="settings">Налаштування</string> <string name="settings">Налаштування</string>
<string name="reboot_userspace">М\'яке перезавантаження</string> <string name="reboot_userspace">М\'яке перезавантаження</string>
<string name="reboot_recovery">Перезавантажити до Recovery</string> <string name="reboot_recovery">Перезавантажити в Recovery</string>
<string name="reboot_bootloader">Перезавантажити до Bootloader</string> <string name="reboot_bootloader">Перезавантажити в Bootloader</string>
<string name="reboot_download">Перезавантажити до Download</string> <string name="reboot_download">Перезавантажити в режим Download</string>
<string name="reboot_edl">Перезавантажити до EDL</string> <string name="reboot_edl">Перезавантажити в режим EDL</string>
<string name="about">Про додаток</string> <string name="about">Про додаток</string>
<string name="module_uninstall_confirm">Ви впевнені, що хочете видалити модуль %s?</string> <string name="module_uninstall_confirm">Ви впевнені, що хочете видалити модуль %s?</string>
<string name="module_uninstall_success">%s видалено</string> <string name="module_uninstall_success">%s видалено</string>
<string name="module_uninstall_failed">Не вдалося видалити: %s</string> <string name="module_uninstall_failed">Не вдалося видалити: %s</string>
<string name="module_version">Версія</string> <string name="module_version">Версія</string>
<string name="module_author">Автор</string> <string name="module_author">Автор</string>
<string name="refresh">Освіжати(Оновити)</string> <string name="refresh">Оновити</string>
<string name="show_system_apps">Показати системні додатки</string> <string name="show_system_apps">Показати системні додатки</string>
<string name="hide_system_apps">Сховати системні додатки</string> <string name="hide_system_apps">Сховати системні додатки</string>
<string name="send_log">Надіслати логи</string> <string name="send_log">Надіслати логи</string>
<string name="safe_mode">Безпечний режим</string> <string name="safe_mode">Безпечний режим</string>
<string name="reboot_to_apply">Перезавантажте, щоб застосувати</string> <string name="reboot_to_apply">Перезавантажте, щоб застосувати</string>
<string name="module_magisk_conflict">Модулі вимкнено, оскільки вони конфліктують із модулями Magisk!</string> <string name="module_magisk_conflict">Модулі недоступні через конфлікт з Magisk!</string>
<string name="home_learn_kernelsu">Дізнайтеся про KernelSU</string> <string name="home_learn_kernelsu">Дізнатися про KernelSU</string>
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string> <string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
<string name="home_click_to_learn_kernelsu">Дізнайтеся, як інсталювати KernelSU і використовувати модулі</string> <string name="home_click_to_learn_kernelsu">Дізнайтеся, як встановити KernelSU та використовувати модулі</string>
<string name="home_support_title">Підтримати нас</string> <string name="home_support_title">Підтримати нас</string>
<string name="home_support_content">KernelSU є, і завжди буде безкоштовним та з відкритим кодом. Однак, якщо вам не байдуже, можете зробити невеличке пожертвування.</string> <string name="home_support_content">KernelSU є, і завжди буде, безкоштовним та з відкритим вихідним кодом. Однак ви можете показати нам свою підтримку, зробивши пожертву.</string>
<string name="about_source_code"><![CDATA[View source code at %1$s<br/>Join our %2$s channel]]></string> <string name="about_source_code"><![CDATA[Переглянути вихідний код на %1$s<br/>Приєднуйтесь до нашого каналу %2$s]]></string>
<string name="profile_default">Типовий</string> <string name="profile" translatable="false">Профіль додатку</string>
<string name="profile_default">За замовчуванням</string>
<string name="profile_template">Шаблон</string> <string name="profile_template">Шаблон</string>
<string name="profile_custom">Власний</string> <string name="profile_custom">Власний</string>
<string name="profile_name">Назва профілю</string> <string name="profile_name">Назва профілю</string>
<string name="profile_groups">Групи</string> <string name="profile_groups">Групи</string>
<string name="profile_capabilities">Можливості</string> <string name="profile_capabilities">Можливості</string>
<string name="profile_selinux_context">Контекст SELinux</string> <string name="profile_selinux_context">Контекст SELinux</string>
<string name="profile_umount_modules">Розмонтувати модулі</string> <string name="profile_umount_modules">Відмонтувати модулі</string>
<string name="failed_to_update_app_profile">Не вдалося оновити профіль додатка для %s</string> <string name="failed_to_update_app_profile">Не вдалося оновити профіль додатку для %s</string>
<string name="require_kernel_version" formatted="false">The current KernelSU version %d is too low for the manager to work properly. Please upgrade to version %d or higher!</string> <string name="require_kernel_version" formatted="false">Поточна версія KernelSU %s занадто низька для коректної роботи менеджера. Будь ласка, оновіться до версії %s або вище!</string>
<string name="settings_umount_modules_default">Розмонтувати модулі за замовчуванням</string> <string name="settings_umount_modules_default">Відмонтовувати модулі за замовчуванням</string>
<string name="settings_umount_modules_default_summary">Загальне значення за замовчуванням для \"Розмонтувати модулі\" у профілях додатків. Якщо ввімкнено, буде видалено всі модифікації модулів у системі для додатків, які не мають встановленого профілю.</string> <string name="settings_umount_modules_default_summary">Глобальне значення за замовчуванням для "Відмонтувати модулі" у профілі додатку. Якщо ввімкнено, це видалить усі зміни системи, зроблені модулями, для додатків без встановленого профілю.</string>
<string name="settings_susfs_toggle">Disable kprobe hooks</string> <string name="settings_susfs_toggle">Вимкнути хуки kprobe</string>
<string name="profile_umount_modules_summary">Увімкнення даної опції дозволить KernelSU відновити для цього додатка будь-які файли, змінені модулями.</string> <string name="profile_umount_modules_summary">Увімкнення цієї опції дозволить KernelSU відновити будь-які змінені модулями файли для цього додатку.</string>
<string name="profile_selinux_domain">Домен</string> <string name="profile_selinux_domain">Домен</string>
<string name="profile_selinux_rules">Правила</string> <string name="profile_selinux_rules">Правила</string>
<string name="module_update">Оновити</string> <string name="module_update">Оновити</string>
<string name="module_downloading">Завантаження модуля: %s</string> <string name="module_downloading">Завантаження модуля: %s</string>
<string name="module_start_downloading">Початок завантаження: %s</string> <string name="module_start_downloading">Початок завантаження: %s</string>
<string name="new_version_available">Нова версія: %s доступна, натисніть, щоб завантажити</string> <string name="new_version_available">Доступна нова версія %s, натисніть для оновлення.</string>
<string name="launch_app">Запустити</string> <string name="launch_app">Запустити</string>
<string name="force_stop_app" formatted="false">Примусово зупинити</string> <string name="force_stop_app" formatted="false">Примусово зупинити</string>
<string name="restart_app">Перезапустити</string> <string name="restart_app">Перезапустити</string>
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string> <string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для %s</string>
<string name="module_changelog">Журнал змін</string> <string name="module_changelog">Список змін</string>
<string name="settings_profile_template">Шаблон Профілю Додатку</string> <string name="settings_profile_template">Шаблон профілю додатку</string>
<string name="settings_profile_template_summary">Керувати локальними та мережевими шаблонами профілів додатків</string> <string name="settings_profile_template_summary">Керування локальними та онлайн-шаблонами профілю додатку</string>
<string name="app_profile_template_create">Створити шаблон</string> <string name="app_profile_template_create">Створити шаблон</string>
<string name="app_profile_template_edit">Редагувати шаблон</string> <string name="app_profile_template_edit">Редагувати шаблон</string>
<string name="app_profile_template_id">Ідентифікатор</string> <string name="app_profile_template_id">ID</string>
<string name="app_profile_template_id_invalid">Невірний ідентифікатор шаблону</string> <string name="app_profile_template_id_invalid">Недійсний ID шаблону</string>
<string name="app_profile_template_name">Ім\'я</string> <string name="app_profile_template_name">Назва</string>
<string name="app_profile_template_description">Опис</string> <string name="app_profile_template_description">Опис</string>
<string name="app_profile_template_save">Зберегти</string> <string name="app_profile_template_save">Зберегти</string>
<string name="app_profile_template_delete">Видалити</string> <string name="app_profile_template_delete">Видалити</string>
<string name="app_profile_template_view">Переглянути шаблон</string> <string name="app_profile_template_view">Переглянути шаблон</string>
<string name="app_profile_template_readonly">Тільки читання</string> <string name="app_profile_template_readonly">Тільки для читання</string>
<string name="app_profile_template_id_exist">Шаблон з таким ідентифікатором вже існує!</string> <string name="app_profile_template_id_exist">ID шаблону вже існує!</string>
<string name="app_profile_import_export">Імпорт/Експорт</string> <string name="app_profile_import_export">Імпорт/Експорт</string>
<string name="app_profile_import_from_clipboard">Імпортувати з буферу обміну</string> <string name="app_profile_import_from_clipboard">Імпортувати з буфера обміну</string>
<string name="app_profile_export_to_clipboard">Експортувати в буфер обміну</string> <string name="app_profile_export_to_clipboard">Експортувати в буфер обміну</string>
<string name="app_profile_template_export_empty">Неможливо знайти локальні шаблони для експорту!</string> <string name="app_profile_template_export_empty">Не знайдено локальних шаблонів для експорту!</string>
<string name="app_profile_template_import_success">Успішно імпортовано</string> <string name="app_profile_template_import_success">Імпортовано успішно</string>
<string name="app_profile_template_sync">Синхронізувати мережеві шаблони</string> <string name="app_profile_template_sync">Синхронізувати онлайн-шаблони</string>
<string name="app_profile_template_save_failed">Помилка при збереженні шаблону</string> <string name="app_profile_template_save_failed">Не вдалося зберегти шаблон</string>
<string name="app_profile_template_import_empty">Буфер обміну пустий!</string> <string name="app_profile_template_import_empty">Буфер обміну порожній!</string>
<string name="module_changelog_failed">Невдача при завантаженні списку змін: %s</string> <string name="module_changelog_failed">Не вдалося завантажити список змін: %s</string>
<string name="settings_check_update">Перевірка оновлень</string> <string name="settings_check_update">Перевіряти оновлення</string>
<string name="settings_check_update_summary">Автоматична перевірка оновлень під час відкриття програми</string> <string name="settings_check_update_summary">Автоматично перевіряти оновлення при відкритті додатку</string>
<string name="grant_root_failed">Не вдалося отримати root!</string> <string name="grant_root_failed">Не вдалося надати root-права!</string>
<string name="action">Action</string> <string name="action">Дія</string>
<string name="close">Close</string> <string name="close">Закрити</string>
<string name="enable_web_debugging">Увімкнути налагодження WebView</string> <string name="enable_web_debugging">Увімкнути налагодження WebView</string>
<string name="enable_web_debugging_summary">Використовується для налагодження WebUI. Будь ласка, вмикайте тільки за потреби.</string> <string name="enable_web_debugging_summary">Можна використовувати для налагодження WebUI. Будь ласка, вмикайте лише за потреби.</string>
<string name="direct_install">Пряме встановлення (рекомендовано)</string> <string name="direct_install">Пряме встановлення (рекомендовано)</string>
<string name="select_file">Виберіть файл</string> <string name="select_file">Виберіть образ для патчу</string>
<string name="install_inactive_slot">Встановлення в неактивний слот (Після OTA)</string> <string name="install_inactive_slot">Встановити в неактивний слот (після OTA)</string>
<string name="install_inactive_slot_warning">Ваш пристрій буде **ПРИМУСОВО** завантажено в поточний неактивний слот після перезавантаження! <string name="install_inactive_slot_warning">Ваш пристрій буде **ПРИМУСОВО** завантажено в поточний неактивний слот після перезавантаження!\nВикористовуйте цю опцію лише після завершення OTA.\nПродовжити?</string>
\n Використовуйте цю опцію тільки після завершення OTA.
\n Продовжити?</string>
<string name="install_next">Далі</string> <string name="install_next">Далі</string>
<string name="select_file_tip">%1$s образ розділу рекомендується</string> <string name="select_file_tip">Рекомендується образ розділу %1$s</string>
<string name="select_kmi">Виберіть KMI</string> <string name="select_file_tip_vendor">(нестабільно)</string>
<string name="select_kmi">Вибрати KMI</string>
<string name="settings_uninstall">Видалити</string> <string name="settings_uninstall">Видалити</string>
<string name="settings_uninstall_temporary">Тимчасово видалити</string> <string name="settings_uninstall_temporary">Тимчасово видалити</string>
<string name="settings_uninstall_permanent">Назавжди видалити</string> <string name="settings_uninstall_permanent">Видалити назавжди</string>
<string name="settings_restore_stock_image">Відновити Стоковий образ</string> <string name="settings_restore_stock_image">Відновити стоковий образ</string>
<string name="settings_uninstall_temporary_message">Тимчасово видалити KernelSU, відновити початковий стан після наступного перезавантаження.</string> <string name="settings_uninstall_temporary_message">Тимчасово видалити KernelSU, відновлення до початкового стану після наступного перезавантаження.</string>
<string name="settings_uninstall_permanent_message">Видалити KernelSU (Root і всі модулі) повністю і назавжди.</string> <string name="settings_uninstall_permanent_message">Повне та остаточне видалення KernelSU (Root та всі модулі).</string>
<string name="settings_restore_stock_image_message">Відновити стоковий заводський образ (якщо є резервна копія), зазвичай використовується перед OTA; якщо вам потрібно видалити KernelSU, використовуйте \"Назавжди видалити\".</string> <string name="settings_restore_stock_image_message">Відновити стоковий заводський образ (якщо існує резервна копія), зазвичай використовується перед OTA; якщо потрібно видалити KernelSU, використовуйте "Видалити назавжди".</string>
<string name="flashing">Прошивка</string> <string name="flashing">Прошивка</string>
<string name="flash_success">Прошивку виконано</string> <string name="flash_success">Прошивка успішна</string>
<string name="flash_failed">Прошивка не виконана</string> <string name="flash_failed">Прошивка не вдалася</string>
<string name="selected_lkm">Обрано lkm: %s</string> <string name="selected_lkm">Обраний LKM: %s</string>
<string name="save_log">Зберегти Журнали</string> <string name="save_log">Зберегти логи</string>
<string name="log_saved">Logs saved</string> <string name="log_saved">Логи збережено</string>
<string name="sus_su_mode">SuS SU mode:</string> <string name="sus_su_mode">Режим SuS SU:</string>
<!-- Module related --> <!-- Module related -->
<string name="module_install_confirm">confirm install module %1$s</string> <string name="module_install_confirm">Підтвердити встановлення модуля %1$s?</string>
<string name="unknown_module">unknown module</string> <string name="unknown_module">невідомий модуль</string>
<!-- Restore related --> <!-- Restore related -->
<string name="restore_confirm_title">Confirm Module Restoration</string> <string name="restore_confirm_title">Підтвердити відновлення модулів</string>
<string name="restore_confirm_message">This operation will overwrite all existing modules. Continue?</string> <string name="restore_confirm_message">Ця операція перезапише всі існуючі модулі. Продовжити?</string>
<string name="confirm">Confirm</string> <string name="confirm">Підтвердити</string>
<string name="cancel">Cancel</string> <string name="cancel">Скасувати</string>
<!-- Backup related --> <!-- Backup related -->
<string name="backup_success">Backup successful (tar.gz)</string> <string name="backup_success">Резервне копіювання успішне (tar.gz)</string>
<string name="backup_failed">Backup failed: %1$s</string> <string name="backup_failed">Не вдалося створити резервну копію: %1$s</string>
<string name="backup_modules">backup modules</string> <string name="backup_modules">резервне копіювання модулів</string>
<string name="restore_modules">restore modules</string> <string name="restore_modules">відновлення модулів</string>
<!-- Restore related messages --> <!-- Restore related messages -->
<string name="restore_success">Modules restored successfully, restart required</string> <string name="restore_success">Модулі успішно відновлено, потрібне перезавантаження</string>
<string name="restore_failed">Restore failed: %1$s</string> <string name="restore_failed">Не вдалося відновити: %1$s</string>
<string name="restart_now">Restart Now</string> <string name="restart_now">Перезавантажити зараз</string>
<string name="unknown_error">Unknown error</string> <string name="unknown_error">Невідома помилка</string>
<!-- Command related --> <!-- Command related -->
<string name="command_execution_failed">Command execution failed: %1$s</string> <string name="command_execution_failed">Не вдалося виконати команду: %1$s</string>
<!-- Allowlist related --> <!-- Allowlist related -->
<string name="allowlist_backup_success">Allowlist backup successful</string> <string name="allowlist_backup_success">Резервне копіювання білого списку успішне</string>
<string name="allowlist_backup_failed">Allowlist backup failed: %1$s</string> <string name="allowlist_backup_failed">Не вдалося створити резервну копію білого списку: %1$s</string>
<string name="allowlist_restore_confirm_title">Confirm Allowlist Restoration</string> <string name="allowlist_restore_confirm_title">Підтвердити відновлення білого списку</string>
<string name="allowlist_restore_confirm_message">This operation will overwrite the current allowlist. Continue?</string> <string name="allowlist_restore_confirm_message">Ця операція перезапише поточний білий список. Продовжити?</string>
<string name="allowlist_restore_success">Allowlist restored successfully</string> <string name="allowlist_restore_success">Білий список успішно відновлено</string>
<string name="allowlist_restore_failed">Allowlist restore failed: %1$s</string> <string name="allowlist_restore_failed">Не вдалося відновити білий список: %1$s</string>
<string name="backup_allowlist">Backup Allowlist</string> <string name="backup_allowlist">Резервна копія білого списку</string>
<string name="restore_allowlist">Restore Allowlist</string> <string name="restore_allowlist">Відновити білий список</string>
<string name="settings_custom_background">Custom App Background</string> <string name="settings_custom_background">Власний фон додатку</string>
<string name="settings_custom_background_summary">Select an image as background</string> <string name="settings_custom_background_summary">Вибрати зображення як фон</string>
<string name="settings_card_alpha">Navigation bar transparency</string> <string name="settings_card_alpha">Прозорість панелі навігації</string>
<string name="home_android_version">Android version</string> <string name="home_android_version">Версія Android</string>
<string name="home_device_model">Device model</string> <string name="home_device_model">Модель пристрою</string>
<string name="su_not_allowed">Granting superuser to %s is not allowed</string> <string name="su_not_allowed">Надання прав суперкористувача для %s заборонено</string>
<string name="settings_disable_su">Disable su compatibility</string> <string name="settings_disable_su">Вимкнути сумісність з su</string>
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (existing root processes will not be affected).</string> <string name="settings_disable_su_summary">Тимчасово заборонити будь-яким додаткам отримувати root-права через команду su (існуючі root-процеси не будуть зачеплені).</string>
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string> <string name="module_install_multiple_confirm_with_names">Ви впевнені, що хочете встановити наступні %1$d модулі? \n\n%2$s</string>
<string name="more_settings">More settings</string> <string name="more_settings">Більше налаштувань</string>
<string name="selinux">SELinux</string> <string name="selinux">SELinux</string>
<string name="selinux_enabled">Enabled</string> <string name="selinux_enabled">Увімкнено</string>
<string name="selinux_disabled">Disabled</string> <string name="selinux_disabled">Вимкнено</string>
<string name="simple_mode">Simplicity mode</string> <string name="simple_mode">Спрощений режим</string>
<string name="simple_mode_summary">Hides unnecessary cards when turned on</string> <string name="simple_mode_summary">Приховує непотрібні картки при ввімкненні</string>
<string name="hide_kernel_kernelsu_version">Hide kernel version</string> <string name="hide_kernel_kernelsu_version">Приховати версію ядра</string>
<string name="hide_kernel_kernelsu_version_summary">Hide kernel version</string> <string name="hide_kernel_kernelsu_version_summary">Приховує версію ядра</string>
<string name="hide_other_info">Hide other info</string> <string name="hide_other_info">Приховати іншу інформацію</string>
<string name="hide_other_info_summary">Hides information about the number of super users, modules and KPM modules on the home page</string> <string name="hide_other_info_summary">Приховує червону крапку про кількість суперкористувачів, модулів та KPM-модулів на сторінці навігаційної панелі</string>
<string name="hide_susfs_status">Hide SuSFS status</string> <string name="hide_susfs_status">Приховати статус SuSFS</string>
<string name="hide_susfs_status_summary">Hide SuSFS status information on the home page</string> <string name="hide_susfs_status_summary">Приховує інформацію про статус SuSFS на головній сторінці</string>
<string name="hide_link_card">Hide Link Card Status</string> <string name="hide_link_card">Приховати картку посилань</string>
<string name="hide_link_card_summary">Hide link card information on the home page</string> <string name="hide_link_card_summary">Приховує інформацію на картці посилань на головній сторінці</string>
<string name="theme_mode">Theme</string> <string name="hide_tag_card">Приховати рядки тегів модуля</string>
<string name="theme_follow_system">Follow system</string> <string name="hide_tag_card_summary">Приховує мітки з назвою папки та розміром у картках модулів</string>
<string name="theme_light">Light</string> <string name="theme_mode">Тема</string>
<string name="theme_dark">Dark</string> <string name="theme_follow_system">Як у системі</string>
<string name="manual_hook">Manual Hook</string> <string name="theme_light">Світла</string>
<string name="dynamic_color_title">Dynamic colours</string> <string name="theme_dark">Темна</string>
<string name="dynamic_color_summary">Dynamic colours using system themes</string> <string name="manual_hook">Ручний хук</string>
<string name="choose_theme_color">Choose a theme colour</string> <string name="dynamic_color_title">Динамічні кольори</string>
<string name="color_default">Blue</string> <string name="dynamic_color_summary">Динамічні кольори з використанням системних тем</string>
<string name="color_green">Green</string> <string name="choose_theme_color">Вибрати колір теми</string>
<string name="color_purple">Purple</string> <string name="color_default">Синій</string>
<string name="color_orange">Orange</string> <string name="color_green">Зелений</string>
<string name="color_pink">Pink</string> <string name="color_purple">Фіолетовий</string>
<string name="color_gray">Gray</string> <string name="color_orange">Помаранчевий</string>
<string name="color_yellow">Yellow</string> <string name="color_pink">Рожевий</string>
<string name="horizon_kernel">Install Anykernel3</string> <string name="color_gray">Сірий</string>
<string name="horizon_kernel_summary">Flash AnyKernel3 kernel file</string> <string name="color_yellow">Жовтий</string>
<string name="root_required">Requires root privileges</string> <string name="horizon_kernel">Встановити Anykernel3</string>
<string name="reboot_complete_title">Scrubbing complete</string> <string name="horizon_kernel_summary">Прошити файл ядра AnyKernel3</string>
<string name="reboot_complete_msg">Whether to reboot immediately</string> <string name="root_required">Потрібні права суперкористувача</string>
<string name="yes">Yes</string> <string name="reboot_complete_title">Очищення завершено</string>
<string name="no">No</string> <string name="reboot_complete_msg">Перезавантажитися негайно?</string>
<string name="failed_reboot">Reboot Failed</string> <string name="yes">Так</string>
<string name="no">Ні</string>
<string name="failed_reboot">Не вдалося перезавантажити</string>
<string name="kpm_title">KPM</string> <string name="kpm_title">KPM</string>
<string name="kpm_empty">No installed kernel modules at this time</string> <string name="kpm_empty">На даний момент немає встановлених модулів ядра</string>
<string name="kpm_version">Version</string> <string name="kpm_version">Версія</string>
<string name="kpm_author">Author</string> <string name="kpm_author">Автор</string>
<string name="kpm_uninstall">Uninstall</string> <string name="kpm_uninstall">Видалити</string>
<string name="kpm_uninstall_success">Uninstalled successfully</string> <string name="kpm_uninstall_success">Видалено успішно</string>
<string name="kpm_uninstall_failed">Failed to uninstall</string> <string name="kpm_uninstall_failed">Не вдалося видалити</string>
<string name="kpm_install_success">Load of kpm module successful</string> <string name="kpm_install_success">Завантаження модуля kpm успішне</string>
<string name="kpm_install_failed">Load of kpm module failed</string> <string name="kpm_install_failed">Не вдалося завантажити модуль kpm</string>
<string name="kpm_args">Parameters</string> <string name="kpm_args">Параметри</string>
<string name="kpm_control">Execute</string> <string name="kpm_control">Виконати</string>
<string name="home_kpm_version">KPM Version</string> <string name="home_kpm_version">Версія KPM</string>
<string name="close_notice">Close</string> <string name="close_notice">Закрити</string>
<string name="kernel_module_notice">The following kernel module functions were developed by KernelPatch and modified to include the kernel module functions of SukiSU Ultra</string> <string name="kernel_module_notice">Наступні функції модулів ядра були розроблені KernelPatch та модифіковані для включення функцій модулів ядра SukiSU Ultra</string>
<string name="home_ContributionCard_kernelsu">SukiSU Ultra Look forward to</string> <string name="home_ContributionCard_kernelsu">SukiSU Ultra з нетерпінням чекає</string>
<string name="kpm_control_success">Success</string> <string name="kpm_control_success">Успішно</string>
<string name="kpm_control_failed">Failed</string> <string name="kpm_control_failed">Невдача</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but we still appreciate the official KernelSU and MKSU etc. for their contributions!</string> <string name="home_click_to_ContributionCard_kernelsu">У майбутньому SukiSU Ultra буде відносно незалежною гілкою KSU, але ми все ще вдячні офіційному KernelSU, MKSU та іншим за їхній внесок!</string>
<string name="not_supported">Unsupported</string> <string name="not_supported">Не підтримується</string>
<string name="supported">Supported</string> <string name="supported">Підтримується</string>
<string name="kernel_patched">Kernel not patched</string> <string name="kernel_patched">Ядро не пропатчене</string>
<string name="kernel_not_enabled">Kernel not configured</string> <string name="kernel_not_enabled">Ядро не налаштоване</string>
<string name="custom_settings">Custom settings</string> <string name="custom_settings">Власні налаштування</string>
<string name="kpm_install_mode">KPM Install</string> <string name="kpm_install_mode">Встановлення KPM</string>
<string name="kpm_install_mode_load">Load</string> <string name="kpm_install_mode_load">Завантажити</string>
<string name="kpm_install_mode_embed">Embed</string> <string name="kpm_install_mode_embed">Вбудувати</string>
<string name="kpm_install_mode_description">Please select: %1\$s Module Installation Mode \n\nLoad: Temporarily load the module \nEmbedded: Permanently install into the system</string> <string name="kpm_install_mode_description">Будь ласка, оберіть: %1$s режим встановлення модуля \n\nЗавантажити: Тимчасово завантажити модуль \nВбудувати: Постійно встановити в систему</string>
<string name="snackbar_failed_to_check_module_file">Unable to check if module file exists</string> <string name="snackbar_failed_to_check_module_file">Не вдалося перевірити існування файлу модуля</string>
<string name="theme_color">Theme Color</string> <string name="theme_color">Колір теми</string>
<string name="invalid_file_type">Incorrect file type! Please select .kpm file.</string> <string name="invalid_file_type">Неправильний тип файлу! Будь ласка, виберіть файл .kpm.</string>
<string name="confirm_uninstall_title_with_filename">Uninstall</string> <string name="confirm_uninstall_title_with_filename">Видалити</string>
<string name="confirm_uninstall_content">The following KPM will be uninstalled: %s</string> <string name="confirm_uninstall_content">Буде видалено наступний KPM: %s</string>
<string name="settings_susfs_toggle_summary">Disable kprobe hooks created by KernelSU, using inline hooks instead, which is similar to non-GKI kernel hooking method.</string> <string name="settings_susfs_toggle_summary">Вимкнути хуки kprobe, створені KernelSU, використовуючи натомість інлайн-хуки, що схоже на метод хуків для ядер без GKI.</string>
<string name="image_editor_hint">Use two fingers to zoom the image, and one finger to drag it to adjust the position</string> <string name="image_editor_hint">Використовуйте два пальці для масштабування зображення та один палець для перетягування, щоб налаштувати положення</string>
<string name="reprovision">Reprovision</string> <string name="reprovision">Переналаштувати</string>
<!-- Kernel Flash Progress Related --> <!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string> <string name="horizon_flash_title">Прошивка ядра</string>
<string name="horizon_logs_label">Logs:</string> <string name="horizon_logs_label">Логи:</string>
<string name="horizon_flash_complete">Flash Complete</string> <string name="horizon_flash_complete">Прошивка завершена</string>
<!-- Flash Status Related --> <!-- Flash Status Related -->
<string name="horizon_preparing">Preparing</string> <string name="horizon_preparing">Підготовка</string>
<string name="horizon_cleaning_files">Cleaning files</string> <string name="horizon_cleaning_files">Очищення файлів</string>
<string name="horizon_copying_files">Copying files</string> <string name="horizon_copying_files">Копіювання файлів</string>
<string name="horizon_extracting_tool">Extracting flash tool</string> <string name="horizon_extracting_tool">Розпакування інструменту прошивки</string>
<string name="horizon_patching_script">Patching flash script</string> <string name="horizon_patching_script">Патчинг скрипту прошивки</string>
<string name="horizon_flashing">Flashing kernel</string> <string name="horizon_flashing">Прошивка ядра</string>
<string name="horizon_flash_complete_status">Flash completed</string> <string name="horizon_flash_complete_status">Прошивка завершена</string>
<!-- Slot selection related strings --> <!-- Slot selection related strings -->
<string name="select_slot_title">Select Flash Slot</string> <string name="select_slot_title">Вибрати слот для прошивки</string>
<string name="select_slot_description">Please select the target slot for flashing boot</string> <string name="select_slot_description">Будь ласка, виберіть цільовий слот для прошивки boot</string>
<string name="slot_a">Slot A</string> <string name="slot_a">Слот A</string>
<string name="slot_b">Slot B</string> <string name="slot_b">Слот B</string>
<string name="selected_slot">Selected slot: %1$s</string> <string name="selected_slot">Вибраний слот: %1$s</string>
<string name="horizon_getting_original_slot">Getting the original slot</string> <string name="horizon_getting_original_slot">Отримання оригінального слоту</string>
<string name="horizon_setting_target_slot">Setting the specified slot</string> <string name="horizon_setting_target_slot">Встановлення вказаного слоту</string>
<string name="horizon_restoring_original_slot">Restore Default Slot</string> <string name="horizon_restoring_original_slot">Відновити слот за замовчуванням</string>
<string name="current_slot">Current Slot%1$s </string> <string name="current_slot">Поточний системний слот за замовчуванням: %1$s</string>
<!-- Error Messages --> <!-- Error Messages -->
<string name="horizon_copy_failed">Copy failed</string> <string name="horizon_copy_failed">Не вдалося скопіювати</string>
<string name="horizon_unknown_error">Unknown error</string> <string name="horizon_unknown_error">Невідома помилка</string>
<string name="flash_failed_message">Flash failed</string> <string name="flash_failed_message">Прошивка не вдалася</string>
<!-- lkm/gki install --> <!-- lkm/gki install -->
<string name="Lkm_install_methods">LKM repair/installation</string> <string name="Lkm_install_methods">Відновлення/встановлення LKM</string>
<string name="GKI_install_methods">Flashing AnyKernel3</string> <string name="GKI_install_methods">Прошивка AnyKernel3</string>
<string name="kernel_version_log">Kernel version%1$s</string> <string name="kernel_version_log">Версія ядра: %1$s</string>
<string name="tool_version_log">Using the patching tool%1$s</string> <string name="tool_version_log">Використовується інструмент для патчингу: %1$s</string>
<string name="configuration">Configure</string> <string name="configuration">Налаштувати</string>
<string name="app_settings">Application Settings</string> <string name="app_settings">Налаштування додатку</string>
<string name="tools">Tools</string> <string name="tools">Інструменти</string>
<!-- String resources used in SuperUser --> <!-- String resources used in SuperUser -->
<string name="no_apps_found">Application not found</string> <string name="no_apps_found">Додаток не знайдено</string>
<string name="selinux_enabled_toast">SELinux Enabled</string> <string name="selinux_enabled_toast">SELinux увімкнено</string>
<string name="selinux_disabled_toast">SELinux Disabled</string> <string name="selinux_disabled_toast">SELinux вимкнено</string>
<string name="selinux_change_failed">SELinux Status change failed</string> <string name="selinux_change_failed">Не вдалося змінити статус SELinux</string>
<string name="advanced_settings">Advanced Settings</string> <string name="advanced_settings">Розширені налаштування</string>
<string name="appearance_settings">Customize the toolbar</string> <string name="appearance_settings">Налаштувати панель інструментів</string>
<string name="back">Comeback</string> <string name="back">Повернутися</string>
<string name="susfs_enabled">SuSFS enabled</string> <string name="susfs_enabled">SuSFS увімкнено</string>
<string name="susfs_disabled">SuSFS disabled</string> <string name="susfs_disabled">SuSFS вимкнено</string>
<string name="background_set_success">Background set successfully</string> <string name="background_set_success">Фон успішно встановлено</string>
<string name="background_removed">Removed custom backgrounds</string> <string name="background_removed">Видалено власні фони</string>
<string name="icon_switch_title">Alternate icon</string> <string name="icon_switch_title">Альтернативна іконка</string>
<string name="icon_switch_summary">Change the launcher icon to KernelSU\'s icon.</string> <string name="icon_switch_summary">Змінити іконку запуску на іконку KernelSU.</string>
<string name="icon_switched">Icon switched</string> <string name="icon_switched">Іконку змінено</string>
<!-- KPM display settings --> <!-- KPM display settings -->
<string name="show_kpm_info">Display KPM Function</string> <string name="show_kpm_info">Приховати функцію KPM</string>
<string name="show_kpm_info_summary">Display KPM information and Function in home and bottom bar (Need to reopen the app)</string> <string name="show_kpm_info_summary">Приховує інформацію та функцію KPM на головному екрані та в нижній панелі</string>
<!-- Webui X settings --> <!-- Webui X settings -->
<string name="use_webuix">Select the WebUI engine to use</string> <string name="use_webuix">Виберіть рушій WebUI для використання</string>
<string name="engine_auto_select">Automatic Selection</string> <string name="engine_auto_select">Автоматичний вибір</string>
<string name="engine_force_webuix">Force the use of WebUI X</string> <string name="engine_force_webuix">Примусово використовувати WebUI X</string>
<string name="engine_force_ksu">Mandatory use of KSU WebUI</string> <string name="engine_force_ksu">Примусово використовувати KSU WebUI</string>
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string> <string name="use_webuix_eruda">Впровадити Eruda у WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string> <string name="use_webuix_eruda_summary">Впровадити консоль налагодження у WebUI X для полегшення налагодження. Потребує увімкненого веб-налагодження.</string>
<!-- DPI setting related strings --> <!-- DPI setting related strings -->
<string name="app_dpi_title">Applied DPI</string> <string name="app_dpi_title">Застосований DPI</string>
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string> <string name="app_dpi_summary">Налаштувати щільність відображення екрана лише для поточного додатку</string>
<string name="dpi_size_small">Small </string> <string name="dpi_size_small">Маленький</string>
<string name="dpi_size_medium">Medium </string> <string name="dpi_size_medium">Середній</string>
<string name="dpi_size_large">Big</string> <string name="dpi_size_large">Великий</string>
<string name="dpi_size_extra_large">oversize</string> <string name="dpi_size_extra_large">Надвеликий</string>
<string name="dpi_size_custom">customizable</string> <string name="dpi_size_custom">Власний</string>
<string name="dpi_apply_settings">Applying DPI settings</string> <string name="dpi_apply_settings">Застосування налаштувань DPI</string>
<string name="dpi_confirm_title">Confirm DPI change</string> <string name="dpi_confirm_title">Підтвердити зміну DPI</string>
<string name="dpi_confirm_message">Are you sure you want to change the application DPI from %1$d to %2$d?</string> <string name="dpi_confirm_message">Ви впевнені, що хочете змінити DPI додатку з %1$d на %2$d?</string>
<string name="dpi_confirm_summary">Application needs to be restarted to apply the new DPI settings, does not affect the system status bar or other applications</string> <string name="dpi_confirm_summary">Додаток потрібно перезапустити, щоб застосувати нові налаштування DPI; це не вплине на системний рядок стану або інші додатки</string>
<string name="dpi_applied_success">DPI has been set to %1$d, effective after restarting the application</string> <string name="dpi_applied_success">DPI встановлено на %1$d, набуде чинності після перезапуску додатку</string>
<!-- Language settings related strings --> <!-- Language settings related strings -->
<string name="language_setting">App Language</string> <string name="language_setting">Мова додатку</string>
<string name="language_follow_system">Follow System</string> <string name="language_follow_system">Як у системі</string>
<string name="language_changed">Language changed, restarting to apply changes</string> <string name="language_changed">Мову змінено, перезапуск для застосування змін</string>
<string name="settings_card_dim">Card Darkness Adjustment</string> <string name="settings_card_dim">Налаштування затемнення карток</string>
<!-- Flash related --> <!-- Flash related -->
<string name="error_code">error code</string> <string name="error_code">код помилки</string>
<string name="check_log">Please check the log</string> <string name="check_log">Будь ласка, перевірте лог</string>
<string name="installing_module">Module being installed %1$d/%2$d</string> <string name="installing_module">Встановлення модуля %1$d/%2$d</string>
<string name="module_failed_count">%d Failed to install a new module</string> <string name="module_failed_count">Не вдалося встановити %d новий модуль</string>
<string name="module_download_error">Module download failed</string> <string name="module_download_error">Не вдалося завантажити модуль</string>
<string name="kernel_flashing">Kernel Flashing</string> <string name="kernel_flashing">Прошивка ядра</string>
<!-- 分类相关 --> <!-- 分类相关 -->
<string name="category_all_apps">All</string> <string name="category_all_apps">Всі</string>
<string name="category_root_apps">Root</string> <string name="category_root_apps">Root</string>
<string name="category_custom_apps">Custom</string> <string name="category_custom_apps">Власні</string>
<string name="category_default_apps">Default</string> <string name="category_default_apps">За замовчуванням</string>
<!-- 排序相关 --> <!-- 排序相关 -->
<string name="sort_name_asc">Ascending order of name</string> <string name="sort_name_asc">Назва за зростанням</string>
<string name="sort_name_desc">Name descending</string> <string name="sort_name_desc">Назва за спаданням</string>
<string name="sort_install_time_new">Installation time (new)</string> <string name="sort_install_time_new">Час встановлення (нові)</string>
<string name="sort_install_time_old">Installation time (old)</string> <string name="sort_install_time_old">Час встановлення (старі)</string>
<string name="sort_size_desc">descending order of size</string> <string name="sort_size_desc">Розмір за спаданням</string>
<string name="sort_size_asc">ascending order of size</string> <string name="sort_size_asc">Розмір за зростанням</string>
<string name="sort_usage_freq">frequency of use</string> <string name="sort_usage_freq">Частота використання</string>
<!-- 状态相关 --> <!-- 状态相关 -->
<string name="no_apps_in_category">No application in this category</string> <string name="no_apps_in_category">Немає додатків у цій категорії</string>
<!-- 标签相关 --> <!-- 标签相关 -->
<!-- FAB菜单相关 --> <string name="deny_authorization">Заборонити права</string>
<string name="deny_authorization">Delegation of authority</string> <string name="grant_authorization">Надати права</string>
<string name="grant_authorization">Authorizations</string> <string name="unmount_modules">Відмонтувати монтування модулів</string>
<string name="unmount_modules">Unmounting Module Mounts</string> <string name="disable_unmount">Вимкнути відмонтування модулів</string>
<string name="disable_unmount">Disable uninstall module mounting</string> <string name="expand_menu">Розгорнути меню</string>
<string name="expand_menu">Expand menu</string> <string name="collapse_menu">Згорнути меню</string>
<string name="collapse_menu">Put away the menu</string> <string name="scroll_to_top">Вгору</string>
<string name="scroll_to_top">Top</string> <string name="scroll_to_bottom">Вниз</string>
<string name="scroll_to_bottom">Bottom</string> <string name="selected">Вибрано</string>
<string name="selected">Selected</string> <string name="select">Вибрати</string>
<string name="select">option</string>
<!-- BottomSheet相关 --> <!-- BottomSheet相关 -->
<string name="menu_options">Menu Options</string> <string name="menu_options">Опції меню</string>
<string name="sort_options">Sort by</string> <string name="sort_options">Сортувати за</string>
<string name="app_categories">Application Type Selection</string> <string name="app_categories">Вибір типу додатку</string>
<!-- SuSFS Configuration --> <!-- SuSFS Configuration -->
<string name="susfs_config_title">Налаштування SuSFS</string>
<string name="susfs_config_description">Опис налаштувань</string>
<string name="susfs_config_description_text">Ця функція дозволяє налаштовувати підміну значення uname та часу збірки SuSFS. Введіть потрібні значення та натисніть "Застосувати", щоб вони набули чинності.</string>
<string name="susfs_uname_label">Значення Uname</string>
<string name="susfs_uname_placeholder">Будь ласка, введіть власне значення uname</string>
<string name="susfs_build_time_label">Підміна часу збірки</string>
<string name="susfs_build_time_placeholder">Будь ласка, введіть значення для підміни часу збірки</string>
<string name="susfs_current_value">Поточне значення: %s</string>
<string name="susfs_current_build_time">Поточний час збірки: %s</string>
<string name="susfs_reset_to_default">Скинути до замовчування</string>
<string name="susfs_apply">Застосувати</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">Підтвердити скидання</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">Не вдалося знайти файл ksu_susfs</string>
<string name="susfs_command_failed">Не вдалося виконати команду SuSFS</string>
<string name="susfs_command_error">Помилка виконання команди SuSFS: %s</string>
<string name="susfs_uname_set_success" formatted="false">Значення uname та час збірки SuSFS успішно встановлено: %s, %s</string>
<!-- SuSFS Settings Item --> <!-- SuSFS Settings Item -->
<string name="susfs_config_setting_title">Налаштування SuSFS</string>
<!-- 开机自启动相关 --> <!-- 开机自启动相关 -->
<string name="susfs_autostart_title">Автозапуск</string>
<string name="susfs_autostart_description">Автоматично застосовувати всі нестандартні конфігурації при перезавантаженні</string>
<string name="susfs_autostart_requirement">Для ввімкнення потрібно додати конфігурацію</string>
<string name="susfs_autostart_enable_failed">Не вдалося ввімкнути автозапуск</string>
<string name="susfs_autostart_disable_failed">Не вдалося вимкнути автозапуск</string>
<string name="susfs_autostart_error">Помилка конфігурації автозапуску: %s</string>
<string name="susfs_no_config_to_autostart">Немає доступної конфігурації для автозапуску</string>
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<!-- SuSFS Dialog Actions --> <string name="susfs_tab_basic_settings">Основні налаштування</string>
<string name="susfs_tab_sus_paths">Шляхи SUS</string>
<string name="susfs_tab_sus_mounts">Монтування SUS</string>
<string name="susfs_tab_try_umount">Спроба відмонтування</string>
<string name="susfs_tab_path_settings">Налаштування шляхів</string>
<string name="susfs_tab_enabled_features">Статус увімкнених функцій</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">Додати шлях SUS</string>
<string name="susfs_add_sus_mount">Додати монтування SUS</string>
<string name="susfs_add_try_umount">Додати спробу відмонтування</string>
<string name="susfs_sus_path_added_success">Шлях SUS успішно додано</string>
<string name="susfs_path_not_found_error">Помилка: шлях не знайдено</string>
<string name="susfs_path_label">Шлях</string>
<string name="susfs_mount_path_label">Шлях монтування</string>
<string name="susfs_path_placeholder">напр.: /system/addon.d</string>
<string name="susfs_no_paths_configured">Немає налаштованих шляхів SUS</string>
<string name="susfs_no_mounts_configured">Немає налаштованих монтувань SUS</string>
<string name="susfs_no_umounts_configured">Немає налаштованих спроб відмонтування</string>
<!-- SuSFS Umount Mode --> <!-- SuSFS Umount Mode -->
<string name="susfs_umount_mode_label">Режим відмонтування</string>
<string name="susfs_umount_mode_normal">Звичайне відмонтування (0)</string>
<string name="susfs_umount_mode_detach">Від\'єднане відмонтування (1)</string>
<string name="susfs_umount_mode_normal_short">Звичайний</string>
<string name="susfs_umount_mode_detach_short">Від\'єднаний</string>
<string name="susfs_umount_mode_display">Режим: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">Шлях для спроби відмонтування успішно додано: %s</string>
<string name="susfs_try_umount_added_saved">Спроба збереження шляху відмонтування успішна: %s</string>
<!-- SuSFS Run Umount --> <!-- SuSFS Run Umount -->
<string name="susfs_run_umount_confirm_title">Підтвердити виконання спроби відмонтування</string>
<string name="susfs_run_umount_confirm_message">Це негайно виконає всі налаштовані операції спроби відмонтування. Ви впевнені, що хочете продовжити?</string>
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">Скинути шляхи SUS</string>
<string name="susfs_reset_paths_message">Це видалить усі конфігурації шляхів SUS. Ви впевнені, що хочете продовжити?</string>
<string name="susfs_reset_mounts_title">Скинути монтування SUS</string>
<string name="susfs_reset_mounts_message">Це видалить усі конфігурації монтувань SUS. Ви впевнені, що хочете продовжити?</string>
<string name="susfs_reset_umounts_title">Скинути спроби відмонтування</string>
<string name="susfs_reset_umounts_message">Це видалить усі конфігурації спроб відмонтування. Ви впевнені, що хочете продовжити?</string>
<string name="susfs_reset_path_title">Скинути налаштування шляхів</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Шлях до Android Data</string>
<string name="susfs_sdcard_path_label">Шлях до SD-карти</string>
<string name="susfs_set_android_data_path">Встановити шлях до Android Data</string>
<string name="susfs_set_sdcard_path">Встановити шлях до SD-карти</string>
<!-- SuSFS Enabled Features --> <!-- SuSFS Enabled Features -->
<string name="susfs_enabled_features_description">Відображення поточного статусу увімкнених функцій SuSFS</string>
<string name="susfs_no_features_found">Інформацію про статус функцій не знайдено</string>
<string name="susfs_feature_enabled">Увімкнено</string>
<string name="susfs_feature_disabled">Вимкнено</string>
<!-- Feature Labels --> <!-- Feature Labels -->
<string name="sus_path_feature_label">Підтримка шляхів SUS</string>
<string name="sus_mount_feature_label">Підтримка монтувань SUS</string>
<string name="try_umount_feature_label">Підтримка спроб відмонтування</string>
<string name="spoof_uname_feature_label">Підтримка підміни uname</string>
<string name="spoof_cmdline_feature_label">Підміна Cmdline/Bootconfig</string>
<string name="open_redirect_feature_label">Підтримка Open Redirect</string>
<string name="enable_log_feature_label">Підтримка логування</string>
<string name="auto_default_mount_feature_label">Автоматичне монтування за замовчуванням</string>
<string name="auto_bind_mount_feature_label">Автоматичне прив\'язане монтування</string>
<string name="auto_try_umount_bind_feature_label">Автоматична спроба відмонтування прив\'язаного монтування</string>
<string name="hide_symbols_feature_label">Приховати символи KSU SUSFS</string>
<string name="magic_mount_feature_label">Підтримка Magic Mount</string>
<string name="sus_kstat_feature_label">Підтримка SUS Kstat</string>
<string name="sus_su_feature_label">Функція перемикання режиму SUS SU</string>
<!-- 可切换状态 --> <!-- 可切换状态 -->
<string name="susfs_feature_configurable">Настроювані функції SuSFS</string>
<string name="susfs_enable_log_label">Увімкнути лог SuSFS</string>
<string name="susfs_log_config_description">Увімкнути або вимкнути логування для SuSFS</string>
<string name="susfs_log_config_title">Налаштування логування SuSFS</string>
<string name="susfs_log_enabled">Увімкнення логування SuSFS</string>
<string name="susfs_log_disabled">Вимкнення логування SuSFS</string>
<string name="module_update_json">Оновити JSON</string>
<string name="module_update_json_copied">URL для оновлення JSON скопійовано в буфер обміну</string>
<!-- Settings related strings --> <!-- Settings related strings -->
<string name="show_more_module_info">Показувати більше інформації про модуль</string>
<string name="show_more_module_info_summary">Відображати додаткову інформацію про модуль, як-от URL-адреси для оновлення JSON</string>
<string name="susfs_execution_location_label">Місце виконання</string>
<string name="susfs_current_execution_location">Поточне місце виконання: %s</string>
<string name="susfs_execution_location_service">Сервіс</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">Виконувати після запуску системних сервісів</string>
<string name="susfs_execution_location_post_fs_data_description">Виконувати після монтування файлової системи, але до повного завантаження системи. Може спричинити бутлуп</string>
<string name="susfs_slot_info_title">Інформація про слот</string>
<string name="susfs_slot_info_description">Переглянути інформацію про поточний завантажувальний слот та скопіювати значення</string>
<string name="susfs_current_active_slot">Поточний активний слот: %s</string>
<string name="susfs_slot_uname">Uname: %s</string>
<string name="susfs_slot_build_time">Час збірки: %s</string>
<string name="susfs_slot_current_badge">Поточний</string>
<string name="susfs_slot_use_uname">Використовувати Uname</string>
<string name="susfs_slot_use_build_time">Використовувати час збірки</string>
<string name="susfs_slot_info_unavailable">Не вдалося отримати інформацію про слот</string>
<!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">Модуль автозапуску SuSFS увімкнено, шлях до модуля: %s</string>
<string name="susfs_autostart_disabled_success">Модуль автозапуску SuSFS вимкнено</string>
<!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Налаштування Kstat</string>
<string name="kstat_static_config_added">Статичну конфігурацію Kstat додано: %1$s</string>
<string name="kstat_config_removed">Конфігурацію Kstat видалено: %1$s</string>
<string name="kstat_path_added">Шлях Kstat додано: %1$s</string>
<string name="kstat_path_removed">Шлях Kstat видалено: %1$s</string>
<string name="kstat_updated">Kstat оновлено: %1$s</string>
<string name="kstat_full_clone_updated">Повне клонування Kstat оновлено: %1$s</string>
<string name="add_kstat_statically_title">Додати статичну конфігурацію Kstat</string>
<string name="file_or_directory_path_label">Шлях до файлу/каталогу</string>
<string name="hint_use_default_value">Підказка: Ви можете використовувати "default" для використання оригінального значення</string>
<string name="add_kstat_path_title">Додати шлях Kstat</string>
<string name="add">Додати</string>
<string name="reset_kstat_config_title">Скинути конфігурацію Kstat</string>
<string name="reset_kstat_config_message">Ви впевнені, що хочете очистити всі конфігурації Kstat? Цю дію неможливо скасувати.</string>
<string name="kstat_config_description_title">Опис конфігурації Kstat</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_statically: Статична інформація про файли/каталоги</string>
<string name="kstat_config_description_add">• add_sus_kstat: Додати шлях перед прив\'язаним монтуванням, зберігаючи оригінальну інформацію</string>
<string name="kstat_config_description_update">• update_sus_kstat: Оновити цільовий ino, залишивши розмір та блоки без змін</string>
<string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: Оновити лише ino, залишивши інші оригінальні значення</string>
<string name="static_kstat_config">Статична конфігурація Kstat</string>
<string name="kstat_path_management">Керування шляхами Kstat</string>
<string name="no_kstat_config_message">Конфігурації Kstat ще немає, натисніть кнопку вище, щоб додати</string>
<!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">Керування приховуванням монтувань SUS</string>
<string name="susfs_hide_mounts_control_description">Керуйте поведінкою приховування монтувань SUS для процесів</string>
<string name="susfs_hide_mounts_for_all_procs_label">Приховувати монтування SUS для всіх процесів</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">Якщо увімкнено, монтування SUS будуть приховані від усіх процесів, включно з процесами KSU</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">Якщо вимкнено, монтування SUS будуть приховані лише від процесів, що не належать KSU; процеси KSU зможуть бачити монтування</string>
<string name="susfs_hide_mounts_all_enabled">Увімкнено приховування монтувань SUS для всіх процесів</string>
<string name="susfs_hide_mounts_all_disabled">Вимкнено приховування монтувань SUS для всіх процесів</string>
<string name="susfs_hide_mounts_recommendation">Рекомендується встановлювати у вимкнений стан після розблокування екрана, або на етапі service.sh чи boot-completed.sh, оскільки це повинно виправити проблему з деякими рутованими додатками, які залежать від монтувань, створених процесом KSU</string>
<string name="susfs_hide_mounts_current_setting">Поточне налаштування: %s</string>
<string name="susfs_hide_mounts_setting_all">Приховувати для всіх процесів</string>
<string name="susfs_hide_mounts_setting_non_ksu">Приховувати лише для процесів, що не належать KSU</string>
<string name="susfs_run">Запустити</string>
<string name="kernel_simple_kernel">Спрощений режим версії ядра</string>
<string name="kernel_simple_kernel_summary">Увімкнути або вимкнути спрощене відображення версії ядра SukiSU</string>
<string name="susfs_android_data_path_set">Шлях до Android Data встановлено на: %s</string>
<string name="susfs_sdcard_path_set">Шлях до SD-карти встановлено на: %s</string>
<string name="susfs_path_setup_warning">Налаштування шляху може бути не повністю успішним, але шляхи SUS будуть додаватися</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">Резервне копіювання</string>
<string name="susfs_backup_description">Створити резервну копію всіх конфігурацій SuSFS. Файл резервної копії включатиме всі налаштування, шляхи та конфігурації.</string>
<string name="susfs_backup_create">Створити резервну копію</string>
<string name="susfs_backup_success">Резервну копію створено успішно: %s</string>
<string name="susfs_backup_failed">Не вдалося створити резервну копію: %s</string>
<string name="susfs_backup_file_not_found">Файл резервної копії не знайдено</string>
<string name="susfs_backup_invalid_format">Недійсний формат файлу резервної копії</string>
<string name="susfs_backup_version_mismatch">Невідповідність версії резервної копії, але буде зроблена спроба відновлення</string>
<string name="susfs_restore_title">Відновлення</string>
<string name="susfs_restore_description">Відновити конфігурації SuSFS з файлу резервної копії. Це перезапише всі поточні налаштування.</string>
<string name="susfs_restore_select_file">Вибрати файл резервної копії</string>
<string name="susfs_restore_success" formatted="false">Конфігурацію успішно відновлено з резервної копії, створеної %s на пристрої: %s</string>
<string name="susfs_restore_failed">Не вдалося відновити: %s</string>
<string name="susfs_restore_confirm_title">Підтвердити відновлення</string>
<string name="susfs_restore_confirm_description">Це перезапише всі поточні конфігурації SuSFS. Ви впевнені, що хочете продовжити?</string>
<string name="susfs_restore_confirm">Відновити</string>
<string name="susfs_backup_info_date">Дата резервної копії: %s</string>
<string name="susfs_backup_info_device">Пристрій: %s</string>
<string name="susfs_backup_info_version">Версія: %s</string>
<string name="hide_bl_script">Приховати скрипт BL</string>
<string name="hide_bl_script_description">Увімкнути скрипти для приховування статусу розблокування завантажувача</string>
<string name="cleanup_residue">Очистити залишки</string>
<string name="cleanup_residue_description">Очищення залишкових файлів та каталогів різних модулів та інструментів (може призвести до випадкового видалення, втрати даних та неможливості завантаження, використовуйте з обережністю)</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">Chưa cài đặt</string> <string name="home_not_installed">Chưa cài đặt</string>
<string name="home_click_to_install">Nhấn để cài đặt</string> <string name="home_click_to_install">Nhấn để cài đặt</string>
<string name="home_working">Đang hoạt động</string> <string name="home_working">Đang hoạt động</string>
<string name="home_working_version">Phiên bản: %d</string> <string name="home_working_version">Phiên bản: %s</string>
<string name="home_unsupported">Không được hỗ trợ</string> <string name="home_unsupported">Không được hỗ trợ</string>
<string name="home_unsupported_reason">Không phát hiện được trình điều khiển SukiSU Ultra trên Kernel của bạn, Kernel sai?</string> <string name="home_unsupported_reason">Không phát hiện được trình điều khiển SukiSU Ultra trên Kernel của bạn, Kernel sai?</string>
<string name="home_kernel">Phiên bản Kernel</string> <string name="home_kernel">Phiên bản Kernel</string>
@@ -27,7 +27,7 @@
<string name="install">Cài đặt</string> <string name="install">Cài đặt</string>
<string name="reboot">Khởi động lại</string> <string name="reboot">Khởi động lại</string>
<string name="settings">Cài đặt</string> <string name="settings">Cài đặt</string>
<string name="reboot_userspace">Khởi động lại không gian người dùng</string> <string name="reboot_userspace">Khởi động lại mềm</string>
<string name="reboot_recovery">Khởi động lại vào Recovery</string> <string name="reboot_recovery">Khởi động lại vào Recovery</string>
<string name="reboot_bootloader">Khởi động lại vào Bootloader</string> <string name="reboot_bootloader">Khởi động lại vào Bootloader</string>
<string name="reboot_download">Khởi động lại vào Download Mode</string> <string name="reboot_download">Khởi động lại vào Download Mode</string>
@@ -42,15 +42,15 @@
<string name="show_system_apps">Hiển thị ứng dụng hệ thống</string> <string name="show_system_apps">Hiển thị ứng dụng hệ thống</string>
<string name="hide_system_apps">Ẩn ứng dụng hệ thống</string> <string name="hide_system_apps">Ẩn ứng dụng hệ thống</string>
<string name="send_log">Gửi logs</string> <string name="send_log">Gửi logs</string>
<string name="safe_mode">CHẾ ĐỘ AN TOÀN</string> <string name="safe_mode">Chế độ an toàn</string>
<string name="reboot_to_apply">Khởi động lại để có hiệu lực</string> <string name="reboot_to_apply">Khởi động lại để có hiệu lực</string>
<string name="module_magisk_conflict">Các module không khả dụng do xung đột với Magisk!</string> <string name="module_magisk_conflict">Các module không khả dụng do xung đột với Magisk!</string>
<string name="home_learn_kernelsu">Tìm hiểu về KernelSU</string> <string name="home_learn_kernelsu">Tìm hiểu về KernelSU</string>
<string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string> <string name="home_learn_kernelsu_url">https://kernelsu.org/guide/what-is-kernelsu.html</string>
<string name="home_click_to_learn_kernelsu">Tìm hiểu cách cài đặt KernelSU và sử dụng các Module!</string> <string name="home_click_to_learn_kernelsu">Tìm hiểu cách cài đặt KernelSU và sử dụng các Module!</string>
<string name="home_support_title">Hỗ trợ chúng tôi</string> <string name="home_support_title">Ủng hộ chúng tôi</string>
<string name="home_support_content">KernelSU sẽ luôn là miễn phí và mã nguồn mở. Tuy nhiên, bạn có thể cho chúng tôi thấy rằng bạn quan tâm bằng cách quyên góp!</string> <string name="home_support_content">KernelSU sẽ luôn là miễn phí và mã nguồn mở. Tuy nhiên, bạn có thể cho chúng tôi thấy rằng bạn quan tâm bằng cách quyên góp!</string>
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s<br/>Tham gia kênh %2$s của chúng tôi]]></string> <string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s<br/>Tham gia kênh %2$s của chúng tôi<br/><br/>Hình ảnh của các tệp có nhãn dán nhân vật anime thuộc bản quyền của %3$s, Quyền sở hữu trí tuệ thương hiệu trong hình ảnh thuộc về %4$s. Trước khi sử dụng các tệp này, ngoài việc tuân thủ %5$s, bạn cũng cần tuân thủ sự cho phép của hai tác giả để sử dụng các nội dung nghệ thuật này]]></string>
<string name="profile_default">Mặc định</string> <string name="profile_default">Mặc định</string>
<string name="profile_template">Bản mẫu</string> <string name="profile_template">Bản mẫu</string>
<string name="profile_custom">Tuỳ chỉnh</string> <string name="profile_custom">Tuỳ chỉnh</string>
@@ -60,10 +60,10 @@
<string name="profile_selinux_context">Bối cảnh SELinux</string> <string name="profile_selinux_context">Bối cảnh SELinux</string>
<string name="profile_umount_modules">Umount modules</string> <string name="profile_umount_modules">Umount modules</string>
<string name="failed_to_update_app_profile">Cập nhật Hồ sơ ứng dụng cho %s thất bại</string> <string name="failed_to_update_app_profile">Cập nhật Hồ sơ ứng dụng cho %s thất bại</string>
<string name="require_kernel_version" formatted="false">Phiên bản SukiSU Ultra hiện tại %d quá thấp để trình quản lý hoạt động bình thường. Vui lòng cập nhật lên phiên bản %d hoặc cao hơn!</string> <string name="require_kernel_version" formatted="false">Phiên bản SukiSU Ultra hiện tại %s quá thấp để trình quản lý hoạt động bình thường. Vui lòng cập nhật lên phiên bản %s hoặc cao hơn!</string>
<string name="settings_umount_modules_default">Umount modules</string> <string name="settings_umount_modules_default">Umount modules</string>
<string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong Hồ sơ ứng dụng. Nếu được bật, mọi thay đổi hệ thống do các module gây ra sẽ bị gỡ bỏ khỏi hệ thống và các ứng dụng chưa thiết lập hồ sơ</string> <string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong Hồ sơ ứng dụng. Nếu được bật, mọi thay đổi hệ thống do các module gây ra sẽ bị gỡ bỏ khỏi hệ thống và các ứng dụng chưa thiết lập hồ sơ</string>
<string name="settings_susfs_toggle">Vô hiệu hóa các hook kprobe</string> <string name="settings_susfs_toggle">Vô hiệu h kprobes hook</string>
<string name="profile_umount_modules_summary">Bật tùy chọn này sẽ cho phép SukiSU Ultra khôi phục mọi file đã được các module sửa đổi trong ứng dụng này</string> <string name="profile_umount_modules_summary">Bật tùy chọn này sẽ cho phép SukiSU Ultra khôi phục mọi file đã được các module sửa đổi trong ứng dụng này</string>
<string name="profile_selinux_domain">Tên miền</string> <string name="profile_selinux_domain">Tên miền</string>
<string name="profile_selinux_rules">Quy tắc</string> <string name="profile_selinux_rules">Quy tắc</string>
@@ -83,7 +83,7 @@
<string name="app_profile_template_id">ID</string> <string name="app_profile_template_id">ID</string>
<string name="app_profile_template_id_invalid">ID mẫu không hợp lệ</string> <string name="app_profile_template_id_invalid">ID mẫu không hợp lệ</string>
<string name="app_profile_template_name">Tên</string> <string name="app_profile_template_name">Tên</string>
<string name="app_profile_template_description">Miêu tả</string> <string name="app_profile_template_description">Mô tả</string>
<string name="app_profile_template_save">Lưu</string> <string name="app_profile_template_save">Lưu</string>
<string name="app_profile_template_delete">Xoá</string> <string name="app_profile_template_delete">Xoá</string>
<string name="app_profile_template_view">Xem mẫu</string> <string name="app_profile_template_view">Xem mẫu</string>
@@ -111,6 +111,7 @@
<string name="install_inactive_slot_warning">Thiết bị của bạn sẽ **BUỘC** phải khởi động vào phân vùng chưa được sử dụng!\nChỉ sử dụng tùy chọn này sau khi OTA hoàn tất.\nTiếp tục?</string> <string name="install_inactive_slot_warning">Thiết bị của bạn sẽ **BUỘC** phải khởi động vào phân vùng chưa được sử dụng!\nChỉ sử dụng tùy chọn này sau khi OTA hoàn tất.\nTiếp tục?</string>
<string name="install_next">Kế tiếp</string> <string name="install_next">Kế tiếp</string>
<string name="select_file_tip">Phân vùng %1$s được khuyến nghị</string> <string name="select_file_tip">Phân vùng %1$s được khuyến nghị</string>
<string name="select_file_tip_vendor">(Thử nghiệm)</string>
<string name="select_kmi">Chọn KMI</string> <string name="select_kmi">Chọn KMI</string>
<string name="settings_uninstall">Gỡ cài đặt</string> <string name="settings_uninstall">Gỡ cài đặt</string>
<string name="settings_uninstall_temporary">Gỡ cài đặt tạm thời</string> <string name="settings_uninstall_temporary">Gỡ cài đặt tạm thời</string>
@@ -130,7 +131,7 @@
<string name="module_install_confirm">Xác nhận cài đặt module %1$s</string> <string name="module_install_confirm">Xác nhận cài đặt module %1$s</string>
<string name="unknown_module">Module không xác định</string> <string name="unknown_module">Module không xác định</string>
<!-- Restore related --> <!-- Restore related -->
<string name="restore_confirm_title">Xác Nhận Khôi Phục Module</string> <string name="restore_confirm_title">Xác nhận khôi phục module</string>
<string name="restore_confirm_message">Hành động này sẽ ghi đè lên tất cả các module hiện có. Tiếp tục?</string> <string name="restore_confirm_message">Hành động này sẽ ghi đè lên tất cả các module hiện có. Tiếp tục?</string>
<string name="confirm">Xác nhận</string> <string name="confirm">Xác nhận</string>
<string name="cancel">Thoát</string> <string name="cancel">Thoát</string>
@@ -145,7 +146,7 @@
<string name="restart_now">Khởi động lại ngay</string> <string name="restart_now">Khởi động lại ngay</string>
<string name="unknown_error">Lỗi không xác định</string> <string name="unknown_error">Lỗi không xác định</string>
<!-- Command related --> <!-- Command related -->
<string name="command_execution_failed">Thực hiện lệnh thất bại: %1$s</string> <string name="command_execution_failed">Thực thi lệnh thất bại: %1$s</string>
<!-- Allowlist related --> <!-- Allowlist related -->
<string name="allowlist_backup_success">Sao lưu danh sách cho phép thành công</string> <string name="allowlist_backup_success">Sao lưu danh sách cho phép thành công</string>
<string name="allowlist_backup_failed">Sao lưu danh sách cho phép thất bại: %1$s</string> <string name="allowlist_backup_failed">Sao lưu danh sách cho phép thất bại: %1$s</string>
@@ -160,7 +161,7 @@
<string name="settings_card_alpha">Độ trong suốt của thanh điều hướng</string> <string name="settings_card_alpha">Độ trong suốt của thanh điều hướng</string>
<string name="home_android_version">Phiên bản Android</string> <string name="home_android_version">Phiên bản Android</string>
<string name="home_device_model">Model thiết bị</string> <string name="home_device_model">Model thiết bị</string>
<string name="su_not_allowed">Quyền SU cho %s chưa được cấp</string> <string name="su_not_allowed">Không thể cấp quyền Superuser cho %s</string>
<string name="settings_disable_su">Vô hiệu hoá lệnh SU</string> <string name="settings_disable_su">Vô hiệu hoá lệnh SU</string>
<string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (Những app đã cấp trước đó không bị ảnh hưởng)</string> <string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (Những app đã cấp trước đó không bị ảnh hưởng)</string>
<string name="module_install_multiple_confirm_with_names">Bạn có chắc muốn cài đặt các module %1$d không? \n\n%2$s</string> <string name="module_install_multiple_confirm_with_names">Bạn có chắc muốn cài đặt các module %1$d không? \n\n%2$s</string>
@@ -176,6 +177,8 @@
<string name="hide_other_info_summary">Ẩn thông tin về số lượng ở các mục Superuser, Module và KPModule trên thanh điều hướng</string> <string name="hide_other_info_summary">Ẩn thông tin về số lượng ở các mục Superuser, Module và KPModule trên thanh điều hướng</string>
<string name="hide_susfs_status">Ẩn trạng thái SuSFS</string> <string name="hide_susfs_status">Ẩn trạng thái SuSFS</string>
<string name="hide_susfs_status_summary">Ẩn thông tin trạng thái SuSFS ở trang chủ</string> <string name="hide_susfs_status_summary">Ẩn thông tin trạng thái SuSFS ở trang chủ</string>
<string name="hide_zygisk_implement">Ẩn trạng thái Zygisk</string>
<string name="hide_zygisk_implement_summary">Ẩn thông tin triển khai Zygisk trên trang chủ</string>
<string name="hide_link_card">Ẩn trạng thái thẻ liên kết</string> <string name="hide_link_card">Ẩn trạng thái thẻ liên kết</string>
<string name="hide_link_card_summary">Ẩn thông tin thẻ liên kết ở trang chủ</string> <string name="hide_link_card_summary">Ẩn thông tin thẻ liên kết ở trang chủ</string>
<string name="hide_tag_card">Ẩn các nhãn module</string> <string name="hide_tag_card">Ẩn các nhãn module</string>
@@ -184,7 +187,7 @@
<string name="theme_follow_system">Theo hệ thống</string> <string name="theme_follow_system">Theo hệ thống</string>
<string name="theme_light">Sáng</string> <string name="theme_light">Sáng</string>
<string name="theme_dark">Tối</string> <string name="theme_dark">Tối</string>
<string name="manual_hook">Móc thủ công</string> <string name="manual_hook">Hook thủ công</string>
<string name="dynamic_color_title">Màu sắc động</string> <string name="dynamic_color_title">Màu sắc động</string>
<string name="dynamic_color_summary">Sử dụng màu sắc động làm chủ đề hệ thống</string> <string name="dynamic_color_summary">Sử dụng màu sắc động làm chủ đề hệ thống</string>
<string name="choose_theme_color">Chọn màu chủ đề</string> <string name="choose_theme_color">Chọn màu chủ đề</string>
@@ -217,7 +220,7 @@
<string name="home_kpm_version">Phiên bản KPM</string> <string name="home_kpm_version">Phiên bản KPM</string>
<string name="close_notice">Đóng</string> <string name="close_notice">Đóng</string>
<string name="kernel_module_notice">Các chức năng Kernel Module sau đây được KernelPatch phát triển và sửa đổi để tương thích với các chức năng Kernel Module của SukiSU Ultra</string> <string name="kernel_module_notice">Các chức năng Kernel Module sau đây được KernelPatch phát triển và sửa đổi để tương thích với các chức năng Kernel Module của SukiSU Ultra</string>
<string name="home_ContributionCard_kernelsu">SukiSU Ultra mong đợi</string> <string name="home_ContributionCard_kernelsu">Tương lai của SukiSU Ultra</string>
<string name="kpm_control_success">Thành công</string> <string name="kpm_control_success">Thành công</string>
<string name="kpm_control_failed">Thất bại</string> <string name="kpm_control_failed">Thất bại</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra sẽ là một nhánh tương đối độc lập của KSU trong tương lai, nhưng chúng tôi xin cảm ơn KernelSU và MKSU,... vì những đóng góp của họ!</string> <string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra sẽ là một nhánh tương đối độc lập của KSU trong tương lai, nhưng chúng tôi xin cảm ơn KernelSU và MKSU,... vì những đóng góp của họ!</string>
@@ -235,8 +238,8 @@
<string name="invalid_file_type">Loại file không đúng! Vui lòng chọn file .kpm</string> <string name="invalid_file_type">Loại file không đúng! Vui lòng chọn file .kpm</string>
<string name="confirm_uninstall_title_with_filename">Gỡ cài đặt</string> <string name="confirm_uninstall_title_with_filename">Gỡ cài đặt</string>
<string name="confirm_uninstall_content">KPM sau đây sẽ được gỡ cài đặt: %s</string> <string name="confirm_uninstall_content">KPM sau đây sẽ được gỡ cài đặt: %s</string>
<string name="settings_susfs_toggle_summary">Vô hiệu hóa các hook kprobe được tạo bởi SukiSU Ultra, thay vào đó sử dụng các hook nội tuyến, tương tự như phương pháp hook kernel không phải GKI</string> <string name="settings_susfs_toggle_summary">Vô hiệu h kprobes hook được tạo bởi SukiSU Ultra, thay vào đó sử dụng inlines hook, tương tự như phương pháp hook của Kernel non-GKI</string>
<string name="image_editor_hint">Sử dụng hai ngón tay để phóng to hình ảnh và một ngón tay kéo để điều chỉnh vị trí</string> <string name="image_editor_hint">Sử dụng hai ngón tay để phóng to hình ảnh và một ngón tay kéo thả để điều chỉnh vị trí</string>
<string name="reprovision">Chọn lại</string> <string name="reprovision">Chọn lại</string>
<!-- Kernel Flash Progress Related --> <!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">Kernel Flashing</string> <string name="horizon_flash_title">Kernel Flashing</string>
@@ -255,13 +258,13 @@
<string name="select_slot_description">Vui lòng chọn Slot để Flash Boot</string> <string name="select_slot_description">Vui lòng chọn Slot để Flash Boot</string>
<string name="slot_a">Slot A</string> <string name="slot_a">Slot A</string>
<string name="slot_b">Slot B</string> <string name="slot_b">Slot B</string>
<string name="selected_slot">Đã chọn Slot: %1$s</string> <string name="selected_slot">Slot đã chọn: %1$s</string>
<string name="horizon_getting_original_slot">Lấy Slot ban đầu</string> <string name="horizon_getting_original_slot">Lấy Slot ban đầu</string>
<string name="horizon_setting_target_slot">Cài đặt Slot được chỉ định</string> <string name="horizon_setting_target_slot">Cài đặt Slot được chỉ định</string>
<string name="horizon_restoring_original_slot">Khôi phục Slot mặc định</string> <string name="horizon_restoring_original_slot">Khôi phục Slot mặc định</string>
<string name="current_slot">Slot hiện tại: %1$s </string> <string name="current_slot">Slot hiện tại: %1$s </string>
<!-- Error Messages --> <!-- Error Messages -->
<string name="horizon_copy_failed">Copy thất bại</string> <string name="horizon_copy_failed">Sao chép thất bại</string>
<string name="horizon_unknown_error">Lỗi không xác định</string> <string name="horizon_unknown_error">Lỗi không xác định</string>
<string name="flash_failed_message">Flash thất bại</string> <string name="flash_failed_message">Flash thất bại</string>
<!-- lkm/gki install --> <!-- lkm/gki install -->
@@ -366,10 +369,9 @@
<string name="susfs_apply">Áp dụng</string> <string name="susfs_apply">Áp dụng</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">Xác nhận khôi phục</string> <string name="susfs_reset_confirm_title">Xác nhận khôi phục</string>
<string name="susfs_reset_confirm">Xác nhận khôi phục</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">Không tìm thấy file ksu_susfs</string> <string name="susfs_binary_not_found">Không tìm thấy file ksu_susfs</string>
<string name="susfs_command_failed">Thực hiện lệnh SuSFS thất bại</string> <string name="susfs_command_failed">Thực thi lệnh SuSFS thất bại</string>
<string name="susfs_command_error">Lỗi khi thực hiện lệnh SuSFS: %s</string> <string name="susfs_command_error">Lỗi khi thực hiện lệnh SuSFS: %s</string>
<string name="susfs_uname_set_success" formatted="false">SuSFS Uname và Thời gian xây dựng được thiết lập thành công: %s, %s</string> <string name="susfs_uname_set_success" formatted="false">SuSFS Uname và Thời gian xây dựng được thiết lập thành công: %s, %s</string>
<!-- SuSFS Settings Item --> <!-- SuSFS Settings Item -->
@@ -385,24 +387,22 @@
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<string name="susfs_tab_basic_settings">Cài đặt cơ bản</string> <string name="susfs_tab_basic_settings">Cài đặt cơ bản</string>
<string name="susfs_tab_sus_paths">Đường dẫn SuS</string> <string name="susfs_tab_sus_paths">Đường dẫn SuS</string>
<string name="susfs_tab_sus_mounts">SuS Mounts</string> <string name="susfs_tab_sus_mounts">SuS Mount</string>
<string name="susfs_tab_try_umount">SuS Umount</string> <string name="susfs_tab_try_umount">Try Umount</string>
<string name="susfs_tab_path_settings">Cài đặt Đường dẫn</string> <string name="susfs_tab_path_settings">Cài đặt Đường dẫn</string>
<string name="susfs_tab_enabled_features">Trạng thái tính năng</string> <string name="susfs_tab_enabled_features">Trạng thái tính năng</string>
<!-- SuSFS Dialog Actions -->
<string name="susfs_add">Thêm</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">Thêm Đường dẫn SuS</string> <string name="susfs_add_sus_path">Thêm Đường dẫn SuS</string>
<string name="susfs_add_sus_mount">Thêm SuS Mount</string> <string name="susfs_add_sus_mount">Thêm SuS Mount</string>
<string name="susfs_add_try_umount">Thêm SuS Umount</string> <string name="susfs_add_try_umount">Thêm Try Umount</string>
<string name="susfs_sus_path_added_success">Đường dẫn SuS đã được thêm thành công</string> <string name="susfs_sus_path_added_success">Đường dẫn SuS đã được thêm thành công</string>
<string name="susfs_path_not_found_error">Lỗi không tìm thấy đường dẫn</string> <string name="susfs_path_not_found_error">Lỗi không tìm thấy đường dẫn</string>
<string name="susfs_path_label">Đường dẫn</string> <string name="susfs_path_label">Đường dẫn</string>
<string name="susfs_mount_path_label">Đường dẫn Mount</string> <string name="susfs_mount_path_label">Đường dẫn Mount</string>
<string name="susfs_path_placeholder">Ví dụ: /system/addon.d</string> <string name="susfs_path_placeholder">Ví dụ: /system/addon.d</string>
<string name="susfs_no_paths_configured">Không có Đường dẫn SuS nào được cấu hình</string> <string name="susfs_no_paths_configured">Không có Đường dẫn SuS nào được cấu hình</string>
<string name="susfs_no_mounts_configured">Không có SuS Mounts nào được cấu hình</string> <string name="susfs_no_mounts_configured">Không có SuS Mount nào được cấu hình</string>
<string name="susfs_no_umounts_configured">Không có SuS Umount nào được cấu hình</string> <string name="susfs_no_umounts_configured">Không có Try Umount nào được cấu hình</string>
<!-- SuSFS Umount Mode --> <!-- SuSFS Umount Mode -->
<string name="susfs_umount_mode_label">Chế độ Umount</string> <string name="susfs_umount_mode_label">Chế độ Umount</string>
<string name="susfs_umount_mode_normal">Normal Umount (0)</string> <string name="susfs_umount_mode_normal">Normal Umount (0)</string>
@@ -410,24 +410,24 @@
<string name="susfs_umount_mode_normal_short">Normal</string> <string name="susfs_umount_mode_normal_short">Normal</string>
<string name="susfs_umount_mode_detach_short">Detach</string> <string name="susfs_umount_mode_detach_short">Detach</string>
<string name="susfs_umount_mode_display">Chế độ: %1$s (%2$s)</string> <string name="susfs_umount_mode_display">Chế độ: %1$s (%2$s)</string>
<string name="susfs_try_umount_added_success">Đường dẫn SuS Umount đã thêm thành công: %s</string> <string name="susfs_try_umount_added_success">Đường dẫn Try Umount đã thêm thành công: %s</string>
<string name="susfs_try_umount_added_saved">Đường dẫn SuS Umount đã lưu thành công: %s</string> <string name="susfs_try_umount_added_saved">Đường dẫn Try Umount đã lưu thành công: %s</string>
<!-- SuSFS Run Umount --> <!-- SuSFS Run Umount -->
<string name="susfs_run_umount_confirm_title">Xác nhận chạy SuS Umount</string> <string name="susfs_run_umount_confirm_title">Xác nhận chạy Try Umount</string>
<string name="susfs_run_umount_confirm_message">Thao tác này sẽ áp dụng ngay lập tức tất cả các thiết lập SuS Umount đã cấu hình. Bạn có chắc chắn muốn tiếp tục không?</string> <string name="susfs_run_umount_confirm_message">Thao tác này sẽ áp dụng ngay lập tức tất cả các thiết lập Try Umount đã cấu hình. Bạn có chắc chắn muốn tiếp tục không?</string>
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">Khôi phục Đường dẫn SuS</string> <string name="susfs_reset_paths_title">Khôi phục Đường dẫn SuS</string>
<string name="susfs_reset_paths_message">Thao tác này sẽ xóa tất cả các cấu hình Đường dẫn SuS. Bạn có chắc chắn muốn tiếp tục không?</string> <string name="susfs_reset_paths_message">Thao tác này sẽ xóa tất cả các cấu hình Đường dẫn SuS. Bạn có chắc chắn muốn tiếp tục không?</string>
<string name="susfs_reset_mounts_title">Khôi phục SuS Mounts</string> <string name="susfs_reset_mounts_title">Khôi phục SuS Mount</string>
<string name="susfs_reset_mounts_message">Thao tác này sẽ xóa tất cả các cấu hình SuS Mount. Bạn có chắc chắn muốn tiếp tục không?</string> <string name="susfs_reset_mounts_message">Thao tác này sẽ xóa tất cả các cấu hình SuS Mount. Bạn có chắc chắn muốn tiếp tục không?</string>
<string name="susfs_reset_umounts_title">Khôi phục SuS Umount</string> <string name="susfs_reset_umounts_title">Khôi phục Try Umount</string>
<string name="susfs_reset_umounts_message">Thao tác này sẽ xóa tất cả các cấu hình SuS Umount. Bạn có chắc chắn muốn tiếp tục không?</string> <string name="susfs_reset_umounts_message">Thao tác này sẽ xóa tất cả các cấu hình Try Umount. Bạn có chắc chắn muốn tiếp tục không?</string>
<string name="susfs_reset_path_title">Reset Cài đặt Đường dẫn</string> <string name="susfs_reset_path_title">Reset Cài đặt Đường dẫn</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Đường dẫn Dữ liệu Android</string> <string name="susfs_android_data_path_label">Đường dẫn Android Data</string>
<string name="susfs_sdcard_path_label">Đường dẫn Thẻ SD</string> <string name="susfs_sdcard_path_label">Đường dẫn SD Card</string>
<string name="susfs_set_android_data_path">Đặt Đường dẫn Dữ liệu Android</string> <string name="susfs_set_android_data_path">Đặt Đường dẫn Android Data</string>
<string name="susfs_set_sdcard_path">Đặt Đường dẫn Thẻ SD</string> <string name="susfs_set_sdcard_path">Đặt Đường dẫn SD Card</string>
<!-- SuSFS Enabled Features --> <!-- SuSFS Enabled Features -->
<string name="susfs_enabled_features_description">Hiển thị trạng thái tính năng hiện tại của SuSFS</string> <string name="susfs_enabled_features_description">Hiển thị trạng thái tính năng hiện tại của SuSFS</string>
<string name="susfs_no_features_found">Không tìm thấy thông tin trạng thái tính năng</string> <string name="susfs_no_features_found">Không tìm thấy thông tin trạng thái tính năng</string>
@@ -436,20 +436,20 @@
<!-- Feature Labels --> <!-- Feature Labels -->
<string name="sus_path_feature_label">Hỗ trợ Đường dẫn SuS</string> <string name="sus_path_feature_label">Hỗ trợ Đường dẫn SuS</string>
<string name="sus_mount_feature_label">Hỗ trợ SuS Mount</string> <string name="sus_mount_feature_label">Hỗ trợ SuS Mount</string>
<string name="try_umount_feature_label">Hỗ trợ SuS Umount</string> <string name="try_umount_feature_label">Hỗ trợ Try Umount</string>
<string name="spoof_uname_feature_label">Hỗ trợ giả mạo Uname</string> <string name="spoof_uname_feature_label">Hỗ trợ giả mạo Uname</string>
<string name="spoof_cmdline_feature_label">Giả mạo Cmdline/Bootconfig</string> <string name="spoof_cmdline_feature_label">Giả mạo Cmdline/Bootconfig</string>
<string name="open_redirect_feature_label">Mở hỗ trợ chuyển hướng</string> <string name="open_redirect_feature_label">Mở hỗ trợ chuyển hướng</string>
<string name="enable_log_feature_label">Hỗ trợ ghi logs</string> <string name="enable_log_feature_label">Hỗ trợ ghi logs</string>
<string name="auto_default_mount_feature_label">Tự động Mount mặc định</string> <string name="auto_default_mount_feature_label">Tự động Mount mặc định</string>
<string name="auto_bind_mount_feature_label">Tự động Bind Mount</string> <string name="auto_bind_mount_feature_label">Tự động Bind Mount</string>
<string name="auto_try_umount_bind_feature_label">Tự động Umount Bind Mount</string> <string name="auto_try_umount_bind_feature_label">Tự động Try Umount Bind Mount</string>
<string name="hide_symbols_feature_label">Ẩn biểu tượng KSU SuSFS</string> <string name="hide_symbols_feature_label">Ẩn biểu tượng KSU SuSFS</string>
<string name="magic_mount_feature_label">Hỗ trợ Magic Mount</string> <string name="magic_mount_feature_label">Hỗ trợ Magic Mount</string>
<string name="sus_kstat_feature_label">Hỗ trợ SuS Kstat</string> <string name="sus_kstat_feature_label">Hỗ trợ SuS Kstat</string>
<string name="sus_su_feature_label">Chức năng chuyển đổi chế độ SuS SU</string> <string name="sus_su_feature_label">Chức năng chuyển đổi chế độ SuS SU</string>
<!-- 可切换状态 --> <!-- 可切换状态 -->
<string name="susfs_feature_configurable">Các tính năng SuSFS có thể cấu hình</string> <string name="susfs_feature_configurable">Nhấn để bật/tắt ghi logs</string>
<string name="susfs_enable_log_label">Kích hoạt logs SuSFS</string> <string name="susfs_enable_log_label">Kích hoạt logs SuSFS</string>
<string name="susfs_log_config_description">Bật hoặc tắt ghi logs cho SuSFS</string> <string name="susfs_log_config_description">Bật hoặc tắt ghi logs cho SuSFS</string>
<string name="susfs_log_config_title">Cấu hình ghi logs SuSFS</string> <string name="susfs_log_config_title">Cấu hình ghi logs SuSFS</string>
@@ -460,12 +460,12 @@
<!-- Settings related strings --> <!-- Settings related strings -->
<string name="show_more_module_info">Hiển thị \"JSON URLs\"</string> <string name="show_more_module_info">Hiển thị \"JSON URLs\"</string>
<string name="show_more_module_info_summary">Hiển thị thông tin đường dẫn cập nhật \"JSON URLs\" của module</string> <string name="show_more_module_info_summary">Hiển thị thông tin đường dẫn cập nhật \"JSON URLs\" của module</string>
<string name="susfs_execution_location_label">Địa điểm thực thi</string> <string name="susfs_execution_location_label">Vị trí thực thi</string>
<string name="susfs_current_execution_location">Vị trí thực thi hiện tại: %s</string> <string name="susfs_current_execution_location">Vị trí thực thi hiện tại: %s</string>
<string name="susfs_execution_location_service">Service</string> <string name="susfs_execution_location_service">Service</string>
<string name="susfs_execution_location_post_fs_data">Post-FS-Data</string> <string name="susfs_execution_location_post_fs_data">Post-FS-Data</string>
<string name="susfs_execution_location_service_description">Thực hiện sau khi dịch vụ hệ thống bắt đầu</string> <string name="susfs_execution_location_service_description">Thực thi sau khi dịch vụ hệ thống khởi động</string>
<string name="susfs_execution_location_post_fs_data_description">Thực hiện sau khi file hệ thống được mount nhưng trước khi hệ thống khởi động hoàn toàn, có thể gây ra boot loop</string> <string name="susfs_execution_location_post_fs_data_description">Thực thi sau khi file hệ thống được mount nhưng trước khi hệ thống khởi động hoàn toàn, có thể gây ra boot loop</string>
<string name="susfs_slot_info_title">Thông tin Slot</string> <string name="susfs_slot_info_title">Thông tin Slot</string>
<string name="susfs_slot_info_description">Xem thông tin Slot khởi động hiện tại và sao chép giá trị</string> <string name="susfs_slot_info_description">Xem thông tin Slot khởi động hiện tại và sao chép giá trị</string>
<string name="susfs_current_active_slot">Slot hiện tại: %s</string> <string name="susfs_current_active_slot">Slot hiện tại: %s</string>
@@ -477,24 +477,22 @@
<string name="susfs_slot_info_unavailable">Không thể lấy thông tin Slot</string> <string name="susfs_slot_info_unavailable">Không thể lấy thông tin Slot</string>
<!-- SuSFS 自启动相关字符串 --> <!-- SuSFS 自启动相关字符串 -->
<string name="susfs_autostart_enabled_success">Module tự động khởi động SuSFS đã bật, đường dẫn module: %s</string> <string name="susfs_autostart_enabled_success">Module tự động khởi động SuSFS đã bật, đường dẫn module: %s</string>
<string name="susfs_autostart_disabled_success">Module tự động khởi động SuSFS đã bị vô hiệu hóa</string> <string name="susfs_autostart_disabled_success">Module tự động khởi động SuSFS đã bị vô hiệu h</string>
<!-- SuSFS Kstat相关字符串 --> <!-- SuSFS Kstat相关字符串 -->
<string name="susfs_tab_kstat_config">Cấu hình Kstat</string> <string name="susfs_tab_kstat_config">Cấu hình Kstat</string>
<string name="kstat_static_config_added">Đã thêm cấu hình tĩnh Kstat: %1$s</string> <string name="kstat_static_config_added">Đã thêm cấu hình Kstat tĩnh: %1$s</string>
<string name="kstat_config_removed">Đã xoá cấu hình Kstat: %1$s</string> <string name="kstat_config_removed">Đã xoá cấu hình Kstat: %1$s</string>
<string name="kstat_path_added">Đã thêm đường dẫn Kstat: %1$s</string> <string name="kstat_path_added">Đã thêm Đường dẫn Kstat: %1$s</string>
<string name="kstat_path_removed">Đã xoá đường dẫn Kstat: %1$s</string> <string name="kstat_path_removed">Đã xoá Đường dẫn Kstat: %1$s</string>
<string name="kstat_updated">Đã cập nhật Kstat: %1$s</string> <string name="kstat_updated">Đã cập nhật Kstat: %1$s</string>
<string name="kstat_full_clone_updated">Bản sao Kstat đầy đủ đã cập nhật: %1$s</string> <string name="kstat_full_clone_updated">Bản sao Kstat đầy đủ đã cập nhật: %1$s</string>
<string name="add_kstat_statically_title">Thêm cấu hình tĩnh Kstat</string> <string name="add_kstat_statically_title">Thêm cấu hình Kstat tĩnh</string>
<string name="file_or_directory_path_label">Đường dẫn File/Folder</string> <string name="file_or_directory_path_label">Đường dẫn File/Folder</string>
<string name="hint_use_default_value">Gợi ý: Bạn có thể sử dụng \"default\" để thiết lập giá trị ban đầu</string> <string name="hint_use_default_value">Gợi ý: Bạn có thể sử dụng \"default\" để thiết lập giá trị ban đầu</string>
<string name="add_kstat_path_title">Thêm Đường dẫn Kstat</string> <string name="add_kstat_path_title">Thêm Đường dẫn Kstat</string>
<string name="kstat_command_description">Lệnh này được sử dụng để thêm trước khi đường dẫn được mount hoặc ghi đè nhằm lưu trữ thông tin trạng thái ban đầu trong bộ nhớ hạt nhân</string>
<string name="add">Thêm</string> <string name="add">Thêm</string>
<string name="reset_kstat_config_title">Khôi phục Cấu hình Kstat</string> <string name="reset_kstat_config_title">Khôi phục Cấu hình Kstat</string>
<string name="reset_kstat_config_message">Bạn có chắc chắn muốn xóa tất cả cấu hình Kstat không? Không thể hoàn tác hành động này</string> <string name="reset_kstat_config_message">Bạn có chắc chắn muốn xóa tất cả cấu hình Kstat không? Không thể hoàn tác hành động này</string>
<string name="confirm_reset">Xác nhận khôi phục</string>
<string name="kstat_config_description_title">Mô tả cấu hình Kstat</string> <string name="kstat_config_description_title">Mô tả cấu hình Kstat</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_statically: Thông tin thống kê cấu hình tĩnh của các File/Folder</string> <string name="kstat_config_description_add_statically">• add_sus_kstat_statically: Thông tin thống kê cấu hình tĩnh của các File/Folder</string>
<string name="kstat_config_description_add">• add_sus_kstat: Thêm đường dẫn trước khi mount để lưu trữ thông tin trạng thái ban đầu</string> <string name="kstat_config_description_add">• add_sus_kstat: Thêm đường dẫn trước khi mount để lưu trữ thông tin trạng thái ban đầu</string>
@@ -502,5 +500,91 @@
<string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: Chỉ cập nhật ino, giữ nguyên các giá trị gốc khác</string> <string name="kstat_config_description_update_full_clone">• update_sus_kstat_full_clone: Chỉ cập nhật ino, giữ nguyên các giá trị gốc khác</string>
<string name="static_kstat_config">Cấu hình Kstat tĩnh</string> <string name="static_kstat_config">Cấu hình Kstat tĩnh</string>
<string name="kstat_path_management">Quản lý Đường dẫn Kstat</string> <string name="kstat_path_management">Quản lý Đường dẫn Kstat</string>
<string name="no_kstat_config_message">Chưa có cấu hình Kstat, hãy nhấp vào nút bên trên để thêm</string> <string name="no_kstat_config_message">Chưa có cấu hình Kstat, hãy nhấp vào nút bên dưới để thêm</string>
<!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">Điều khiển ẩn SuS Mount</string>
<string name="susfs_hide_mounts_control_description">Kiểm soát hành vi ẩn của SuS Mount với các tiến trình</string>
<string name="susfs_hide_mounts_for_all_procs_label">Ẩn SuS Mount khỏi tất cả các tiến trình</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">Khi kích hoạt, SuS Mount sẽ bị ẩn khỏi tất cả các tiến trình, bao gồm cả các tiến trình KSU</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">Khi bị vô hiệu hoá, SuS Mount sẽ chỉ bị ẩn khỏi các tiến trình không phải KSU, không bị ẩn ở tiến trình KSU</string>
<string name="susfs_hide_mounts_all_enabled">Đã kích hoạt ẩn SuS Mount khỏi tất cả các tiến trình</string>
<string name="susfs_hide_mounts_all_disabled">Đã vô hiệu hoá việc ẩn SuS Mount cho tất cả các tiến trình</string>
<string name="susfs_hide_mounts_recommendation">Nên vô hiệu hoá sau khi màn hình được mở khoá hoặc trong giai đoạn service.sh hoặc boot-completed.sh, vì điều này sẽ khắc phục sự cố trên một số ứng dụng đã root dựa vào mount bởi tiến trình KSU</string>
<string name="susfs_hide_mounts_current_setting">Cài đặt hiện tại: %s</string>
<string name="susfs_hide_mounts_setting_all">Ẩn khỏi tất cả các tiến trình</string>
<string name="susfs_hide_mounts_setting_non_ksu">Chỉ ẩn đối với các tiến trình không phải KSU</string>
<string name="susfs_run">Chạy</string>
<string name="kernel_simple_kernel">Hiển thị tóm tắt \"Phiên bản Kernel\"</string>
<string name="kernel_simple_kernel_summary">Tóm tắt hiển thị phiên bản Kernel cho ngắn gọn</string>
<string name="susfs_android_data_path_set">Đường dẫn Android Data đã được đặt thành: %s</string>
<string name="susfs_sdcard_path_set">Đường dẫn SD Card đã được đặt thành: %s</string>
<string name="susfs_path_setup_warning">Thiết lập đường dẫn có thể không thành công hoàn toàn, nhưng đường dẫn SuS sẽ tiếp tục được thêm vào</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">Sao lưu</string>
<string name="susfs_backup_description">Tạo bản sao lưu cho tất cả các cấu hình SuSFS. File sao lưu sẽ bao gồm tất cả các thiết lập, đường dẫn và thông tin cấu hình</string>
<string name="susfs_backup_create">Tạo bản sao lưu</string>
<string name="susfs_backup_success">Đã tạo bản sao lưu thành công: %s</string>
<string name="susfs_backup_failed">Tạo bản sao lưu thất bại: %s</string>
<string name="susfs_backup_file_not_found">Không tìm thấy file sao lưu</string>
<string name="susfs_backup_invalid_format">Định dạng file sao lưu không hợp lệ</string>
<string name="susfs_backup_version_mismatch">Phiên bản sao lưu không khớp, nhưng sẽ cố gắng khôi phục</string>
<string name="susfs_restore_title">Khôi phục</string>
<string name="susfs_restore_description">Khôi phục cấu hình SuSFS từ file sao lưu. Thao tác này sẽ ghi đè lên tất cả các cài đặt hiện tại</string>
<string name="susfs_restore_select_file">Chọn file sao lưu</string>
<string name="susfs_restore_success" formatted="false">Cấu hình đã được khôi phục thành công từ bản sao lưu được tạo trên %s, từ thiết bị: %s</string>
<string name="susfs_restore_failed">Khôi phục thất bại: %s</string>
<string name="susfs_restore_confirm_title">Xác nhận khôi phục</string>
<string name="susfs_restore_confirm_description">Thao tác này sẽ ghi đè lên tất cả các cấu hình SuSFS hiện tại. Bạn có chắc chắn muốn tiếp tục không?</string>
<string name="susfs_restore_confirm">Khôi phục</string>
<string name="susfs_backup_info_date">Ngày sao lưu: %s</string>
<string name="susfs_backup_info_device">Thiết bị: %s</string>
<string name="susfs_backup_info_version">Phiên bản: %s</string>
<string name="hide_bl_script">Ẩn Script BL</string>
<string name="hide_bl_script_description">Ẩn scripts trạng thái Unlock Bootloader</string>
<string name="cleanup_residue">Dọn rác</string>
<string name="cleanup_residue_description">Dọn dẹp các file và folder còn sót lại của các module và công cụ (Có thể bị xóa nhầm, dẫn đến mất dữ liệu và không khởi động được)</string>
<string name="susfs_edit_sus_path">Chỉnh sửa Đường dẫn SuS</string>
<string name="susfs_edit_sus_mount">Chỉnh sửa SuS Mount</string>
<string name="susfs_edit_try_umount">Chỉnh sửa Try Umount</string>
<string name="edit_kstat_statically_title">Chỉnh sửa cấu hình Kstat tĩnh</string>
<string name="edit_kstat_path_title">Chỉnh sửa Đường dẫn Kstat</string>
<string name="susfs_save">Lưu</string>
<string name="edit">Chỉnh sửa</string>
<string name="delete">Xoá</string>
<string name="update">Cập nhật</string>
<string name="kstat_config_updated">Cập nhật cấu hình Kstat</string>
<string name="kstat_path_updated">Cập nhật Đường dẫn Kstat</string>
<string name="susfs_update_full_clone">Cập nhật bản sao SuSFS đầy đủ</string>
<string name="umount_zygote_iso_service">Umount dịch vụ cô lập Zygote</string>
<string name="umount_zygote_iso_service_description">Umount các điểm dịch vụ cô lập Zygote khi khởi động hệ thống</string>
<string name="umount_zygote_iso_service_enabled">Umount dịch vụ cô lập Zygote đã bật</string>
<string name="umount_zygote_iso_service_disabled">Umount dịch vụ cô lập Zygote đã tắt</string>
<string name="app_paths_section">Đường dẫn ứng dụng</string>
<string name="other_paths_section">Đường dẫn khác</string>
<string name="add_custom_path">Khác</string>
<string name="add_app_path">Ứng dụng</string>
<string name="susfs_add_app_path">Thêm Đường dẫn ứng dụng</string>
<string name="search_apps">Tìm kiếm ứng dụng</string>
<string name="selected_apps_count">%1$d ứng dụng đã chọn</string>
<string name="already_added_apps_count">%1$d ứng dụng đã thêm</string>
<string name="all_apps_already_added">Tất cả các ứng dụng đã được thêm vào</string>
<string name="dynamic_sign_title">Cấu hình chữ ký động</string>
<string name="dynamic_sign_enabled_summary">Đã kích hoạt (Size: %s)</string>
<string name="dynamic_sign_disabled">Đã vô hiệu hoá</string>
<string name="enable_dynamic_sign">Kích hoạt chữ ký động</string>
<string name="signature_size">Size chữ ký</string>
<string name="signature_hash">Hash chữ ký</string>
<string name="hash_must_be_64_chars">Hash phải dài 64 ký tự thập lục phân</string>
<string name="dynamic_sign_set_success">Cấu hình chữ ký động đã được thiết lập thành công</string>
<string name="dynamic_sign_set_failed">Thiết lập cấu hình chữ ký động thất bại</string>
<string name="invalid_sign_config">Cấu hình chữ ký không hợp lệ</string>
<string name="dynamic_sign_disabled_success">Chữ ký động đã bị vô hiệu hoá</string>
<string name="dynamic_sign_clear_failed">Xoá chữ ký động thất bại</string>
<string name="dynamic_signature">Chữ ký động</string>
<string name="signature_index">Chữ ký %1$d</string>
<string name="unknown_signature">Không xác định</string>
<string name="multi_manager_list">Trình quản lý đang hoạt động</string>
<string name="no_active_manager">Trình quản lý đang không hoạt động</string>
<string name="default_signature">SukiSU</string>
<string name="home_zygisk_implement">Triển khai Zygisk</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="home_not_installed">未安装</string> <string name="home_not_installed">未安装</string>
<string name="home_click_to_install">点击安装</string> <string name="home_click_to_install">点击安装</string>
<string name="home_working">工作中</string> <string name="home_working">工作中</string>
<string name="home_working_version">版本:%d</string> <string name="home_working_version">版本:%s</string>
<string name="home_unsupported">不支持</string> <string name="home_unsupported">不支持</string>
<string name="home_unsupported_reason">内核上未检测到 KernelSU 驱动程序,内核错误?</string> <string name="home_unsupported_reason">内核上未检测到 KernelSU 驱动程序,内核错误?</string>
<string name="home_kernel">内核版本</string> <string name="home_kernel">内核版本</string>
@@ -50,7 +50,7 @@
<string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string> <string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string>
<string name="home_support_title">支持开发</string> <string name="home_support_title">支持开发</string>
<string name="home_support_content">KernelSU 将保持免费开源,向开发者捐赠以表示支持。</string> <string name="home_support_content">KernelSU 将保持免费开源,向开发者捐赠以表示支持。</string>
<string name="about_source_code"><![CDATA[在 %1$s 查看源码<br/>加入我们的 %2$s 频道]]></string> <string name="about_source_code"><![CDATA[在 %1$s 查看源码<br/>加入我们的 %2$s 频道<br/><br/>有动漫人物图片表情包的图像版权为%3$s所有图像中的知识产权由%4$s 所有。在使用这些文件之前,除了必须遵守 %5$s 以外,还需要遵守向前两者索要使用这些艺术内容的授权。]]></string>
<string name="profile_default">默认</string> <string name="profile_default">默认</string>
<string name="profile_template">模版</string> <string name="profile_template">模版</string>
<string name="profile_custom">自定义</string> <string name="profile_custom">自定义</string>
@@ -60,7 +60,7 @@
<string name="profile_selinux_context">SELinux</string> <string name="profile_selinux_context">SELinux</string>
<string name="profile_umount_modules">卸载模块</string> <string name="profile_umount_modules">卸载模块</string>
<string name="failed_to_update_app_profile">为 %s 更新 App Profile 失败</string> <string name="failed_to_update_app_profile">为 %s 更新 App Profile 失败</string>
<string name="require_kernel_version" formatted="false">当前 KernelSU 版本 %d 过低,管理器无法正常工作,请将内核 KernelSU 版本升级至 %d 或以上!</string> <string name="require_kernel_version" formatted="false">当前 KernelSU 版本 %s 过低,管理器无法正常工作,请将内核 KernelSU 版本升级至 %s 或以上!</string>
<string name="settings_umount_modules_default">默认卸载模块</string> <string name="settings_umount_modules_default">默认卸载模块</string>
<string name="settings_umount_modules_default_summary">App Profile 中\"卸载模块\"的全局默认值,如果启用,将会为没有设置 Profile 的应用移除所有模块针对系统的修改。</string> <string name="settings_umount_modules_default_summary">App Profile 中\"卸载模块\"的全局默认值,如果启用,将会为没有设置 Profile 的应用移除所有模块针对系统的修改。</string>
<string name="settings_susfs_toggle">禁用 kprobe 钩子</string> <string name="settings_susfs_toggle">禁用 kprobe 钩子</string>
@@ -111,6 +111,7 @@
<string name="install_inactive_slot_warning">将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认</string> <string name="install_inactive_slot_warning">将在重启后强制切换到另一个槽位!\n注意只能在 OTA 更新完成后的重启之前使用。\n确认</string>
<string name="install_next">下一步</string> <string name="install_next">下一步</string>
<string name="select_file_tip">建议选择 %1$s 分区镜像</string> <string name="select_file_tip">建议选择 %1$s 分区镜像</string>
<string name="select_file_tip_vendor">(实验性的)</string>
<string name="select_kmi">选择 KMI</string> <string name="select_kmi">选择 KMI</string>
<string name="settings_uninstall">卸载</string> <string name="settings_uninstall">卸载</string>
<string name="settings_uninstall_temporary">临时卸载</string> <string name="settings_uninstall_temporary">临时卸载</string>
@@ -176,6 +177,8 @@
<string name="hide_other_info_summary">隐藏导航栏上的超级用户数、模块数和 KPM 模块数红点</string> <string name="hide_other_info_summary">隐藏导航栏上的超级用户数、模块数和 KPM 模块数红点</string>
<string name="hide_susfs_status">隐藏 SuSFS 状态信息</string> <string name="hide_susfs_status">隐藏 SuSFS 状态信息</string>
<string name="hide_susfs_status_summary">隐藏主页上的 SuSFS 状态信息</string> <string name="hide_susfs_status_summary">隐藏主页上的 SuSFS 状态信息</string>
<string name="hide_zygisk_implement">隐藏 Zygisk 状态信息</string>
<string name="hide_zygisk_implement_summary">隐藏主页上的 Zygisk 实现状态信息</string>
<string name="hide_link_card">隐藏链接卡片</string> <string name="hide_link_card">隐藏链接卡片</string>
<string name="hide_link_card_summary">隐藏主页上的链接卡片信息</string> <string name="hide_link_card_summary">隐藏主页上的链接卡片信息</string>
<string name="hide_tag_card">隐藏模块标签行</string> <string name="hide_tag_card">隐藏模块标签行</string>
@@ -239,7 +242,7 @@
<string name="image_editor_hint">使用双指缩放图片,单指拖动调整位置</string> <string name="image_editor_hint">使用双指缩放图片,单指拖动调整位置</string>
<string name="reprovision">重置</string> <string name="reprovision">重置</string>
<!-- Kernel Flash Progress Related --> <!-- Kernel Flash Progress Related -->
<string name="horizon_flash_title">刷写Kernel</string> <string name="horizon_flash_title">刷写 Kernel</string>
<string name="horizon_logs_label">日志:</string> <string name="horizon_logs_label">日志:</string>
<string name="horizon_flash_complete">刷写完成</string> <string name="horizon_flash_complete">刷写完成</string>
<!-- Flash Status Related --> <!-- Flash Status Related -->
@@ -252,9 +255,9 @@
<string name="horizon_flash_complete_status">刷写完成</string> <string name="horizon_flash_complete_status">刷写完成</string>
<!-- Slot selection related strings --> <!-- Slot selection related strings -->
<string name="select_slot_title">选择刷写槽位</string> <string name="select_slot_title">选择刷写槽位</string>
<string name="select_slot_description">请选择要刷写boot的目标槽位</string> <string name="select_slot_description">请选择要刷写 boot 的目标槽位</string>
<string name="slot_a">A槽位</string> <string name="slot_a">A 槽位</string>
<string name="slot_b">B槽位</string> <string name="slot_b">B 槽位</string>
<string name="selected_slot">已选择槽位: %1$s</string> <string name="selected_slot">已选择槽位: %1$s</string>
<string name="horizon_getting_original_slot">获取原有槽位</string> <string name="horizon_getting_original_slot">获取原有槽位</string>
<string name="horizon_setting_target_slot">设置指定槽位</string> <string name="horizon_setting_target_slot">设置指定槽位</string>
@@ -265,7 +268,7 @@
<string name="horizon_unknown_error">未知错误</string> <string name="horizon_unknown_error">未知错误</string>
<string name="flash_failed_message">刷写失败</string> <string name="flash_failed_message">刷写失败</string>
<!-- lkm/gki install --> <!-- lkm/gki install -->
<string name="Lkm_install_methods">LKM修补/安装</string> <string name="Lkm_install_methods">LKM 修补/安装</string>
<string name="GKI_install_methods">刷写 AnyKernel3</string> <string name="GKI_install_methods">刷写 AnyKernel3</string>
<string name="kernel_version_log">内核版本:%1$s</string> <string name="kernel_version_log">内核版本:%1$s</string>
<string name="tool_version_log">使用修补工具:%1$s</string> <string name="tool_version_log">使用修补工具:%1$s</string>
@@ -298,17 +301,17 @@
<string name="use_webuix_eruda">将 Eruda 注入 WebUI X</string> <string name="use_webuix_eruda">将 Eruda 注入 WebUI X</string>
<string name="use_webuix_eruda_summary">在 WebUI X 中注入调试控制台,使调试更容易,需要启用 WebView 调试</string> <string name="use_webuix_eruda_summary">在 WebUI X 中注入调试控制台,使调试更容易,需要启用 WebView 调试</string>
<!-- DPI setting related strings --> <!-- DPI setting related strings -->
<string name="app_dpi_title">应用DPI</string> <string name="app_dpi_title">应用 DPI</string>
<string name="app_dpi_summary">仅调整当前应用的屏幕显示密度</string> <string name="app_dpi_summary">仅调整当前应用的屏幕显示密度</string>
<string name="dpi_size_small"></string> <string name="dpi_size_small"></string>
<string name="dpi_size_medium"></string> <string name="dpi_size_medium"></string>
<string name="dpi_size_large"></string> <string name="dpi_size_large"></string>
<string name="dpi_size_extra_large">超大</string> <string name="dpi_size_extra_large">超大</string>
<string name="dpi_size_custom">自定义</string> <string name="dpi_size_custom">自定义</string>
<string name="dpi_apply_settings">应用DPI设置</string> <string name="dpi_apply_settings">应用 DPI 设置</string>
<string name="dpi_confirm_title">确认更改DPI</string> <string name="dpi_confirm_title">确认更改 DPI</string>
<string name="dpi_confirm_message">你确定要将应用DPI从 %1$d 更改为 %2$d 吗?</string> <string name="dpi_confirm_message">你确定要将应用 DPI 从 %1$d 更改为 %2$d 吗?</string>
<string name="dpi_confirm_summary">应用需要重启以应用新的DPI设置不会影响系统状态栏或其他应用</string> <string name="dpi_confirm_summary">应用需要重启以应用新的 DPI 设置,不会影响系统状态栏或其他应用</string>
<string name="dpi_applied_success">DPI 已设置为 %1$d重启应用后生效</string> <string name="dpi_applied_success">DPI 已设置为 %1$d重启应用后生效</string>
<!-- Language settings related strings --> <!-- Language settings related strings -->
<string name="language_setting">应用语言</string> <string name="language_setting">应用语言</string>
@@ -330,8 +333,8 @@
<!-- 排序相关 --> <!-- 排序相关 -->
<string name="sort_name_asc">名称升序</string> <string name="sort_name_asc">名称升序</string>
<string name="sort_name_desc">名称降序</string> <string name="sort_name_desc">名称降序</string>
<string name="sort_install_time_new">安装时间(新)</string> <string name="sort_install_time_new">安装时间(新)</string>
<string name="sort_install_time_old">安装时间(旧)</string> <string name="sort_install_time_old">安装时间(旧)</string>
<string name="sort_size_desc">大小降序</string> <string name="sort_size_desc">大小降序</string>
<string name="sort_size_asc">大小升序</string> <string name="sort_size_asc">大小升序</string>
<string name="sort_usage_freq">使用频率</string> <string name="sort_usage_freq">使用频率</string>
@@ -366,7 +369,6 @@
<string name="susfs_apply">应用</string> <string name="susfs_apply">应用</string>
<!-- SuSFS Reset Confirmation --> <!-- SuSFS Reset Confirmation -->
<string name="susfs_reset_confirm_title">确认重置</string> <string name="susfs_reset_confirm_title">确认重置</string>
<string name="susfs_reset_confirm">确认重置</string>
<!-- SuSFS Toast Messages --> <!-- SuSFS Toast Messages -->
<string name="susfs_binary_not_found">无法找到 ksu_susfs 文件</string> <string name="susfs_binary_not_found">无法找到 ksu_susfs 文件</string>
<string name="susfs_command_failed">SuSFS 命令执行失败</string> <string name="susfs_command_failed">SuSFS 命令执行失败</string>
@@ -384,29 +386,27 @@
<string name="susfs_no_config_to_autostart">没有可用的配置进行开机自启动</string> <string name="susfs_no_config_to_autostart">没有可用的配置进行开机自启动</string>
<!-- SuSFS Tab Titles --> <!-- SuSFS Tab Titles -->
<string name="susfs_tab_basic_settings">基本设置</string> <string name="susfs_tab_basic_settings">基本设置</string>
<string name="susfs_tab_sus_paths">SUS路径</string> <string name="susfs_tab_sus_paths">SuS 路径</string>
<string name="susfs_tab_sus_mounts">SUS挂载</string> <string name="susfs_tab_sus_mounts">SuS 挂载</string>
<string name="susfs_tab_try_umount">尝试卸载</string> <string name="susfs_tab_try_umount">尝试卸载</string>
<string name="susfs_tab_path_settings">路径设置</string> <string name="susfs_tab_path_settings">路径设置</string>
<string name="susfs_tab_enabled_features">启用功能状态</string> <string name="susfs_tab_enabled_features">启用功能状态</string>
<!-- SuSFS Dialog Actions -->
<string name="susfs_add">添加</string>
<!-- SuSFS Path Management --> <!-- SuSFS Path Management -->
<string name="susfs_add_sus_path">添加SUS路径</string> <string name="susfs_add_sus_path">添加 SuS 路径</string>
<string name="susfs_add_sus_mount">添加SUS挂载</string> <string name="susfs_add_sus_mount">添加 SuS 挂载</string>
<string name="susfs_add_try_umount">添加尝试卸载</string> <string name="susfs_add_try_umount">添加尝试卸载</string>
<string name="susfs_sus_path_added_success">SUS 路径添加成功</string> <string name="susfs_sus_path_added_success">SuS 路径添加成功</string>
<string name="susfs_path_not_found_error">路径未找到错误</string> <string name="susfs_path_not_found_error">路径未找到错误</string>
<string name="susfs_path_label">路径</string> <string name="susfs_path_label">路径</string>
<string name="susfs_mount_path_label">挂载路径</string> <string name="susfs_mount_path_label">挂载路径</string>
<string name="susfs_path_placeholder">例如: /system/addon.d</string> <string name="susfs_path_placeholder">例如: /system/addon.d</string>
<string name="susfs_no_paths_configured">暂无 SUS 路径配置</string> <string name="susfs_no_paths_configured">暂无 SuS 路径配置</string>
<string name="susfs_no_mounts_configured">暂无 SUS 挂载配置</string> <string name="susfs_no_mounts_configured">暂无 SuS 挂载配置</string>
<string name="susfs_no_umounts_configured">暂无尝试卸载配置</string> <string name="susfs_no_umounts_configured">暂无尝试卸载配置</string>
<!-- SuSFS Umount Mode --> <!-- SuSFS Umount Mode -->
<string name="susfs_umount_mode_label">卸载模式</string> <string name="susfs_umount_mode_label">卸载模式</string>
<string name="susfs_umount_mode_normal">普通卸载 (0)</string> <string name="susfs_umount_mode_normal">普通卸载0</string>
<string name="susfs_umount_mode_detach">分离卸载 (1)</string> <string name="susfs_umount_mode_detach">分离卸载1</string>
<string name="susfs_umount_mode_normal_short">普通</string> <string name="susfs_umount_mode_normal_short">普通</string>
<string name="susfs_umount_mode_detach_short">分离</string> <string name="susfs_umount_mode_detach_short">分离</string>
<string name="susfs_umount_mode_display">模式: %1$s (%2$s)</string> <string name="susfs_umount_mode_display">模式: %1$s (%2$s)</string>
@@ -416,26 +416,26 @@
<string name="susfs_run_umount_confirm_title">确认运行尝试卸载</string> <string name="susfs_run_umount_confirm_title">确认运行尝试卸载</string>
<string name="susfs_run_umount_confirm_message">这将立即执行所有已配置的尝试卸载操作,确定要继续吗?</string> <string name="susfs_run_umount_confirm_message">这将立即执行所有已配置的尝试卸载操作,确定要继续吗?</string>
<!-- SuSFS Reset Categories --> <!-- SuSFS Reset Categories -->
<string name="susfs_reset_paths_title">重置 SUS 路径</string> <string name="susfs_reset_paths_title">重置 SuS 路径</string>
<string name="susfs_reset_paths_message">这将清除所有 SUS 路径配置,确定要继续吗?</string> <string name="susfs_reset_paths_message">这将清除所有 SuS 路径配置,确定要继续吗?</string>
<string name="susfs_reset_mounts_title">重置 SUS 挂载</string> <string name="susfs_reset_mounts_title">重置 SuS 挂载</string>
<string name="susfs_reset_mounts_message">这将清除所有 SUS 挂载配置,确定要继续吗?</string> <string name="susfs_reset_mounts_message">这将清除所有 SuS 挂载配置,确定要继续吗?</string>
<string name="susfs_reset_umounts_title">重置尝试卸载</string> <string name="susfs_reset_umounts_title">重置尝试卸载</string>
<string name="susfs_reset_umounts_message">这将清除所有尝试卸载配置,确定要继续吗?</string> <string name="susfs_reset_umounts_message">这将清除所有尝试卸载配置,确定要继续吗?</string>
<string name="susfs_reset_path_title">重置路径设置</string> <string name="susfs_reset_path_title">重置路径设置</string>
<!-- SuSFS Path Settings --> <!-- SuSFS Path Settings -->
<string name="susfs_android_data_path_label">Android Data 路径</string> <string name="susfs_android_data_path_label">Android Data 路径</string>
<string name="susfs_sdcard_path_label">SD 路径</string> <string name="susfs_sdcard_path_label">SDCard 路径</string>
<string name="susfs_set_android_data_path">设置 Android Data 路径</string> <string name="susfs_set_android_data_path">设置 Android Data 路径</string>
<string name="susfs_set_sdcard_path">设置 SD 路径</string> <string name="susfs_set_sdcard_path">设置 SDCard 路径</string>
<!-- SuSFS Enabled Features --> <!-- SuSFS Enabled Features -->
<string name="susfs_enabled_features_description">显示当前 SuSFS 启用的功能状态</string> <string name="susfs_enabled_features_description">显示当前 SuSFS 启用的功能状态</string>
<string name="susfs_no_features_found">未找到功能状态信息</string> <string name="susfs_no_features_found">未找到功能状态信息</string>
<string name="susfs_feature_enabled">已启用</string> <string name="susfs_feature_enabled">已启用</string>
<string name="susfs_feature_disabled">已禁用</string> <string name="susfs_feature_disabled">已禁用</string>
<!-- Feature Labels --> <!-- Feature Labels -->
<string name="sus_path_feature_label">SUS 路径支持</string> <string name="sus_path_feature_label">SuS 路径支持</string>
<string name="sus_mount_feature_label">SUS 挂载支持</string> <string name="sus_mount_feature_label">SuS 挂载支持</string>
<string name="try_umount_feature_label">尝试卸载支持</string> <string name="try_umount_feature_label">尝试卸载支持</string>
<string name="spoof_uname_feature_label">欺骗 uname 支持</string> <string name="spoof_uname_feature_label">欺骗 uname 支持</string>
<string name="spoof_cmdline_feature_label">欺骗 Cmdline/Bootconfig</string> <string name="spoof_cmdline_feature_label">欺骗 Cmdline/Bootconfig</string>
@@ -444,10 +444,10 @@
<string name="auto_default_mount_feature_label">自动默认挂载</string> <string name="auto_default_mount_feature_label">自动默认挂载</string>
<string name="auto_bind_mount_feature_label">自动绑定挂载</string> <string name="auto_bind_mount_feature_label">自动绑定挂载</string>
<string name="auto_try_umount_bind_feature_label">自动尝试卸载绑定挂载</string> <string name="auto_try_umount_bind_feature_label">自动尝试卸载绑定挂载</string>
<string name="hide_symbols_feature_label">隐藏 KSU SUSFS 符号</string> <string name="hide_symbols_feature_label">隐藏 KSU SuSFS 符号</string>
<string name="magic_mount_feature_label">魔法坐骑支持</string> <string name="magic_mount_feature_label">魔法坐骑支持</string>
<string name="sus_kstat_feature_label">SUS Kstat 支持</string> <string name="sus_kstat_feature_label">SuS Kstat 支持</string>
<string name="sus_su_feature_label">SUS SU 模式切换功能</string> <string name="sus_su_feature_label">SuS SU 模式切换功能</string>
<!-- 可切换状态 --> <!-- 可切换状态 -->
<string name="susfs_feature_configurable">可配置的 SuSFS 功能</string> <string name="susfs_feature_configurable">可配置的 SuSFS 功能</string>
<string name="susfs_enable_log_label">SuSFS 启用日志</string> <string name="susfs_enable_log_label">SuSFS 启用日志</string>
@@ -490,11 +490,9 @@
<string name="file_or_directory_path_label">文件/目录路径</string> <string name="file_or_directory_path_label">文件/目录路径</string>
<string name="hint_use_default_value">提示:可以使用 “default” 来使用原始值</string> <string name="hint_use_default_value">提示:可以使用 “default” 来使用原始值</string>
<string name="add_kstat_path_title">添加 Kstat 路径</string> <string name="add_kstat_path_title">添加 Kstat 路径</string>
<string name="kstat_command_description">此命令用于在路径被绑定挂载或覆盖之前添加,用于在内核内存中存储原始 stat 信息</string>
<string name="add">添加</string> <string name="add">添加</string>
<string name="reset_kstat_config_title">重置 Kstat 配置</string> <string name="reset_kstat_config_title">重置 Kstat 配置</string>
<string name="reset_kstat_config_message">确定要清除所有 Kstat 配置吗?此操作不可撤销</string> <string name="reset_kstat_config_message">确定要清除所有 Kstat 配置吗?此操作不可撤销</string>
<string name="confirm_reset">确认重置</string>
<string name="kstat_config_description_title">Kstat 配置说明</string> <string name="kstat_config_description_title">Kstat 配置说明</string>
<string name="kstat_config_description_add_statically">• add_sus_kstat_statically: 静态配置文件/目录的 stat 信息</string> <string name="kstat_config_description_add_statically">• add_sus_kstat_statically: 静态配置文件/目录的 stat 信息</string>
<string name="kstat_config_description_add">• add_sus_kstat: 在绑定挂载前添加路径,存储原始 stat 信息</string> <string name="kstat_config_description_add">• add_sus_kstat: 在绑定挂载前添加路径,存储原始 stat 信息</string>
@@ -503,17 +501,109 @@
<string name="static_kstat_config">静态 Kstat 配置</string> <string name="static_kstat_config">静态 Kstat 配置</string>
<string name="kstat_path_management">Kstat 路径管理</string> <string name="kstat_path_management">Kstat 路径管理</string>
<string name="no_kstat_config_message">暂无 Kstat 配置,点击下方按钮添加配置</string> <string name="no_kstat_config_message">暂无 Kstat 配置,点击下方按钮添加配置</string>
<!-- SuSFS 挂载隐藏控制相关字符串 --> <!-- SuSFS Mount Hiding Control Related Strings -->
<string name="susfs_hide_mounts_control_title">SUS挂载隐藏控制</string> <string name="susfs_hide_mounts_control_title">SuS 挂载隐藏控制</string>
<string name="susfs_hide_mounts_control_description">控制SUS挂载对进程的隐藏行为</string> <string name="susfs_hide_mounts_control_description">控制 SuS 挂载对进程的隐藏行为</string>
<string name="susfs_hide_mounts_for_all_procs_label">对所有进程隐藏SUS挂载</string> <string name="susfs_hide_mounts_for_all_procs_label">对所有进程隐藏 SuS 挂载</string>
<string name="susfs_hide_mounts_for_all_procs_enabled_description">启用后SUS挂载将对所有进程隐藏包括KSU进程</string> <string name="susfs_hide_mounts_for_all_procs_enabled_description">启用后SuS 挂载将对所有进程隐藏,包括 KSU 进程</string>
<string name="susfs_hide_mounts_for_all_procs_disabled_description">禁用后SUS挂载仅对非KSU进程隐藏KSU进程可以看到挂载</string> <string name="susfs_hide_mounts_for_all_procs_disabled_description">禁用后SuS 挂载仅对非 KSU 进程隐藏KSU 进程可以看到挂载</string>
<string name="susfs_hide_mounts_all_enabled">已启用对所有进程隐藏SUS挂载</string> <string name="susfs_hide_mounts_all_enabled">已启用对所有进程隐藏 SuS 挂载</string>
<string name="susfs_hide_mounts_all_disabled">已禁用对所有进程隐藏SUS挂载</string> <string name="susfs_hide_mounts_all_disabled">已禁用对所有进程隐藏 SuS 挂载</string>
<string name="susfs_hide_mounts_recommendation">建议在屏幕解锁后或在service.shboot-completed.sh阶段设置为禁用这可以修复一些依赖KSU进程挂载的root应用的问题</string> <string name="susfs_hide_mounts_recommendation">建议在屏幕解锁后或在 service.shboot-completed.sh 阶段设置为禁用,这可以修复一些依赖 KSU 进程挂载的 root 应用的问题</string>
<string name="susfs_hide_mounts_current_setting">当前设置: %s</string> <string name="susfs_hide_mounts_current_setting">当前设置: %s</string>
<string name="susfs_hide_mounts_setting_all">对所有进程隐藏</string> <string name="susfs_hide_mounts_setting_all">对所有进程隐藏</string>
<string name="susfs_hide_mounts_setting_non_ksu">仅对非KSU进程隐藏</string> <string name="susfs_hide_mounts_setting_non_ksu">仅对非 KSU 进程隐藏</string>
<string name="susfs_run">运行</string> <string name="susfs_run">运行</string>
<string name="kernel_simple_kernel">内核版本简洁模式</string>
<string name="kernel_simple_kernel_summary">启用或禁用 SukiSU 内核版本显示的简洁模式</string>
<string name="susfs_android_data_path_set">Android Data 路径已设置为: %s</string>
<string name="susfs_sdcard_path_set">SDCard 路径已设置为: %s</string>
<string name="susfs_path_setup_warning">路径设置可能未完全成功,但将继续添加 SuS 路径</string>
<!-- 备份和还原相关字符串 -->
<string name="susfs_backup_title">备份</string>
<string name="susfs_backup_description">创建所有 SuSFS 配置的备份。备份文件将包含所有设置、路径和配置信息。</string>
<string name="susfs_backup_create">创建备份</string>
<string name="susfs_backup_success">备份创建成功:%s</string>
<string name="susfs_backup_failed">备份创建失败:%s</string>
<string name="susfs_backup_file_not_found">备份文件未找到</string>
<string name="susfs_backup_invalid_format">无效的备份文件格式</string>
<string name="susfs_backup_version_mismatch">备份版本不匹配,但将尝试还原</string>
<string name="susfs_restore_title">还原</string>
<string name="susfs_restore_description">从备份文件还原 SuSFS 配置。这将覆盖所有当前设置。</string>
<string name="susfs_restore_select_file">选择备份文件</string>
<string name="susfs_restore_success" formatted="false">配置还原成功,备份创建于 %s来自设备%s</string>
<string name="susfs_restore_failed">还原失败:%s</string>
<string name="susfs_restore_confirm_title">确认还原</string>
<string name="susfs_restore_confirm_description">这将覆盖所有当前的 SuSFS 配置。您确定要继续吗?</string>
<string name="susfs_restore_confirm">还原</string>
<string name="susfs_backup_info_date">备份日期:%s</string>
<string name="susfs_backup_info_device">设备:%s</string>
<string name="susfs_backup_info_version">版本:%s</string>
<string name="hide_bl_script">隐藏 BL 脚本</string>
<string name="hide_bl_script_description">启用隐藏 Bootloader 解锁状态脚本</string>
<string name="cleanup_residue">清理工具残留</string>
<string name="cleanup_residue_description">清理各种模块以及工具的残留文件和目录(可能会误删导致丢失以及无法启动,谨慎使用)</string>
<string name="susfs_edit_sus_path">编辑 SuS 路径</string>
<string name="susfs_edit_sus_mount">编辑 SuS 挂载</string>
<string name="susfs_edit_try_umount">编辑尝试卸载</string>
<string name="edit_kstat_statically_title">编辑 Kstat 静态配置</string>
<string name="edit_kstat_path_title">编辑 Kstat 路径</string>
<string name="susfs_save">保存</string>
<string name="edit">编辑</string>
<string name="delete">删除</string>
<string name="update">更新</string>
<string name="kstat_config_updated">Kstat 配置更新</string>
<string name="kstat_path_updated">Kstat 路径更新</string>
<string name="susfs_update_full_clone">Susfs 完整克隆更新</string>
<string name="umount_zygote_iso_service">卸载 Zygote 隔离服务</string>
<string name="umount_zygote_iso_service_description">启用此选项将在系统启动时卸载 Zygote 隔离服务挂载点</string>
<string name="umount_zygote_iso_service_enabled">Zygote 隔离服务卸载已启用</string>
<string name="umount_zygote_iso_service_disabled">Zygote 隔离服务卸载已禁用</string>
<string name="app_paths_section">应用路径</string>
<string name="other_paths_section">其他路径</string>
<string name="add_custom_path">其他</string>
<string name="add_app_path">应用</string>
<string name="susfs_add_app_path">添加应用路径</string>
<string name="search_apps">搜索应用</string>
<string name="selected_apps_count">%1$d 个已选应用</string>
<string name="already_added_apps_count">%1$d 个已添加应用</string>
<string name="all_apps_already_added">所有应用均已添加</string>
<string name="dynamic_sign_title">动态签名配置</string>
<string name="dynamic_sign_enabled_summary">已启用(大小: %s</string>
<string name="dynamic_sign_disabled">未启用</string>
<string name="enable_dynamic_sign">启用动态签名</string>
<string name="signature_size">签名大小</string>
<string name="signature_hash">签名哈希值</string>
<string name="hash_must_be_64_chars">哈希值必须是 64 位十六进制字符</string>
<string name="dynamic_sign_set_success">动态签名配置设置成功</string>
<string name="dynamic_sign_set_failed">动态签名配置设置失败</string>
<string name="invalid_sign_config">无效的签名配置</string>
<string name="dynamic_sign_disabled_success">动态签名已禁用</string>
<string name="dynamic_sign_clear_failed">清除动态签名错误</string>
<string name="dynamic_signature">动态</string>
<string name="signature_index">签名 %1$d</string>
<string name="unknown_signature">未知</string>
<string name="multi_manager_list">活跃管理器</string>
<string name="no_active_manager">无活跃管理器</string>
<string name="home_zygisk_implement">Zygisk 实现</string>
<!-- 循环路径相关 -->
<string name="susfs_tab_sus_loop_paths">SUS循环路径</string>
<string name="susfs_add_sus_loop_path">添加SUS循环路径</string>
<string name="susfs_edit_sus_loop_path">编辑SUS循环路径</string>
<string name="susfs_loop_path_added_success">SUS循环路径添加成功: %1$s</string>
<string name="susfs_loop_path_removed">SUS循环路径已移除: %1$s</string>
<string name="susfs_loop_path_updated">SUS循环路径已更新: %1$s -> %2$s</string>
<string name="susfs_no_loop_paths_configured">未配置SUS循环路径</string>
<string name="susfs_reset_loop_paths_title">重置循环路径</string>
<string name="susfs_reset_loop_paths_message">确定要清空所有SUS循环路径吗此操作无法撤销。</string>
<string name="susfs_loop_path_label">循环路径</string>
<string name="susfs_loop_path_placeholder">/data/example/path</string>
<string name="susfs_loop_path_restriction_warning">注意:只有不在/storage/和/sdcard/内的路径才能通过循环路径添加。</string>
<string name="susfs_loop_path_invalid_location">错误:循环路径不能位于/storage/或/sdcard/目录内</string>
<string name="loop_paths_section">循环路径</string>
<string name="add_loop_path">添加循环路径</string>
<!-- 循环路径功能描述 -->
<string name="sus_loop_path_feature_label">SUS循环路径</string>
<string name="sus_loop_paths_description_title">循环路径配置</string>
<string name="sus_loop_paths_description_text">循环路径会在每次非root用户应用或隔离服务启动时重新标记为SUS_PATH。这有助于解决添加的路径可能因inode状态重置或内核中inode重新创建而失效的问题</string>
</resources> </resources>

Some files were not shown because too many files have changed in this diff Show More