Compare commits

...

220 Commits

Author SHA1 Message Date
Rifat Azad
dc7ae2db5f manager: fix status card startActivity intent fallback to not allow lkm install on non gki 2025-06-24 09:53:20 +06:00
Rifat Azad
b3b7ef1cb3 manager: dont show developer options and banner toggle when ksuversion is null 2025-06-24 09:26:14 +06:00
Rifat Azad
4de4d1e091 ksud: second test of vendor_boot patching now handling vendor_boot partition and restore partition 2025-06-24 09:17:24 +06:00
Rifat Azad
0beea57ab7 ksud: test vendor_boot patching for some newer devices 2025-06-23 18:17:46 +06:00
Rifat Azad
49aee1ff4c manager: remove susfs info from status card and merge it to info card 2025-06-21 17:01:21 +06:00
Rifat Azad
f7a3699fe3 manager: show module update count as badge in bottom bar instead of status card 2025-06-21 12:44:29 +06:00
5ec1cff
66d42de599 app: persist show system app settings 2025-06-20 00:54:23 +06:00
Kaorun
d562594ae1 Update Module.kt 2025-06-19 13:35:05 +06:00
Rifat Azad
02afc6710c manager: show sucmpat when both sucompat is disabled and sus_su enabled 2025-06-18 20:23:35 +06:00
Caner Karaca
9d9f9ed5d5 Update 2025-06-16 06:00:17 +06:00
kam821
b3b6320946 Update Polish translation
- Added missing strings
2025-06-16 05:56:46 +06:00
Rifat Azad
d43b8320ad manager: minor improvements 2025-06-16 05:55:14 +06:00
dependabot[bot]
a2260ae330 build(deps): bump the crates group across 1 directory with 27 updates
Bumps the crates group with 22 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.38` | `4.5.40` |
| [which](https://github.com/harryfei/which-rs) | `7.0.3` | `8.0.0` |
| [getopts](https://github.com/rust-lang/getopts) | `0.2.21` | `0.2.23` |
| [adler2](https://github.com/oyvindln/adler2) | `2.0.0` | `2.0.1` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.18` | `0.6.19` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.10` | `1.0.11` |
| [anstyle-parse](https://github.com/rust-cli/anstyle) | `0.2.6` | `0.2.7` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.2` | `1.1.3` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.8` | `3.0.9` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.17.0` | `3.18.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.23` | `1.2.26` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.4` | `0.7.5` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.3` | `1.0.4` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.1` | `1.1.2` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.4` | `2.7.5` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.8` | `0.8.9` |
| [once_cell_polyfill](https://github.com/polyfill-rs/once_cell_polyfill) | `1.70.0` | `1.70.1` |
| [rustc-demangle](https://github.com/rust-lang/rustc-demangle) | `0.1.24` | `0.1.25` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.20` | `1.0.21` |
| [syn](https://github.com/dtolnay/syn) | `2.0.101` | `2.0.102` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.45.0` | `1.45.1` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.1.1` | `0.1.2` |



Updates `clap` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.38...clap_complete-v4.5.40)

Updates `which` from 7.0.3 to 8.0.0
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/7.0.3...8.0.0)

Updates `getopts` from 0.2.21 to 0.2.23
- [Release notes](https://github.com/rust-lang/getopts/releases)
- [Changelog](https://github.com/rust-lang/getopts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/getopts/compare/v0.2.21...v0.2.23)

Updates `adler2` from 2.0.0 to 2.0.1
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

Updates `anstream` from 0.6.18 to 0.6.19
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.18...anstream-v0.6.19)

Updates `anstyle` from 1.0.10 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.10...v1.0.11)

Updates `anstyle-parse` from 0.2.6 to 0.2.7
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.6...anstyle-parse-v0.2.7)

Updates `anstyle-query` from 1.1.2 to 1.1.3
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.3)

Updates `anstyle-wincon` from 3.0.8 to 3.0.9
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.8...anstyle-wincon-v3.0.9)

Updates `bumpalo` from 3.17.0 to 3.18.1
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.17.0...v3.18.1)

Updates `cc` from 1.2.23 to 1.2.26
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.26)

Updates `clap_builder` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.38...v4.5.40)

Updates `clap_derive` from 4.5.32 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.32...v4.5.40)

Updates `clap_lex` from 0.7.4 to 0.7.5
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.4...clap_lex-v0.7.5)

Updates `colorchoice` from 1.0.3 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `flate2` from 1.1.1 to 1.1.2
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

Updates `libz-rs-sys` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

Updates `miniz_oxide` from 0.8.8 to 0.8.9
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

Updates `once_cell_polyfill` from 1.70.0 to 1.70.1
- [Changelog](https://github.com/polyfill-rs/once_cell_polyfill/blob/v1.70.1/CHANGELOG.md)
- [Commits](https://github.com/polyfill-rs/once_cell_polyfill/compare/v1.70.0...v1.70.1)

Updates `rustc-demangle` from 0.1.24 to 0.1.25
- [Commits](https://github.com/rust-lang/rustc-demangle/commits)

Updates `rustversion` from 1.0.20 to 1.0.21
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.20...1.0.21)

Updates `syn` from 2.0.101 to 2.0.102
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.101...2.0.102)

Updates `tokio` from 1.45.0 to 1.45.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.45.1)

Updates `unicode-width` from 0.1.14 to 0.2.1
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.14...v0.2.1)

Updates `windows-link` from 0.1.1 to 0.1.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zlib-rs` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: which
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: getopts
  dependency-version: 0.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: adler2
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstream
  dependency-version: 0.6.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-parse
  dependency-version: 0.2.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-query
  dependency-version: 1.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bumpalo
  dependency-version: 3.18.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_lex
  dependency-version: 0.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libz-rs-sys
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-version: 0.8.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell_polyfill
  dependency-version: 1.70.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustc-demangle
  dependency-version: 0.1.25
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustversion
  dependency-version: 1.0.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-version: 2.0.102
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-width
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-link
  dependency-version: 0.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zlib-rs
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:53 +06:00
dependabot[bot]
aa221acad1 build(deps): bump the crates group across 1 directory with 28 updates
Bumps the crates group with 23 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.38` | `4.5.40` |
| [which](https://github.com/harryfei/which-rs) | `7.0.3` | `8.0.0` |
| [getopts](https://github.com/rust-lang/getopts) | `0.2.21` | `0.2.23` |
| [adler2](https://github.com/oyvindln/adler2) | `2.0.0` | `2.0.1` |
| [anstream](https://github.com/rust-cli/anstyle) | `0.6.18` | `0.6.19` |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.10` | `1.0.11` |
| [anstyle-parse](https://github.com/rust-cli/anstyle) | `0.2.6` | `0.2.7` |
| [anstyle-query](https://github.com/rust-cli/anstyle) | `1.1.2` | `1.1.3` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.8` | `3.0.9` |
| [bumpalo](https://github.com/fitzgen/bumpalo) | `3.17.0` | `3.18.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.23` | `1.2.26` |
| [cfg-if](https://github.com/rust-lang/cfg-if) | `1.0.0` | `1.0.1` |
| [clap_lex](https://github.com/clap-rs/clap) | `0.7.4` | `0.7.5` |
| [colorchoice](https://github.com/rust-cli/anstyle) | `1.0.3` | `1.0.4` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.1` | `1.1.2` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.7.4` | `2.7.5` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.8` | `0.8.9` |
| [once_cell_polyfill](https://github.com/polyfill-rs/once_cell_polyfill) | `1.70.0` | `1.70.1` |
| [rustc-demangle](https://github.com/rust-lang/rustc-demangle) | `0.1.24` | `0.1.25` |
| [rustversion](https://github.com/dtolnay/rustversion) | `1.0.20` | `1.0.21` |
| [syn](https://github.com/dtolnay/syn) | `2.0.101` | `2.0.102` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.45.0` | `1.45.1` |
| [windows-link](https://github.com/microsoft/windows-rs) | `0.1.1` | `0.1.2` |



Updates `clap` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.38...clap_complete-v4.5.40)

Updates `which` from 7.0.3 to 8.0.0
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/7.0.3...8.0.0)

Updates `getopts` from 0.2.21 to 0.2.23
- [Release notes](https://github.com/rust-lang/getopts/releases)
- [Changelog](https://github.com/rust-lang/getopts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/getopts/compare/v0.2.21...v0.2.23)

Updates `adler2` from 2.0.0 to 2.0.1
- [Changelog](https://github.com/oyvindln/adler2/blob/main/CHANGELOG.md)
- [Commits](https://github.com/oyvindln/adler2/commits)

Updates `anstream` from 0.6.18 to 0.6.19
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.18...anstream-v0.6.19)

Updates `anstyle` from 1.0.10 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.10...v1.0.11)

Updates `anstyle-parse` from 0.2.6 to 0.2.7
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-parse-v0.2.6...anstyle-parse-v0.2.7)

Updates `anstyle-query` from 1.1.2 to 1.1.3
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-query-v1.1.2...anstyle-query-v1.1.3)

Updates `anstyle-wincon` from 3.0.8 to 3.0.9
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.8...anstyle-wincon-v3.0.9)

Updates `bumpalo` from 3.17.0 to 3.18.1
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.17.0...v3.18.1)

Updates `cc` from 1.2.23 to 1.2.26
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.26)

Updates `cfg-if` from 1.0.0 to 1.0.1
- [Release notes](https://github.com/rust-lang/cfg-if/releases)
- [Changelog](https://github.com/rust-lang/cfg-if/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cfg-if/compare/1.0.0...v1.0.1)

Updates `clap_builder` from 4.5.38 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.38...v4.5.40)

Updates `clap_derive` from 4.5.32 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.32...v4.5.40)

Updates `clap_lex` from 0.7.4 to 0.7.5
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_lex-v0.7.4...clap_lex-v0.7.5)

Updates `colorchoice` from 1.0.3 to 1.0.4
- [Commits](https://github.com/rust-cli/anstyle/compare/colorchoice-v1.0.3...colorchoice-v1.0.4)

Updates `flate2` from 1.1.1 to 1.1.2
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

Updates `libz-rs-sys` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

Updates `miniz_oxide` from 0.8.8 to 0.8.9
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

Updates `once_cell_polyfill` from 1.70.0 to 1.70.1
- [Changelog](https://github.com/polyfill-rs/once_cell_polyfill/blob/v1.70.1/CHANGELOG.md)
- [Commits](https://github.com/polyfill-rs/once_cell_polyfill/compare/v1.70.0...v1.70.1)

Updates `rustc-demangle` from 0.1.24 to 0.1.25
- [Commits](https://github.com/rust-lang/rustc-demangle/commits)

Updates `rustversion` from 1.0.20 to 1.0.21
- [Release notes](https://github.com/dtolnay/rustversion/releases)
- [Commits](https://github.com/dtolnay/rustversion/compare/1.0.20...1.0.21)

Updates `syn` from 2.0.101 to 2.0.102
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.101...2.0.102)

Updates `tokio` from 1.45.0 to 1.45.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.45.0...tokio-1.45.1)

Updates `unicode-width` from 0.1.14 to 0.2.1
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.14...v0.2.1)

Updates `windows-link` from 0.1.1 to 0.1.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zlib-rs` from 0.5.0 to 0.5.1
- [Release notes](https://github.com/trifectatechfoundation/zlib-rs/releases)
- [Changelog](https://github.com/trifectatechfoundation/zlib-rs/blob/main/docs/release.md)
- [Commits](https://github.com/trifectatechfoundation/zlib-rs/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: which
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: crates
- dependency-name: getopts
  dependency-version: 0.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: adler2
  dependency-version: 2.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstream
  dependency-version: 0.6.19
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-parse
  dependency-version: 0.2.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-query
  dependency-version: 1.1.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: bumpalo
  dependency-version: 3.18.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cfg-if
  dependency-version: 1.0.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_derive
  dependency-version: 4.5.40
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_lex
  dependency-version: 0.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: colorchoice
  dependency-version: 1.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libz-rs-sys
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: miniz_oxide
  dependency-version: 0.8.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: once_cell_polyfill
  dependency-version: 1.70.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustc-demangle
  dependency-version: 0.1.25
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rustversion
  dependency-version: 1.0.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: syn
  dependency-version: 2.0.102
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: unicode-width
  dependency-version: 0.2.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: windows-link
  dependency-version: 0.1.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zlib-rs
  dependency-version: 0.5.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:36 +06:00
dependabot[bot]
c41d35db62 build(deps): bump the maven group across 1 directory with 9 updates
Bumps the maven group with 9 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.compose:compose-bom | `2025.05.01` | `2025.06.00` |
| androidx.lifecycle:lifecycle-runtime-ktx | `2.9.0` | `2.9.1` |
| androidx.lifecycle:lifecycle-runtime-compose | `2.9.0` | `2.9.1` |
| androidx.lifecycle:lifecycle-viewmodel-compose | `2.9.0` | `2.9.1` |
| androidx.webkit:webkit | `1.13.0` | `1.14.0` |
| [org.lsposed.libcxx:libcxx](https://github.com/LSPosed/prefab-libcxx) | `27.0.12077973` | `28.1.13356709` |
| com.android.application | `8.10.0` | `8.10.1` |
| com.android.library | `8.10.0` | `8.10.1` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.21-2.0.1` | `2.1.21-2.0.2` |



Updates `androidx.compose:compose-bom` from 2025.05.01 to 2025.06.00

Updates `androidx.lifecycle:lifecycle-runtime-ktx` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.9.0 to 2.9.1

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.9.0 to 2.9.1

Updates `androidx.webkit:webkit` from 1.13.0 to 1.14.0

Updates `org.lsposed.libcxx:libcxx` from 27.0.12077973 to 28.1.13356709
- [Commits](https://github.com/LSPosed/prefab-libcxx/compare/27.0.12077973...28.1.13356709)

Updates `com.android.application` from 8.10.0 to 8.10.1

Updates `com.android.library` from 8.10.0 to 8.10.1

Updates `com.android.library` from 8.10.0 to 8.10.1

Updates `com.google.devtools.ksp` from 2.1.21-2.0.1 to 2.1.21-2.0.2
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.21-2.0.1...2.1.21-2.0.2)

---
updated-dependencies:
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.06.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: androidx.webkit:webkit
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: org.lsposed.libcxx:libcxx
  dependency-version: 28.1.13356709
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.21-2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 23:31:19 +06:00
luigimak
e5f0c733b8 Update italian translation
add developer translation, values-it/strings.xml
2025-06-15 23:26:29 +06:00
kam821
70b52f85e9 Update Polish translation
- Added missing strings
- Updated translations for refreshed strings
2025-06-15 23:26:17 +06:00
роизен
303b5192ec Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
443d3a6abe Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
a2a7383343 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
ed64f933f5 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
4c7ad8eac4 Update strings.xml 2025-06-15 23:26:05 +06:00
роизен
6a922febcd Update ukranian 2025-06-15 23:26:05 +06:00
Rifat Azad
71eba5df8b manager: disable module and superuser navigation if sucompat is disabled and also show an indicator in status card 2025-06-15 22:07:15 +06:00
Rifat Azad
f1ef0afc20 manager: finish activity after flashing module intent is completed 2025-06-15 21:09:31 +06:00
Rifat Azad
844c9f94e9 manager: fix flashing lkm duplication 2025-06-15 20:13:32 +06:00
Rifat Azad
07a4d3457c manager: add separate developer menu 2025-06-15 13:00:30 +06:00
Rifat Azad
8c9728df95 manager: fix zip not flashing from content:// uri 2025-06-15 12:09:32 +06:00
Rifat Azad
14ec1194e4 manager: add support for opening zip file and directly flash module 2025-06-15 07:09:13 +06:00
Rifat Azad
a37f398cc7 kernel/Makefile: check kernelsu driver version from online git repo first, if fails then check local .git and if that also fails then use hardcoded fallback 2025-06-14 22:52:10 +06:00
backslashxx
80bd797737 kernel: ksud: remove remove read_iter requirement
nothing uses this on old kernels, so even backporting this to file_operations
is not really needed

https://elixir.bootlin.com/linux/v3.16.85/source/include/linux/fs.h#L1487

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:14:12 +06:00
backslashxx
600d9ce5d2 kernel: throne_tracker: resolve s_magic for < 3.9
throne_tracker, cross-fs avoidance:
f_inode is f_path.dentry->d_inode
so file->f_inode->i_sb->s_magic is file->f_path.dentry->d_inode->i_sb->s_magic

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:14:03 +06:00
backslashxx
f15d9b18e9 kernel: ksud: d_is_reg to IS_REG
d_is_reg requires 4.0
 - e36cb0b89c
IS_REG is still there on 6.15 so I do NOT see any issues forcing it for all.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:13:13 +06:00
backslashxx
aa19e8c609 kernel: throne_tracker: add strscpy/strlcpy compat
strscpy requires 4.3
strscpy on this usage can be replaced with strncpy + null term.
kernel gives us an option though.
strlcpy is fast af, hotrod fast. It’s just memcpy + null term, so lets go with that.
it got dropped in 6.8 due to risk concerns, so for those, lets use og strscpy.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:13:06 +06:00
backslashxx
2b2320000c kernel: throne_tracker: remove unneeded check here
come to think of it, this part is only about folders
2025-06-14 20:12:51 +06:00
backslashxx
06135cc827 kernel: apk_sign: loop file open on is_manager_apk
lets loop on this and wait for installation to finish

this is the third race.
2025-06-14 20:12:14 +06:00
backslashxx
fc58bdf0e2 kernel: throne_tracker: harden packages.list checker further 2025-06-14 20:08:53 +06:00
backslashxx
9b5e60912d kernel: throne_tracker, apk_sign: functionify d_lock spinlock check 2025-06-14 20:08:23 +06:00
backslashxx
c108a8ed32 kernel: throne_tracker: harden track_throne_function file read
this probably wont happen, but just to make sure, we dont block the rename now
so there is really a chance that this does not exist yet when the kthread runs.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:07:24 +06:00
F-19-F
adce657583 kernel: ksud: provide is_ksu_transition check v2
context: this is known by many as `selinux hook`, `4.9 hook`

add is_ksu_transition check which allows ksud execution under nosuid.
it also eases up integration on 3.X kernels that does not have check_nnp_nosuid.

Usage:
	if (is_ksu_transition(old_tsec, new_tsec))
		return 0;

on either check_nnp_nosuid or selinux_bprm_set_creds (after execve sid reset)

reference: dfe003c9fd

taken from:
`allow init exec ksud under nosuid`
- 3df9df42a6
- https://github.com/tiann/KernelSU/pull/166#issue-1565872173

250611-edit:
- remove ksu_execveat_hook entry check
- turns out some devices needs the transition for multiple times

Reported-by: edenadversary <143865198+edenadversary@users.noreply.github.com>
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:07:16 +06:00
rsuntk
d6601e1e54 kernel: core_hook: fix refcount leaks on try_umount (#2635)
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Signed-off-by: rsuntk <rsuntk@yukiprjkt.my.id>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:03:30 +06:00
backslashxx
0d4efa649f kernel: throne_tracker: avoid cross-fs traversal using s_magic check (#2633)
Skip directories that does NOT have the same magic as /data/app.
This is to avoid scanning incfs and any other stacked filesystems.

While this is way dumber, it's way cheaper.
no kern_path(), no missable path_put(), no ref handling.

This supercedes
`throne_tracker: avoid cross fs access
(https://github.com/tiann/KernelSU/pull/2626)`
- upstream
0b6998b474

Signed-off-by: backslashxx
<118538522+backslashxx@users.noreply.github.com>
2025-06-14 20:03:04 +06:00
Wang Han
85f4e6ac27 Switch to prepare_creds/commit_creds (#2631)
Update API as per kernel doc recommends, also fix setup_groups refcount
leak while at it.
2025-06-14 20:01:36 +06:00
Rifat Azad
c91f9c18ec Revert "kernel: ksud, throne_tracker: small changes for UL"
This reverts commit c4deee1e49.
2025-06-14 19:54:59 +06:00
Rifat Azad
bf35f73430 Revert "kernel: throne_tracker: move throne_tracker to kthread"
This reverts commit 6a6fc07cd4.
2025-06-14 19:54:36 +06:00
Rifat Azad
ad290a51a0 manager: fully polish and refactor module card ui 2025-06-12 23:40:14 +06:00
Rifat Azad
d218346613 manager: keep mount system preference persistent without breaking rootAvailable() checks 2025-06-12 21:50:16 +06:00
Rifat Azad
502e5599fe manager: improve module card ui 2025-06-12 21:05:40 +06:00
Rifat Azad
11fb52b929 manager: merge legacy and revamped module card ui, also tapping the card open webui when available and actions when available but if both are available then prefer webui 2025-06-12 13:03:41 +06:00
Rifat Azad
057388ccef manager: do not go at the start of the superuser list and stay where you were after app profile changes (resolves #491) 2025-06-12 10:42:53 +06:00
Rifat Azad
67759ad723 manager: update app state upon app profile changes
properly update the superuser app list state after changes have been made to app profile
2025-06-12 10:18:51 +06:00
Rifat Azad
f231cbdba7 Revert "manager: refresh superuser applist on appprofile exit"
This reverts commit fcbb02a115.
2025-06-12 08:46:38 +06:00
Suraj J Pai
7abc9bc821 [BUGFIX] manager: Fix Module Flashing fails when orientation changes (#503)
The issue is caused by re-rendering of Activity when orientation changes.
All states are reset when it is re-rendered. Using ViewModel to manage zipUri fixes the issue.

Fixes issue: https://github.com/KernelSU-Next/KernelSU-Next/issues/488
2025-06-12 04:44:45 +06:00
GMárton
e7697d86fe Update hungarian translation (#489)
* Update hungarian translation

* Fix typo

---------

Co-authored-by: Marty <marton.garamszegi@mptrdev.com>
2025-06-11 04:30:29 +06:00
1alessandro1
68394fddd5 Update doc (#485) 2025-06-11 04:30:14 +06:00
cvnertnc
90d34bf511 Manager: update values-tr/strings.xml (#469) 2025-06-11 04:29:47 +06:00
luigimak
236fbc7615 Update Italian Translation (#461)
* Update Italian Translation

values-it/strings.xml

* fix use_webuix_summary

Update values-it/strings.xml

* Update values-it/strings.xml

* Add module_size values-it/strings.xml

* Add settings_banner values-it/strings.xml

* fix settings_banner
2025-06-11 04:29:31 +06:00
mr_vokintos
6871cbdba7 Update Russian (#466)
* Update strings.xml

Update Russian

* Update strings.xml

* Update strings.xml
2025-06-11 04:29:15 +06:00
AxelPLN(Axel Yinjia Huang)
38a9949211 Update manager translations for zh-rCN & zh-rTW (#456)
* Update translations for zh-rCN &zh-rTW to 0a42dbf

* Add zh-rCN & zh-rTW translations for functions as legacyUI & module banner and so on.

Improve translations.
2025-06-11 04:27:58 +06:00
igor
9fba0faa43 Update portuguese translation (#453)
* Update portuguese translation

* Update strings.xml

* Update strings.xml

* Update README.md

* Update README_PT-BR.md

* Update strings.xml

* Update strings.xml
2025-06-11 04:26:43 +06:00
Caner Karaca
b1250b002e Workflow Updates (#481)
* Update

* Use ubuntu-22.04

* Revert some renamings

* Create renovate.json

* oops
2025-06-11 04:23:22 +06:00
Rifat Azad
10f7d5cf50 Revert "manager: keep mount system preference persistent"
This reverts commit 609926bff1.
2025-06-10 02:31:14 +06:00
rifsxd
0c883ddfd6 manager: let module banner be set locally from module dir
ex: banner=banner.png , banner=example.webp banner=temp/hello.jpg
if banner string value starts with http, https then it will try to fetch from online.

Co-authored-by: fatalcoder524 <11532648+fatalcoder524@users.noreply.github.com>
2025-06-06 04:09:16 +06:00
Paul
3921175e4c kernel: core_hook: intercept devpts via security_inode_permission LSM (#480)
`ksu handles devpts with selinux lsm hook` - aviraxp

- no, not yet, but yes we can, thats a good idea.

This change tries to do that, so instead of hooking pts_unix98_lookup or
devpts_get_priv, we just watch security_inode_permission, if its devpts,
pass it along to the original handler.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-authored-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-05 06:20:53 +06:00
5ec1cff
84fdcf8bf5 throne_tracker: avoid cross fs access 2025-06-03 03:30:54 +06:00
rifsxd
886cfd5a33 manager: adjusted module banner fade opacity 2025-06-03 03:28:42 +06:00
rifsxd
aea384bdd4 manager: do dynamic fade for banner based on monet when available 2025-06-03 01:49:57 +06:00
rifsxd
84695cea71 manager: do white fade for banner when on light mode 2025-06-03 00:58:58 +06:00
rifsxd
f91afe6c46 manager: add module background banners"
module devs can add banners for their modules through module.prop config

Example:

banner=https://something.com/banner.png
2025-06-03 00:34:37 +06:00
rifsxd
3f7e731df6 manager: fix update tag attached to wrong module after using sort options (fix #473) 2025-06-02 15:34:30 +06:00
rifsxd
582662dce9 manager: fix back gestures conflicting with LKM warning window (fix #474) 2025-06-02 15:12:59 +06:00
rifsxd
f3b49723e8 manager: add sorting by size for module list 2025-06-01 21:03:04 +06:00
backslashxx
c4deee1e49 kernel: ksud, throne_tracker: small changes for UL
Safe Ultra-Legacy changes that don't deserve their own commit

d_is_reg requires 4.0
 - e36cb0b89c
IS_REG is still there on 6.15 so I do NOT see any issues forcing it for all.

strscpy requires 4.3
strscpy on this usage can be replaced with strncpy + null term.
kernel gives us an option though.
strlcpy is fast af, hotrod fast. It’s just memcpy + null term, so lets go with that.
it got dropped in 6.8 due to risk concerns, so for those, lets use og strscpy.
ref: openwrt/packages #26453

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-01 20:09:20 +06:00
Yaroslav Zviezda
6a6fc07cd4 kernel: throne_tracker: move throne_tracker to kthread
Runs throne_tracker() in kthread instead of blocking the caller.
Prevents full lockup during installation and removing the manager.

This also looks for manager UID in /data/system/packages.list, not
/data/system/packages.list.tmp

Nice additional side effect is a faster booting.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
Co-Authored-By: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-06-01 20:03:38 +06:00
rifsxd
d8cb7ef772 manager: fix module sorting state when module list is null initially before modules are fetched (this should fix #470) 2025-06-01 19:47:43 +06:00
rifsxd
dddf2f06a0 manager: show reboot button when flashing LKM directly and inactive slot 2025-06-01 15:46:25 +06:00
rifsxd
e7e935aeb2 manager: added module size label 2025-06-01 15:37:13 +06:00
rifsxd
cb146200aa manager: output full logs of actions and flash modules when developer option is enabled 2025-06-01 04:05:35 +06:00
rifsxd
609926bff1 manager: keep mount system preference persistent 2025-06-01 03:37:10 +06:00
rifsxd
8803058521 manager: added amoled theme for non material u devices 2025-06-01 02:33:02 +06:00
rifsxd
c74805b12b manager: autoexpand infocard when dev option is enabled 2025-06-01 01:43:08 +06:00
rifsxd
43870237fc manager: removed unused imports from backuprestore.kt 2025-06-01 01:17:44 +06:00
rifsxd
ca24085b5b manager: add a separate customization screen in settings 2025-06-01 01:17:35 +06:00
rifsxd
93191c2b8b manager: add legacy ui toggle 2025-06-01 00:20:23 +06:00
rifsxd
ebc3ded2b2 manager: removed module config to override webui engine 2025-05-30 04:18:02 +06:00
rifsxd
d9d1c874ab manager: improved module update detection and pre-load applist and modulelist 2025-05-30 02:09:13 +06:00
rifsxd
08477fc361 manager: improved module update status label 2025-05-29 20:55:11 +06:00
rifsxd
11836b876f manager: change home screen power menu icon to a proper power menu icon 2025-05-29 17:24:20 +06:00
rifsxd
bf20965c46 manager: make the module card neat and clean with less clutter and add useful indicators 2025-05-29 16:14:15 +06:00
rifsxd
22a48e52eb manager: rearrange and refactor the Module Card UI 2025-05-28 21:50:17 +06:00
rifsxd
15b703b5f2 manager: show webui and action label when a module has it 2025-05-28 20:42:57 +06:00
rifsxd
18f0eb8a36 manager: better spacing between app package name and label item in superuser 2025-05-28 18:12:23 +06:00
rifsxd
32cdcc6fbe manager: improve layout and look of module cards 2025-05-28 17:57:46 +06:00
rifsxd
437c4b9bc5 manager: improved AMOLED mode 2025-05-28 16:11:00 +06:00
rifsxd
0a42dbf5ba manager: add amoled mode 2025-05-28 04:21:38 +06:00
igor
ea4f319898 Update strings.xml (#444) 2025-05-28 01:14:02 +06:00
Rifat Azad
7b6b944106 docs: updated architecture support 2025-05-28 01:13:54 +06:00
rifsxd
59c966771e manager: show modules update count on status card only if any update is vailable 2025-05-27 03:24:32 +06:00
rifsxd
a83c20b667 manager: removed the logic for if overlayfs is not found then show warning in module screen
since magic_mount is the default mount system and if overlayfs is not available we cant swtich to use overlayfs anyways
2025-05-27 03:00:04 +06:00
rifsxd
d5c4f85d73 manager: move the wx platform init to the Application class so it starts as soon as the app process launches 2025-05-27 02:05:58 +06:00
rifsxd
36f683a299 manager: fix module list empty until refreshed manually 2025-05-27 01:43:30 +06:00
Rifat Azad
652e9719ed docs: removed LKM deprecation information 2025-05-26 13:31:46 +06:00
Der_Googler
011b658422 manager: Improvements (#443)
* manager: bump mmrl

* manager: use ktx ext Str.toUri

* manager: add "webui-engine" from config.json

This allows the developer to override the user preference of the selected WebUI engine.

Supported engines are:

- `wx` for WebUI X
- `ksu` for the KernelSU WebUI

All not named strings will default to `wx`

R.string.use_webuix_summary needs proper translations

* manager: add support for multilingual module meta
2025-05-26 03:03:31 +06:00
rifsxd
5fa1050e1b src: bring back LKM patching 2025-05-26 03:03:18 +06:00
Rifat Azad
39617497ca manager: change webui TaskDescription title 2025-05-25 10:49:56 +06:00
rifsxd
44ad960da7 src: add x86_64 support 2025-05-24 20:33:38 +06:00
rifsxd
db223a1e92 manager: do not show some infocard item if ksuVersion is null 2025-05-23 22:56:26 +06:00
Der_Googler
ea4b8f51c2 manager: use myUserId as fallback #429 (#432) 2025-05-23 20:34:09 +06:00
rifsxd
407826396b ci: try release artifacts properly 2025-05-23 05:17:08 +06:00
rifsxd
124547c9c5 manager: update root project name to "KernelSU-Next" 2025-05-23 05:02:04 +06:00
igor
db7a9df880 Update translation (#423) 2025-05-23 04:55:37 +06:00
rifsxd
29725214f7 ksud_overlayfs: change find_temp_path to use keep() method for temporary directory since into_path() is deprecated 2025-05-23 04:52:48 +06:00
rifsxd
9189de4db1 manager: refactor backup and restore paths and logic for modules and allowlist 2025-05-23 04:48:36 +06:00
rifsxd
fec0032883 ksud: fix clippy warning/error 2025-05-23 03:18:36 +06:00
роизен
1ee737b1aa Update and rename strings.xml to strings.xml (#422) 2025-05-23 00:43:45 +06:00
dependabot[bot]
2a32e1d746 build(deps): bump the crates group across 1 directory with 18 updates (#417)
Bumps the crates group with 11 updates in the /userspace/ksud_overlayfs directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.37` | `4.5.38` |
| rust-embed | `8.7.1` | `8.7.2` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.19.1` | `3.20.0` |
| [ahash](https://github.com/tkaitchuck/ahash) | `0.8.11` | `0.8.12` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.7` | `3.0.8` |
| [backtrace](https://github.com/rust-lang/backtrace-rs) | `0.3.74` | `0.3.75` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.21` | `1.2.23` |
| [crc](https://github.com/mrhooray/crc-rs) | `3.2.1` | `3.3.0` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.2` | `0.3.3` |
| [libm](https://github.com/rust-lang/compiler-builtins) | `0.2.14` | `0.2.15` |
| [windows-core](https://github.com/microsoft/windows-rs) | `0.61.0` | `0.61.2` |



Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

Updates `rust-embed` from 8.7.1 to 8.7.2

Updates `tempfile` from 3.19.1 to 3.20.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

Updates `ahash` from 0.8.11 to 0.8.12
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits)

Updates `anstyle-wincon` from 3.0.7 to 3.0.8
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.7...anstyle-wincon-v3.0.8)

Updates `backtrace` from 0.3.74 to 0.3.75
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

Updates `cc` from 1.2.21 to 1.2.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.23)

Updates `clap_builder` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.37...v4.5.38)

Updates `crc` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/mrhooray/crc-rs/releases)
- [Commits](https://github.com/mrhooray/crc-rs/commits)

Updates `getrandom` from 0.3.2 to 0.3.3
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3)

Updates `libm` from 0.2.14 to 0.2.15
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15)

Updates `rust-embed-impl` from 8.7.0 to 8.7.2

Updates `rust-embed-utils` from 8.7.0 to 8.7.2

Updates `windows-core` from 0.61.0 to 0.61.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-result` from 0.3.2 to 0.3.4
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-strings` from 0.4.0 to 0.4.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zerocopy` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

Updates `zerocopy-derive` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-version: 8.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ahash
  dependency-version: 0.8.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: backtrace
  dependency-version: 0.3.75
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: crc
  dependency-version: 3.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: getrandom
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-core
  dependency-version: 0.61.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-result
  dependency-version: 0.3.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-strings
  dependency-version: 0.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zerocopy
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: zerocopy-derive
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:58 +06:00
dependabot[bot]
bdaf50ab0f build(deps): bump the crates group across 1 directory with 18 updates (#416)
Bumps the crates group with 11 updates in the /userspace/ksud_magic directory:

| Package | From | To |
| --- | --- | --- |
| [clap](https://github.com/clap-rs/clap) | `4.5.37` | `4.5.38` |
| rust-embed | `8.7.1` | `8.7.2` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.19.1` | `3.20.0` |
| [ahash](https://github.com/tkaitchuck/ahash) | `0.8.11` | `0.8.12` |
| [anstyle-wincon](https://github.com/rust-cli/anstyle) | `3.0.7` | `3.0.8` |
| [backtrace](https://github.com/rust-lang/backtrace-rs) | `0.3.74` | `0.3.75` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.21` | `1.2.23` |
| [crc](https://github.com/mrhooray/crc-rs) | `3.2.1` | `3.3.0` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.2` | `0.3.3` |
| [libm](https://github.com/rust-lang/compiler-builtins) | `0.2.14` | `0.2.15` |
| [windows-core](https://github.com/microsoft/windows-rs) | `0.61.0` | `0.61.2` |



Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

Updates `rust-embed` from 8.7.1 to 8.7.2

Updates `tempfile` from 3.19.1 to 3.20.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

Updates `ahash` from 0.8.11 to 0.8.12
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits)

Updates `anstyle-wincon` from 3.0.7 to 3.0.8
- [Commits](https://github.com/rust-cli/anstyle/compare/anstyle-wincon-v3.0.7...anstyle-wincon-v3.0.8)

Updates `backtrace` from 0.3.74 to 0.3.75
- [Release notes](https://github.com/rust-lang/backtrace-rs/releases)
- [Commits](https://github.com/rust-lang/backtrace-rs/compare/0.3.74...0.3.75)

Updates `cc` from 1.2.21 to 1.2.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.23)

Updates `clap_builder` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.37...v4.5.38)

Updates `crc` from 3.2.1 to 3.3.0
- [Release notes](https://github.com/mrhooray/crc-rs/releases)
- [Commits](https://github.com/mrhooray/crc-rs/commits)

Updates `getrandom` from 0.3.2 to 0.3.3
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/getrandom/compare/v0.3.2...v0.3.3)

Updates `libm` from 0.2.14 to 0.2.15
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15)

Updates `rust-embed-impl` from 8.7.0 to 8.7.2

Updates `rust-embed-utils` from 8.7.0 to 8.7.2

Updates `windows-core` from 0.61.0 to 0.61.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-result` from 0.3.2 to 0.3.4
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `windows-strings` from 0.4.0 to 0.4.2
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/commits)

Updates `zerocopy` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

Updates `zerocopy-derive` from 0.7.35 to 0.8.25
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.35...v0.8.25)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed
  dependency-version: 8.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: ahash
  dependency-version: 0.8.12
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: anstyle-wincon
  dependency-version: 3.0.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: backtrace
  dependency-version: 0.3.75
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: clap_builder
  dependency-version: 4.5.38
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: crc
  dependency-version: 3.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: getrandom
  dependency-version: 0.3.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-impl
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: rust-embed-utils
  dependency-version: 8.7.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-core
  dependency-version: 0.61.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-result
  dependency-version: 0.3.4
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: windows-strings
  dependency-version: 0.4.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: zerocopy
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
- dependency-name: zerocopy-derive
  dependency-version: 0.8.25
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:36 +06:00
dependabot[bot]
37a129080a build(deps): bump the maven group across 1 directory with 10 updates (#378)
Bumps the maven group with 10 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.navigation:navigation-compose | `2.8.9` | `2.9.0` |
| androidx.compose:compose-bom | `2025.04.01` | `2025.05.00` |
| androidx.lifecycle:lifecycle-runtime-ktx | `2.8.7` | `2.9.0` |
| androidx.lifecycle:lifecycle-runtime-compose | `2.8.7` | `2.9.0` |
| androidx.lifecycle:lifecycle-viewmodel-compose | `2.8.7` | `2.9.0` |
| com.android.application | `8.9.2` | `8.10.0` |
| com.android.library | `8.9.2` | `8.10.0` |
| [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) | `2.1.20` | `2.1.21` |
| [org.jetbrains.kotlin.plugin.compose](https://github.com/JetBrains/kotlin) | `2.1.20` | `2.1.21` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.20-2.0.1` | `2.1.21-2.0.1` |



Updates `androidx.navigation:navigation-compose` from 2.8.9 to 2.9.0

Updates `androidx.compose:compose-bom` from 2025.04.01 to 2025.05.00

Updates `androidx.lifecycle:lifecycle-runtime-ktx` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-runtime-compose` from 2.8.7 to 2.9.0

Updates `androidx.lifecycle:lifecycle-viewmodel-compose` from 2.8.7 to 2.9.0

Updates `com.android.application` from 8.9.2 to 8.10.0

Updates `com.android.library` from 8.9.2 to 8.10.0

Updates `com.android.library` from 8.9.2 to 8.10.0

Updates `org.jetbrains.kotlin.android` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `org.jetbrains.kotlin.plugin.compose` from 2.1.20 to 2.1.21
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.1.20...v2.1.21)

Updates `com.google.devtools.ksp` from 2.1.20-2.0.1 to 2.1.21-2.0.1
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.20-2.0.1...2.1.21-2.0.1)

---
updated-dependencies:
- dependency-name: androidx.navigation:navigation-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.05.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: androidx.lifecycle:lifecycle-viewmodel-compose
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.android
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.1.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.21-2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 00:40:18 +06:00
Rifat Azad
024b6ce292 docs: updated installation link for all README 2025-05-22 20:45:58 +06:00
rifsxd
b13a12e3d5 manager: something interesting? 2025-05-22 11:02:01 +06:00
rifsxd
9d9738eed0 manager: keep screen on when FlashingStatus.FLASHING 2025-05-22 10:21:31 +06:00
rifsxd
135fe1e5d4 manager: made the see more collapse button round for infocard 2025-05-22 10:07:03 +06:00
Rifat Azad
2d033b6b87 manager: disable mount system info if ksuversion is null 2025-05-22 09:48:25 +06:00
cvnertnc
9048ffbdab Manager: update values-tr/strings.xml and Docs: update README-tr.md (#415) 2025-05-22 08:38:47 +06:00
роизен
d43fdd3cb4 Add Ukranian (#414)
* Create README_UA.md

* Update README_UA.md

* Update README.md

* Update README_BG.md

* Update README_CN.md

* Update README_FR.md

* Update README_ID.md

* Update README_IT.md

* Update README_JA.md

* Update README_KO.md

* Update README_PL.md

* Update README_PT-BR.md

* Update README_RU.md

* Update README_TH.md

* Update README_TR.md

* Update README_TW.md

* Update README_VI.md

* Create strings.xml

* МЕГА ПОТУЖНО

* МЕГА ПОТУЖНО

* напотужнічав

---------

Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-05-22 08:37:51 +06:00
Melamit
14d16eff46 docs: Update translations (#383)
* docs: Update Installation instruction link for BG, JA and EN

* docs: Add Ukrainian translation

* docs: Add LKM mode deprecaton info in English and Ukrainian translations

This informs the user about the recent change in KernelSU Next manager in the Readme

---------

Co-authored-by: melamit <sunshine@melamit.in>
2025-05-22 08:06:07 +06:00
luigimak
1a603c2b48 Update Italian Translation (#413)
Update values-it/strings.xml
2025-05-22 08:02:45 +06:00
mr_vokintos
2092161fe0 Update Russian (#409)
* Update README_RU.md

Donations added

* Update strings.xml

fix

* Update strings.xml

again

* Update README_RU.md

* Update Ru strings.xml

Fixes and additions

* Update README_RU.md

I didn't like the way it looked

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml

* Update strings.xml
2025-05-22 08:01:44 +06:00
igor
a8b92f50cc Update portuguese translation (#401) 2025-05-22 08:00:21 +06:00
itsaschoolbus
4556c9a5d1 manager: Update LKM mode deprecation string for Vietnamese (#396) 2025-05-22 07:59:58 +06:00
Nhật Minh
e6fcae4f02 Update strings.xml (#372) 2025-05-22 07:59:34 +06:00
Rifat Azad
74ab5488e1 manager: rename unmount -> umount for superuser label item 2025-05-22 07:39:18 +06:00
rifsxd
5cdec242eb manager: keep screen on when isActionRunning (#341) 2025-05-22 00:27:31 +06:00
rifsxd
e938a499f6 manager: disabled auto update by default 2025-05-22 00:09:40 +06:00
rifsxd
84b5915eea manager: use WebUIX as default webui providor 2025-05-22 00:08:07 +06:00
rifsxd
540ce1d2c3 manager: redesign/rearrange home infocard 2025-05-21 23:42:05 +06:00
rifsxd
b40f2af0f0 manager: fix bad prctl calls for native code 2025-05-21 22:55:38 +06:00
rifsxd
324d09a61e manager: added MINIMAL_SUPPORTED_HOOK_MODE and hook_mode info 2025-05-21 18:07:47 +06:00
rifsxd
d5dfecefea Revert "kernel: Makefile: sanity checks"
This reverts commit 26d3ec14a6.
2025-05-21 18:07:46 +06:00
rifsxd
ce37e17c87 kernel: added CMD_HOOK_MODE prctl to get the enabled su hook mode value 2025-05-21 18:07:41 +06:00
rifsxd
3b1d5f15f4 manager: webuix no longer should be stated beta as it is stable enough for release 2025-05-21 15:18:01 +06:00
rifsxd
714ec4695b manager: show home_failure instead of lkm_mode_deprecated 2025-05-21 15:16:37 +06:00
rifsxd
3795d92d7a manager: fix kprobes strings 2025-05-21 15:15:27 +06:00
rifsxd
eed685507a kernel: rename KSU_WITH_KPROBES to KSU_KPROBES_HOOK for better self explanitory 2025-05-21 15:13:17 +06:00
backslashxx
26d3ec14a6 kernel: Makefile: sanity checks 2025-05-21 15:09:33 +06:00
ShirkNeko
96d475407a Add a formatting string for the update list #2556 (#2597)
Fix module update failures caused by spaces and other non Linux readable
characters


Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
2025-05-21 15:03:06 +06:00
backslashxx
27d8bc458f kernel: sucompat: increase reliability of execve_sucompat
On plain ARMv8.0 devices (A53,A57,A73), strncpy_from_user_nofault() sometimes
fails to copy `filename_user` string correctly. This breaks su ofc, breaking
some apps like Termux (Play Store ver), ZArchiver and Root Explorer.

This does NOT seem to affect newer ARMv8.2+ CPUs (A75/A76 and newer)

My speculation? ARMv8.0 has weak speculation :)

here we replace `strncpy_from_user_nofault()` with another routine:
 - access_ok() to validate the pointer
 - strncpy_from_user() to copy and validate string
 - manual null-termination just in case, as strncpy_from_user_nofault also does it
 - remove that memset, seems useless as it is an strncpy, not strncat

Kind of mimicking _nofault, but yes with this one we allow pagefaults.

Tested on:
- ARMv8.0 A73.a53, A57.a53, A53.a53
- ARMv8.2 A76.a55

Tested-by: iDead XD <rafifirdaus12bb@gmail.com>
Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-21 15:01:01 +06:00
Der_Googler
519f86c47e manager: refactor label item in superuser list (#403) 2025-05-19 22:50:11 +06:00
backslashxx
980f71c1bd kernel: core_hook: fixup 217d230b (#402)
Reported-by: Trijal Saha <97483939+Trijal08@users.noreply.github.com>
2025-05-19 22:49:44 +06:00
Rifat Azad
7692665428 manager: warn about LKM mode deprecation for GKI2 kernels 2025-05-19 00:07:05 +06:00
Trijal Saha
aaca0b5283 ci: Only have one task for susfsd irrespective of the target architecture (#395) 2025-05-18 22:49:39 +06:00
Der_Googler
e5a495489d Improve StatusCard and fix WX wrappers of WebUI X (#393)
* manager: bump mmrl to 1998c70b77

* manager: improve StatusCard
2025-05-18 22:11:38 +06:00
Der_Googler
e07a6fb3ff manager: Bump MMRL and possible fix #384 (#391)
* manager: bump mmrl to 346470abb8

- Possible fix a bug where IUserManager.getUsers(ZZZ) are not defined in the framework.jar
- Refactored WebUI X to meet the new WXInterface
- Only fetch the app from the current user and not all users

* manager: remove unused AIDL interfaces
2025-05-18 16:50:51 +06:00
Rifat Azad
b8c2660996 manager: add ABI info icon 2025-05-18 12:30:20 +06:00
rifsxd
ec2ecdcacb manager: fix unresolved referance 2025-05-18 12:22:34 +06:00
rifsxd
3c3ab77f65 manager: Add ABI archirecture info for manager 2025-05-18 12:09:08 +06:00
rifsxd
ffb2c89c36 manager: add kernel ABI info 2025-05-18 12:03:49 +06:00
rifsxd
bda62cc8a1 manager: refine working mode designation 2025-05-18 11:54:41 +06:00
Wang Han
a052af4180 Fix fallback option for createRootShell() (#2593) 2025-05-18 11:30:47 +06:00
rifsxd
8835c37536 ksud_magic: Update zip-extensions and set needed features for zip
zip-extensions does not export time and deflate64 features now.
2025-05-18 11:29:58 +06:00
Wang Han
69f3c9f6ab Update zip-extensions and set needed features for zip (#2592)
zip-extensions does not export time and deflate64 features now.
2025-05-18 11:25:38 +06:00
Rifat Azad
af3e0bd6a5 ci: fux ksud armv7a artifact download 2025-05-18 10:40:31 +06:00
Rifat Azad
5b14512323 ci: fux susfsd artifact download 2025-05-18 10:32:41 +06:00
Rifat Azad
6f176ad1c4 ksud_magic: removed loopdev 2025-05-18 10:24:39 +06:00
Rifat Azad
bc9d720a3c ksud_overlayfs: use upstream loopdev 2025-05-18 10:18:35 +06:00
Rifat Azad
93c5013251 ksud_overlayfs: use upstream hole-punch 2025-05-18 10:01:05 +06:00
Rifat Azad
bc5c993093 manager: added armv7a abi 2025-05-18 09:14:14 +06:00
Rifat Azad
759b3c5baf ci: fix workflow 2025-05-18 04:10:23 +06:00
Rifat Azad
e1303d13a3 ci: fix duplicate susfsd artifact upload error 2025-05-18 04:05:50 +06:00
Rifat Azad
8824115697 ci: upload armv7a susfsd artifact 2025-05-18 03:57:09 +06:00
Rifat Azad
a78a1e7d2e ci: fixed syntax error 2025-05-18 03:49:41 +06:00
backslashxx
9e150b2c44 ksud/installer: /odm handling
we move the folder out of system if it exists in real filesystem and it
is not a symlink.
this is already supported on init_event.rs so only handle_partition
logic was needed to make it happen

since KernelSU is using overlayfs, we need to move these out.

Signed-off-by: backslashxx
<118538522+backslashxx@users.noreply.github.com>

---------

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:42:32 +06:00
backslashxx
217d230b61 kernel: expose KSU_LSM_SECURITY_HOOKS on Kconfig
disabling this removes the need for LSM_HOOK_INIT, security_add_hooks and such,.
furthermore, this will also allow easier integration on pre-4.1 kernels.
Expose this and make it a configurable option.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
ba1b3c4fc7 kernel/throne_tracker: we just uninstalled the manager, stop looking for it
When the manager UID disappears from packages.list, we correctly
invalidate it — good. But, in the very next breath, we start scanning
/data/app hoping to find it again?

This event is just unnecessary I/O, exactly when we should be doing less.
Apparently this causes hangups and stuckups which is REALLY noticeable
on Ultra-Legacy devices.

Skip the scan — we’ll catch the reinstall next time packages.list updates.

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
5f871cd713 kernel/selinux: fix pointer mismatch with 32-bit ksud on 64-bit kernels
Since KernelSU Manager can now be built for 32-bit, theres this problematic
setup where userspace is 32-bit (armeabi-v7a) and kernel is 64bit (aarch64).

On 64-bit kernels with CONFIG_COMPAT=y, 32-bit userspace passes 32-bit pointers.
These values are interpreted as 64-bit pointers without proper casting and that
results in invalid or near-null memory access.

This patch adds proper compat-mode handling with the ff changes:
- introduce a dedicated struct (`sepol_compat_data`) using u32 fields
- use `compat_ptr()` to safely convert 32-bit user pointers to kernel pointers
- adding a runtime `ksu_is_compat` flag to dynamically select between struct layouts

This prevents a near-null pointer dereference when handling SELinux
policy updates from 32-bit ksud in a 64-bit kernel.

Truth table:

kernel 32 + ksud 32, struct is u32, no compat_ptr
kernel 64 + ksud 32, struct is u32, yes compat_ptr
kernel 64 + ksud 64, struct is u64, no compat_ptr

Preprocessor check

64BIT=y COMPAT=y: define both structs, select dynamically
64BIT=y COMPAT=n: struct u64
64BIT=n: struct u32

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>
2025-05-18 03:23:12 +06:00
backslashxx
4a37422af5 kernel/sucompat: sync to KSU pr #2506
kernel: sucompat: sucompat toggle support for non-kp

This is done like how vfs_read_hook, input_hook and execve_hook is disabled.
While this is not exactly the same thing, this CAN achieve the same results.
The complete disabling of all KernelSU hooks.

While this is likely unneeded, It keeps feature parity to non-kprobe builds.

adapted from upstream:
	kernel: Allow to re-enable sucompat - 4593ae81c7

Rejected: https://github.com/tiann/KernelSU/pull/2506

Signed-off-by: backslashxx <118538522+backslashxx@users.noreply.github.com>

kernel: sucompat: fix compile issue on kprobe builds, unused variable
2025-05-18 03:23:12 +06:00
Rifat Azad
a081fc87c9 manager/userspace: added 32bit (armv7a) support 2025-05-18 03:19:50 +06:00
Rifat Azad
0e8286e195 manager: refactor working mode designation 2025-05-18 01:56:47 +06:00
Rifat Azad
e9d53c4084 manager: removed overlayfs check for modules screen
since magic_mount is the default mount system which most UL (ultra legacy) devices will depend on
2025-05-17 10:41:22 +06:00
Rifat Azad
697a0ac9fc issue_template: we don't accept features requests anymore 2025-05-13 10:14:34 +06:00
dependabot[bot]
7f12e1c19a build(deps): bump the crates group across 1 directory with 4 updates (#365)
Bumps the crates group with 4 updates in the /userspace/ksud_magic directory: rust-embed, [cc](https://github.com/rust-lang/cc-rs), [libm](https://github.com/rust-lang/compiler-builtins) and [tokio](https://github.com/tokio-rs/tokio).


Updates `rust-embed` from 8.7.0 to 8.7.1

Updates `cc` from 1.2.20 to 1.2.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

Updates `libm` from 0.2.13 to 0.2.14
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.13...libm-v0.2.14)

Updates `tokio` from 1.44.2 to 1.45.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.2...tokio-1.45.0)

---
updated-dependencies:
- dependency-name: rust-embed
  dependency-version: 8.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:36:03 +06:00
dependabot[bot]
bf99cb50fd build(deps): bump the crates group across 1 directory with 4 updates (#364)
Bumps the crates group with 4 updates in the /userspace/ksud_overlayfs directory: rust-embed, [cc](https://github.com/rust-lang/cc-rs), [libm](https://github.com/rust-lang/compiler-builtins) and [tokio](https://github.com/tokio-rs/tokio).


Updates `rust-embed` from 8.7.0 to 8.7.1

Updates `cc` from 1.2.20 to 1.2.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

Updates `libm` from 0.2.13 to 0.2.14
- [Release notes](https://github.com/rust-lang/compiler-builtins/releases)
- [Changelog](https://github.com/rust-lang/compiler-builtins/blob/master/.release-plz.toml)
- [Commits](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.13...libm-v0.2.14)

Updates `tokio` from 1.44.2 to 1.45.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.44.2...tokio-1.45.0)

---
updated-dependencies:
- dependency-name: rust-embed
  dependency-version: 8.7.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: libm
  dependency-version: 0.2.14
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: tokio
  dependency-version: 1.45.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:35:26 +06:00
dependabot[bot]
1333f0113f build(deps): bump the maven group in /manager with 2 updates (#349)
Bumps the maven group in /manager with 2 updates: [io.github.raamcosta.compose-destinations:core](https://github.com/raamcosta/compose-destinations) and [io.github.raamcosta.compose-destinations:ksp](https://github.com/raamcosta/compose-destinations).


Updates `io.github.raamcosta.compose-destinations:core` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

Updates `io.github.raamcosta.compose-destinations:ksp` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/raamcosta/compose-destinations/releases)
- [Commits](https://github.com/raamcosta/compose-destinations/compare/2.1.0...2.1.1)

---
updated-dependencies:
- dependency-name: io.github.raamcosta.compose-destinations:core
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: io.github.raamcosta.compose-destinations:ksp
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 02:35:03 +06:00
igor
1b544bd22d Update Portuguese translation (#361) 2025-05-07 02:33:03 +06:00
mr_vokintos
24f514c949 Fixes for Russian translation (#358)
* Update README_RU.md

Donations added

* Update strings.xml

fix

* Update strings.xml

again

* Update README_RU.md

* Update Ru strings.xml

Fixes and additions

* Update README_RU.md

I didn't like the way it looked
2025-05-07 02:32:31 +06:00
Bachpooh
8eed26e0a1 manager: Update values-vi/strings.xml (#357)
* Corrects mistranslation
* Fix issues #335
2025-05-07 02:32:17 +06:00
luigimak
3c5b3f0a49 Update Italian translation (#355) 2025-05-07 02:32:03 +06:00
Caner Karaca
1d23b4bb67 ksud: fix rustfmt errors (#359) 2025-05-06 22:48:58 +06:00
Rifat Azad
48e533f660 ksud_overlayfs: removed custom_sparse_size text file extension 2025-05-04 19:39:06 +06:00
Der_Googler
86fbed60eb Add Eruda Support for WebUI X (#354)
* manager: Improvements

- Bump MMRL version
- Improved SwitchItem when it is not enabled
- Added option to enable eruda

* manager: Use custom user agent for WebUI X
2025-05-04 01:08:34 +06:00
dependabot[bot]
164341b543 build(deps): bump the crates group across 1 directory with 2 updates (#344)
Bumps the crates group with 2 updates in the /userspace/ksud_magic directory: [chrono](https://github.com/chronotope/chrono) and [sha2](https://github.com/RustCrypto/hashes).


Updates `chrono` from 0.4.40 to 0.4.41
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.40...v0.4.41)

Updates `sha2` from 0.10.8 to 0.10.9
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.8...sha2-v0.10.9)

---
updated-dependencies:
- dependency-name: chrono
  dependency-version: 0.4.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: sha2
  dependency-version: 0.10.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:52 +06:00
dependabot[bot]
94942fe488 build(deps): bump the crates group across 1 directory with 2 updates (#343)
Bumps the crates group with 2 updates in the /userspace/ksud_overlayfs directory: [chrono](https://github.com/chronotope/chrono) and [sha2](https://github.com/RustCrypto/hashes).


Updates `chrono` from 0.4.40 to 0.4.41
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.40...v0.4.41)

Updates `sha2` from 0.10.8 to 0.10.9
- [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.8...sha2-v0.10.9)

---
updated-dependencies:
- dependency-name: chrono
  dependency-version: 0.4.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: crates
- dependency-name: sha2
  dependency-version: 0.10.9
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: crates
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:28 +06:00
dependabot[bot]
ca64f6c8ac build(deps): bump the maven group across 1 directory with 5 updates (#322)
Bumps the maven group with 5 updates in the /manager directory:

| Package | From | To |
| --- | --- | --- |
| androidx.compose:compose-bom | `2025.03.01` | `2025.04.00` |
| [org.jetbrains.kotlinx:kotlinx-coroutines-core](https://github.com/Kotlin/kotlinx.coroutines) | `1.10.1` | `1.10.2` |
| com.android.application | `8.9.1` | `8.9.2` |
| com.android.library | `8.9.1` | `8.9.2` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.1.20-1.0.32` | `2.1.20-2.0.0` |



Updates `androidx.compose:compose-bom` from 2025.03.01 to 2025.04.00

Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core` from 1.10.1 to 1.10.2
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.10.1...1.10.2)

Updates `com.android.application` from 8.9.1 to 8.9.2

Updates `com.android.library` from 8.9.1 to 8.9.2

Updates `com.android.library` from 8.9.1 to 8.9.2

Updates `com.google.devtools.ksp` from 2.1.20-1.0.32 to 2.1.20-2.0.0
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.1.20-1.0.32...2.1.20-2.0.0)

---
updated-dependencies:
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2025.04.00
  dependency-type: direct:production
  dependency-group: maven
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core
  dependency-version: 1.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.library
  dependency-version: 8.9.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.1.20-2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:06:11 +06:00
luigimak
e8ef483098 Update italian translation (#342)
* Update values-it/strings.xml

Update Italian Translation

* Update italian translation
2025-05-02 00:05:16 +06:00
cvnertnc
85faf43fdd manager: Update values-tr/strings.xml (#334) 2025-05-02 00:04:14 +06:00
igor
09620c269e Update portuguese & english (#333) 2025-05-02 00:03:29 +06:00
itsaschoolbus
0c05a4c375 manager: Update WebUI X translation string for Vietnamese (#332) 2025-05-02 00:03:10 +06:00
Der_Googler
298aa7960e Improve Platform (#345)
* Add option to use WebUI X

- Added WebUI X from MMRL to KernelSU Next

* Some improvements

* Again some improvements

* Fix NPE

* Still not fixed

Use mappings from the action to decode the stacktrace

* bump mmrl

does still not work

* Works

* WORKS

* small fixes

* manager: only launch webui x when Platform.isAlive is `true`

* manager: disable "Use WebUI X" option when Platform.isAlive is `false`

* manager: improve app list loading

* manager: use system packageManager api

* ci: add spoofed manager workflow

* ci: add spoofed manager workflow

---------

Co-authored-by: rifsxd <rifat.44.azad.rifs@gmail.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
2025-05-01 20:24:00 +06:00
rifsxd
b112513df0 ci: add spoofed manager workflow 2025-05-01 19:52:36 +06:00
rifsxd
f19b5a453a ksud: changed deps repo to fetch from KernelSU-Next org 2025-05-01 17:29:08 +06:00
rifsxd
72e54653a2 ksud: disabled BootRestore command 2025-05-01 16:54:09 +06:00
rifsxd
5696d72a3f ksud: fix rustfmt errors 2025-05-01 16:47:20 +06:00
rifsxd
757d20166a manager: clean lkm remnants
ksud: clean clippy warnings
2025-05-01 16:30:09 +06:00
rifsxd
1336996129 manager: disabled KMI/LKM installation
manager: check if overlayfs is available to allow mount system switching
ksud: disabled KMI/LKM commands
ci: disabled LKM build workflow
ksud: removed ksuinit
2025-05-01 15:58:18 +06:00
Rifat Azad
4f35240203 ci/gki-kernel: run the sed command for BAZEL only if BUILD.bazel exists to avoid file not found error on non BAZEL kernel common tree 2025-05-01 11:48:41 +06:00
Rifat Azad
5565a6b3f8 ci: fix BAZEL build while remove protected module exports 2025-05-01 01:02:25 +06:00
Der_Googler
9dbe135e66 Fix Shortcuts in WebUI X (#339)
* manager: fix webui x shortcuts
2025-04-30 11:08:25 +06:00
rifsxd
fe5c031701 ci/gki-kernel: keep abi_gki_protected_exports to avoid BAZEL build errors 2025-04-29 01:30:48 +06:00
rifsxd
0511a90640 manager: fully optimize the broken/buggy bottom navbar 2025-04-28 23:25:52 +06:00
Re*Index. (ot_inc)
2c87dfbb35 Add Japanese README. (#320)
* Add Japanese README

* Update README.md

* Update README_JA.md
2025-04-28 01:56:00 +06:00
Caner Karaca
9b4d07008d ci: update workflows (#329) 2025-04-28 01:55:16 +06:00
Caner Karaca
c40218a919 manager: update gradle and NDK (#327)
* manager: update gradle

* manager: update NDK
2025-04-28 01:54:58 +06:00
Caner Karaca
0c410b87ec ksud: cargo lock file maintenance (#328) 2025-04-28 01:54:46 +06:00
rifsxd
114a07a440 manager: fixed buggy bottombar with a neat workaround 2025-04-28 00:14:29 +06:00
Der_Googler
babae3b2ad Add WebUI X (#316)
* Add option to use WebUI X

- Added WebUI X from MMRL to KernelSU Next

* Some improvements

* Again some improvements

* Fix NPE

* Still not fixed

Use mappings from the action to decode the stacktrace

* bump mmrl

does still not work

* Works

* WORKS

* small fixes
2025-04-27 22:01:25 +06:00
muhammadbahaa2001
a7a9f86a71 Updated Arabic (#312) 2025-04-25 20:15:46 +06:00
Aliza
c65fcd5133 Adding Persian Language (#305)
* Adding Persian Language

* Create app.yml

* Delete .github/workflows/app.yml
2025-04-17 21:40:59 +06:00
Oscar1640
b298b4203a Fix su --shell argument handling for ksud magic mount (#309)
Co-authored-by: Wang Han <416810799@qq.com>
2025-04-17 21:36:04 +06:00
onlymash
250310fc9f improve manager translations for zh-rCN (#300) 2025-04-13 22:35:11 +06:00
GMárton
89cf05d3a4 Added Hungarian translation (#284) 2025-04-09 01:10:13 +06:00
138 changed files with 5178 additions and 1643 deletions

View File

@@ -1,5 +1,5 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Feature Request - name: Feature Request
url: https://t.me/ksunext_group url: https://t.me/ksunext/578
about: "We accept external Feature Requests, see this link for more details." about: "We do not accept external Feature Requests anymore, check the link for more details."

View File

@@ -37,7 +37,7 @@ on:
jobs: jobs:
build: build:
name: Build ${{ inputs.version_name }} name: Build ${{ inputs.version_name }}
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- name: Maximize build space - name: Maximize build space
uses: easimon/maximize-build-space@master uses: easimon/maximize-build-space@master

View File

@@ -7,9 +7,9 @@ jobs:
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android12-5.10 version: android12-5.10
version_name: android12-5.10.226 version_name: android12-5.10.236
tag: android12-5.10-2024-11 tag: android12-5.10-2025-05
os_patch_level: 2024-11 os_patch_level: 2025-05
patch_path: "5.10" patch_path: "5.10"
debug: true debug: true
build-debug-kernel-a13: build-debug-kernel-a13:
@@ -17,11 +17,11 @@ jobs:
matrix: matrix:
include: include:
- version: "5.10" - version: "5.10"
sub_level: 228 sub_level: 236
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android13-${{ matrix.version }} version: android13-${{ matrix.version }}
@@ -34,11 +34,11 @@ jobs:
matrix: matrix:
include: include:
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "6.1" - version: "6.1"
sub_level: 118 sub_level: 138
os_patch_level: 2025-01 os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android14-${{ matrix.version }} version: android14-${{ matrix.version }}
@@ -51,8 +51,8 @@ jobs:
matrix: matrix:
include: include:
- version: "6.6" - version: "6.6"
sub_level: 58 sub_level: 89
os_patch_level: 2025-01 os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android15-${{ matrix.version }} version: android15-${{ matrix.version }}

View File

@@ -21,14 +21,14 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- sub_level: 209
os_patch_level: 2024-05
- sub_level: 218 - sub_level: 218
os_patch_level: 2024-08 os_patch_level: 2024-08
- sub_level: 226 - sub_level: 226
os_patch_level: 2024-11 os_patch_level: 2024-11
- sub_level: 233 - sub_level: 233
os_patch_level: 2025-02 os_patch_level: 2025-02
- sub_level: 236
os_patch_level: 2025-05
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
secrets: inherit secrets: inherit
with: with:
@@ -114,7 +114,7 @@ jobs:
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android12-5.10 version: android12-5.10
version_name: android12-5.10.223 version_name: android12-5.10.236
tag: android12-5.10-2024-11 tag: android12-5.10-2025-05
os_patch_level: 2024-11 os_patch_level: 2025-05
patch_path: "5.10" patch_path: "5.10"

View File

@@ -21,9 +21,6 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- version: "5.10"
sub_level: 209
os_patch_level: 2024-05
- version: "5.10" - version: "5.10"
sub_level: 210 sub_level: 210
os_patch_level: 2024-06 os_patch_level: 2024-06
@@ -39,9 +36,12 @@ jobs:
- version: "5.10" - version: "5.10"
sub_level: 228 sub_level: 228
os_patch_level: 2025-01 os_patch_level: 2025-01
- version: "5.15" - version: "5.10"
sub_level: 148 sub_level: 234
os_patch_level: 2024-05 os_patch_level: 2025-03
- version: "5.10"
sub_level: 236
os_patch_level: 2025-05
- version: "5.15" - version: "5.15"
sub_level: 149 sub_level: 149
os_patch_level: 2024-07 os_patch_level: 2024-07
@@ -57,6 +57,12 @@ jobs:
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 170
os_patch_level: 2025-01 os_patch_level: 2025-01
- version: "5.15"
sub_level: 178
os_patch_level: 2025-03
- version: "5.15"
sub_level: 180
os_patch_level: 2025-05
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
secrets: inherit secrets: inherit
with: with:
@@ -143,11 +149,11 @@ jobs:
matrix: matrix:
include: include:
- version: "5.10" - version: "5.10"
sub_level: 228 sub_level: 236
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android13-${{ matrix.version }} version: android13-${{ matrix.version }}

View File

@@ -21,9 +21,6 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- version: "5.15"
sub_level: 148
os_patch_level: 2024-05
- version: "5.15" - version: "5.15"
sub_level: 149 sub_level: 149
os_patch_level: 2024-06 os_patch_level: 2024-06
@@ -42,9 +39,12 @@ jobs:
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 170
os_patch_level: 2025-01 os_patch_level: 2025-01
- version: "6.1" - version: "5.15"
sub_level: 75 sub_level: 178
os_patch_level: 2024-05 os_patch_level: 2025-03
- version: "5.15"
sub_level: 180
os_patch_level: 2025-05
- version: "6.1" - version: "6.1"
sub_level: 78 sub_level: 78
os_patch_level: 2024-06 os_patch_level: 2024-06
@@ -72,6 +72,18 @@ jobs:
- version: "6.1" - version: "6.1"
sub_level: 124 sub_level: 124
os_patch_level: 2025-02 os_patch_level: 2025-02
- version: "6.1"
sub_level: 128
os_patch_level: 2025-03
- version: "6.1"
sub_level: 129
os_patch_level: 2025-04
- version: "6.1"
sub_level: 134
os_patch_level: 2025-05
- version: "6.1"
sub_level: 138
os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
secrets: inherit secrets: inherit
with: with:
@@ -158,11 +170,11 @@ jobs:
matrix: matrix:
include: include:
- version: "5.15" - version: "5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "6.1" - version: "6.1"
sub_level: 118 sub_level: 138
os_patch_level: 2025-01 os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android14-${{ matrix.version }} version: android14-${{ matrix.version }}

View File

@@ -42,6 +42,18 @@ jobs:
- version: "6.6" - version: "6.6"
sub_level: 66 sub_level: 66
os_patch_level: 2025-02 os_patch_level: 2025-02
- version: "6.6"
sub_level: 77
os_patch_level: 2025-03
- version: "6.6"
sub_level: 82
os_patch_level: 2025-04
- version: "6.6"
sub_level: 87
os_patch_level: 2025-05
- version: "6.6"
sub_level: 89
os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
secrets: inherit secrets: inherit
with: with:
@@ -128,8 +140,8 @@ jobs:
matrix: matrix:
include: include:
- version: "6.6" - version: "6.6"
sub_level: 58 sub_level: 89
os_patch_level: 2025-01 os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: android15-${{ matrix.version }} version: android15-${{ matrix.version }}

137
.github/workflows/build-kernel-arcvm.yml vendored Normal file
View File

@@ -0,0 +1,137 @@
name: Build Kernel - ChromeOS ARCVM
on:
push:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-arcvm.yml"
- "kernel/**"
pull_request:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-arcvm.yml"
- "kernel/**"
workflow_call:
workflow_dispatch:
env:
git_tag: chromeos-5.10-arcvm
jobs:
build:
if: github.event_name != 'pull_request' || (github.event_name == 'pull_request' && !github.event.pull_request.draft)
strategy:
matrix:
include:
- arch: x86_64
kernel_image_name: bzImage
build_config: build.config.gki.x86_64
defconfig: x86_64_arcvm_defconfig
- arch: arm64
kernel_image_name: Image
build_config: build.config.gki.aarch64
defconfig: arm64_arcvm_defconfig
name: Build ChromeOS ARCVM kernel
runs-on: ubuntu-22.04
env:
LTO: thin
ROOT_DIR: /
KERNEL_DIR: ${{ github.workspace }}/kernel
steps:
- name: Install Build Tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends bc \
bison build-essential ca-certificates flex git gnupg \
libelf-dev libssl-dev lsb-release software-properties-common wget \
libncurses-dev binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu nuget gzip \
rsync python3 device-tree-compiler
sudo ln -s --force python3 /usr/bin/python
export LLVM_VERSION=14
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh $LLVM_VERSION
rm ./llvm.sh
sudo ln -s --force /usr/bin/clang-$LLVM_VERSION /usr/bin/clang
sudo ln -s --force /usr/bin/ld.lld-$LLVM_VERSION /usr/bin/ld.lld
sudo ln -s --force /usr/bin/llvm-objdump-$LLVM_VERSION /usr/bin/llvm-objdump
sudo ln -s --force /usr/bin/llvm-ar-$LLVM_VERSION /usr/bin/llvm-ar
sudo ln -s --force /usr/bin/llvm-nm-$LLVM_VERSION /usr/bin/llvm-nm
sudo ln -s --force /usr/bin/llvm-strip-$LLVM_VERSION /usr/bin/llvm-strip
sudo ln -s --force /usr/bin/llvm-objcopy-$LLVM_VERSION /usr/bin/llvm-objcopy
sudo ln -s --force /usr/bin/llvm-readelf-$LLVM_VERSION /usr/bin/llvm-readelf
sudo ln -s --force /usr/bin/clang++-$LLVM_VERSION /usr/bin/clang++
- name: Checkout KernelSU-Next
uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: Setup kernel source
run: git clone https://chromium.googlesource.com/chromiumos/third_party/kernel.git -b ${{ env.git_tag }} --depth=1
- name: Extract version from Makefile
working-directory: kernel
run: |
VERSION=$(grep -E '^VERSION = ' Makefile | awk '{print $3}')
PATCHLEVEL=$(grep -E '^PATCHLEVEL = ' Makefile | awk '{print $3}')
SUBLEVEL=$(grep -E '^SUBLEVEL = ' Makefile | awk '{print $3}')
echo "ChromeOS ARCVM Linux kernel version: $VERSION.$PATCHLEVEL.$SUBLEVEL"
echo "version=$VERSION.$PATCHLEVEL.$SUBLEVEL" >> $GITHUB_ENV
- name: Setup KernelSU-Next
working-directory: kernel
run: |
echo "[+] KernelSU-Next setup"
KERNEL_ROOT=$GITHUB_WORKSPACE/kernel
echo "[+] KERNEL_ROOT: $KERNEL_ROOT"
echo "[+] Copy KernelSU-Next driver to $KERNEL_ROOT/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $KERNEL_ROOT/drivers/kernelsu-next
echo "[+] Add KernelSU-Next driver to Makefile"
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
DRIVER_KCONFIG=$KERNEL_ROOT/drivers/Kconfig
grep -q "kernelsu-next" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu-next/\n" >> "$DRIVER_MAKEFILE"
grep -q "kernelsu-next" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu-next/Kconfig\"" "$DRIVER_KCONFIG"
echo "[+] Apply KernelSU patches"
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/5.10/*.patch || echo "[-] No patch found"
echo "[+] Patch script/setlocalversion"
sed -i 's/-dirty//g' $KERNEL_ROOT/scripts/setlocalversion
echo "[+] KernelSU-Next setup done."
cd $GITHUB_WORKSPACE/KernelSU-Next
KSU_VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "KernelSU-Next version: $KSU_VERSION"
echo "kernelsu-next_version=$KSU_VERSION" >> $GITHUB_ENV
- name: Build Kernel
working-directory: kernel
env:
KERNEL_IMAGE_NAME: ${{ matrix.kernel_image_name }}
ARCH: ${{ matrix.arch }}
run: |
set -a && . ${{ matrix.build_config }}; set +a
export DEFCONFIG=${{ matrix.defconfig }}
if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
fi
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} mrproper
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} ${DEFCONFIG} < /dev/null
scripts/config --file .config -e LTO_CLANG -d LTO_NONE -e LTO_CLANG_THIN -d LTO_CLANG_FULL -e THINLTO
make LLVM=1 LLVM_IAS=1 DEPMOD=depmod DTC=dtc O=${PWD} -j$(nproc) ${KERNEL_IMAGE_NAME} modules prepare-objtool
ls -l -h ${PWD}/arch/${ARCH}/boot
echo "file_path=${PWD}/arch/${ARCH}/boot/${KERNEL_IMAGE_NAME}" >> $GITHUB_ENV
- name: Upload kernel-ARCVM-${{ matrix.arch }}-${{ env.version }}
uses: actions/upload-artifact@v4
with:
name: kernel-ARCVM-${{ matrix.arch }}-${{ env.version }}
path: "${{ env.file_path }}"

39
.github/workflows/build-kernel-avd.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Build Kernel - AVD
on:
push:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-avd.yml"
- ".github/workflows/avd-kernel.yml"
- "kernel/**"
pull_request:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-avd.yml"
- ".github/workflows/avd-kernel.yml"
- "kernel/**"
workflow_call:
workflow_dispatch:
jobs:
build-kernel:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
uses: ./.github/workflows/avd-kernel.yml
secrets: inherit
strategy:
matrix:
include:
- version: "android-14-avd_x86_64"
manifest: "android-14-avd_x86_64.xml"
arch: "x86_64"
- version: "android-15-avd_aarch64"
manifest: "android-15-avd_aarch64.xml"
arch: "aarch64"
- version: "android-15-avd_x86_64"
manifest: "android-15-avd_x86_64.xml"
arch: "x86_64"
with:
version_name: ${{ matrix.version }}
manifest_name: ${{ matrix.manifest }}
arch: ${{ matrix.arch }}
debug: true

38
.github/workflows/build-kernel-wsa.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Build Kernel - WSA
on:
push:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-wsa.yml"
- ".github/workflows/wsa-kernel.yml"
- "kernel/**"
pull_request:
branches: ["next"]
paths:
- ".github/workflows/build-kernel-wsa.yml"
- ".github/workflows/wsa-kernel.yml"
- "kernel/**"
workflow_call:
workflow_dispatch:
jobs:
build:
if: github.event_name != 'pull_request' && github.ref != 'refs/heads/checkci'
strategy:
matrix:
arch: [x86_64, arm64]
version: ["5.15.94.2", "5.15.104.1", "5.15.104.2", "5.15.104.3", "5.15.104.4"]
uses: ./.github/workflows/wsa-kernel.yml
with:
arch: ${{ matrix.arch }}
version: ${{ matrix.version }}
check_build:
if: (github.event_name == 'pull_request' && !github.event.pull_request.draft) || github.ref == 'refs/heads/checkci'
uses: ./.github/workflows/wsa-kernel.yml
strategy:
matrix:
arch: [x86_64, arm64]
with:
arch: ${{ matrix.arch }}
version: "5.15.104.4"

View File

@@ -15,23 +15,23 @@ jobs:
matrix: matrix:
include: include:
- version: "android12-5.10" - version: "android12-5.10"
sub_level: 233 sub_level: 236
os_patch_level: 2025-02 os_patch_level: 2025-05
- version: "android13-5.10" - version: "android13-5.10"
sub_level: 228 sub_level: 236
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "android13-5.15" - version: "android13-5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "android14-5.15" - version: "android14-5.15"
sub_level: 170 sub_level: 180
os_patch_level: 2025-01 os_patch_level: 2025-05
- version: "android14-6.1" - version: "android14-6.1"
sub_level: 124 sub_level: 138
os_patch_level: 2025-02 os_patch_level: 2025-06
- version: "android15-6.6" - version: "android15-6.6"
sub_level: 66 sub_level: 89
os_patch_level: 2025-02 os_patch_level: 2025-06
uses: ./.github/workflows/gki-kernel.yml uses: ./.github/workflows/gki-kernel.yml
with: with:
version: ${{ matrix.version }} version: ${{ matrix.version }}

View File

@@ -1,4 +1,4 @@
name: Build Manager name: Build Manager CI
on: on:
push: push:
@@ -28,11 +28,9 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- target: aarch64-linux-android - os: ubuntu-latest
os: ubuntu-latest
uses: ./.github/workflows/susfsd.yml uses: ./.github/workflows/susfsd.yml
with: with:
target: ${{ matrix.target }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
build-ksud: build-ksud:
@@ -42,6 +40,10 @@ jobs:
include: include:
- target: aarch64-linux-android - target: aarch64-linux-android
os: ubuntu-latest os: ubuntu-latest
- target: armv7-linux-androideabi
os: ubuntu-latest
- target: x86_64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud.yml uses: ./.github/workflows/ksud.yml
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
@@ -90,36 +92,87 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Download arm64 susfsd - name: Download susfsd
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: susfsd-aarch64-linux-android name: susfsd-linux-android
path: . path: .
- name: Copy susfsd to app jniLibs - name: Copy susfsd to app jniLibs
run: | run: |
mkdir -p app/src/main/jniLibs/arm64-v8a mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
mkdir -p app/src/main/jniLibs/armeabi-v7a
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
- name: Download arm64 ksud_overlayfs - name: Download arm64 ksud_overlayfs
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: ksud_overlayfs-aarch64-linux-android name: ksud_overlayfs-aarch64-linux-android
path: ksud_overlayfs path: ksud_overlayfs
- name: Download arm ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-armv7-linux-androideabi
path: ksud_overlayfs
- name: Download x86_64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-x86_64-linux-android
path: ksud_overlayfs
- name: Copy ksud_overlayfs to app jniLibs - name: Copy ksud_overlayfs to app jniLibs
run: | run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/armeabi-v7a
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
- name: Download arm64 ksud_magic - name: Download arm64 ksud_magic
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: ksud_magic-aarch64-linux-android name: ksud_magic-aarch64-linux-android
path: ksud_magic path: ksud_magic
- name: Download arm ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-armv7-linux-androideabi
path: ksud_magic
- name: Download x86_64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-x86_64-linux-android
path: ksud_magic
- name: Copy ksud_magic to app jniLibs - name: Copy ksud_magic to app jniLibs
run: | run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/armeabi-v7a
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
- name: Build with Gradle - name: Build with Gradle
run: | run: |
@@ -171,4 +224,4 @@ jobs:
APK=$(find ./app/build/outputs/apk/release -name "*.apk") APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install telethon pip3 install telethon
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
fi fi

View File

@@ -0,0 +1,222 @@
name: Build Manager Spoofed
on:
push:
branches: [ "next" ]
paths:
- '.github/workflows/build-manager-ci.yml'
- 'manager/**'
- 'kernel/**'
- 'userspace/ksud_overlayfs**'
- 'userspace/ksud_magic/**'
- 'userspace/susfsd/**'
pull_request:
branches: [ "next" ]
paths:
- '.github/workflows/build-manager-ci.yml'
- 'manager/**'
workflow_call:
workflow_dispatch:
schedule:
- cron: "0 12 * * *" # 6 PM UTC+6 | 12 PM UTC
jobs:
build-lkm:
uses: ./.github/workflows/build-lkm.yml
secrets: inherit
build-susfsd:
needs: build-lkm
strategy:
matrix:
include:
- os: ubuntu-latest
uses: ./.github/workflows/susfsd.yml
with:
os: ${{ matrix.os }}
build-ksud:
needs: build-susfsd
strategy:
matrix:
include:
- target: aarch64-linux-android
os: ubuntu-latest
- target: armv7-linux-androideabi
os: ubuntu-latest
- target: x86_64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud.yml
with:
target: ${{ matrix.target }}
os: ${{ matrix.os }}
build-manager:
needs: build-ksud
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./manager
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Spoof Package ID
run: |
chmod +x spoof
./spoof
- name: Setup need_upload
id: need_upload
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
echo "UPLOAD=true" >> $GITHUB_OUTPUT
else
echo "UPLOAD=false" >> $GITHUB_OUTPUT
fi
- name: Write Key
run: |
if [ ! -z "${{ secrets.KEYSTORE }}" ]; then
{
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}'
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}'
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}'
echo KEYSTORE_FILE='key.jks'
} >> gradle.properties
echo ${{ secrets.KEYSTORE }} | base64 -d > key.jks
fi
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Download susfsd
uses: actions/download-artifact@v4
with:
name: susfsd-linux-android
path: .
- name: Copy susfsd to app jniLibs
run: |
mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
mkdir -p app/src/main/jniLibs/armeabi-v7a
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
- name: Download arm64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-aarch64-linux-android
path: ksud_overlayfs
- name: Download arm ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-armv7-linux-androideabi
path: ksud_overlayfs
- name: Download x86_64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-x86_64-linux-android
path: ksud_overlayfs
- name: Copy ksud_overlayfs to app jniLibs
run: |
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
- name: Download arm64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-aarch64-linux-android
path: ksud_magic
- name: Download arm ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-armv7-linux-androideabi
path: ksud_magic
- name: Download x86_64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-x86_64-linux-android
path: ksud_magic
- name: Copy ksud_magic to app jniLibs
run: |
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
- name: Build with Gradle
run: |
{
echo 'org.gradle.parallel=true'
echo 'org.gradle.vfs.watch=true'
echo 'org.gradle.jvmargs=-Xmx2048m'
echo 'android.native.buildOutput=verbose'
} >> gradle.properties
sed -i 's/org.gradle.configuration-cache=true//g' gradle.properties
chmod +x gradlew
./gradlew clean assembleRelease
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: Manager
path: manager/app/build/outputs/apk/release/*.apk
- name: Upload Mappings
uses: actions/upload-artifact@v4
with:
name: Mappings
path: manager/app/build/outputs/mapping/release/
- name: Bot Session Cache
if: steps.need_upload.outputs.UPLOAD == 'true'
id: bot_session_cache
uses: actions/cache@v4
with:
path: scripts/ksunextbot.session
key: ${{ runner.os }}-bot-session
- name: Upload to Telegram
if: steps.need_upload.outputs.UPLOAD == 'true'
env:
API_ID: ${{ secrets.API_ID }}
API_HASH: ${{ secrets.API_HASH }}
CHAT_ID: ${{ secrets.CHAT_ID }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
TITLE: CI Manager (SPOOFED BUILD)
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
export VERSION=$(git rev-list --count HEAD)
APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install telethon
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
fi

View File

@@ -28,11 +28,9 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- target: aarch64-linux-android - os: ubuntu-latest
os: ubuntu-latest
uses: ./.github/workflows/susfsd.yml uses: ./.github/workflows/susfsd.yml
with: with:
target: ${{ matrix.target }}
os: ${{ matrix.os }} os: ${{ matrix.os }}
build-ksud: build-ksud:
@@ -42,6 +40,10 @@ jobs:
include: include:
- target: aarch64-linux-android - target: aarch64-linux-android
os: ubuntu-latest os: ubuntu-latest
- target: armv7-linux-androideabi
os: ubuntu-latest
- target: x86_64-linux-android
os: ubuntu-latest
uses: ./.github/workflows/ksud.yml uses: ./.github/workflows/ksud.yml
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
@@ -90,36 +92,75 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Download arm64 susfsd - name: Download susfsd
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: susfsd-aarch64-linux-android name: susfsd-linux-android
path: . path: .
- name: Copy susfsd to app jniLibs - name: Copy susfsd to app jniLibs
run: | run: |
mkdir -p app/src/main/jniLibs/arm64-v8a mkdir -p app/src/main/jniLibs/arm64-v8a
cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so cp -f ../arm64-v8a/susfsd ../manager/app/src/main/jniLibs/arm64-v8a/libsusfsd.so
mkdir -p app/src/main/jniLibs/armeabi-v7a
cp -f ../armeabi-v7a/susfsd ../manager/app/src/main/jniLibs/armeabi-v7a/libsusfsd.so
mkdir -p app/src/main/jniLibs/x86_64
cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so
- name: Download arm64 ksud_overlayfs - name: Download arm64 ksud_overlayfs
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: ksud_overlayfs-aarch64-linux-android name: ksud_overlayfs-aarch64-linux-android
path: ksud_overlayfs path: ksud_overlayfs
- name: Download arm ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-armv7-linux-androideabi
path: ksud_overlayfs
- name: Download x86_64 ksud_overlayfs
uses: actions/download-artifact@v4
with:
name: ksud_overlayfs-x86_64-linux-android
path: ksud_overlayfs
- name: Copy ksud_overlayfs to app jniLibs - name: Copy ksud_overlayfs to app jniLibs
run: | run: |
cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so cp -f ../ksud_overlayfs/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_overlayfs.so
cp -f ../ksud_overlayfs/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_overlayfs.so
- name: Download arm64 ksud_magic - name: Download arm64 ksud_magic
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: ksud_magic-aarch64-linux-android name: ksud_magic-aarch64-linux-android
path: ksud_magic path: ksud_magic
- name: Download arm ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-armv7-linux-androideabi
path: ksud_magic
- name: Download x86_64 ksud_magic
uses: actions/download-artifact@v4
with:
name: ksud_magic-x86_64-linux-android
path: ksud_magic
- name: Copy ksud_magic to app jniLibs - name: Copy ksud_magic to app jniLibs
run: | run: |
cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so cp -f ../ksud_magic/aarch64-linux-android/release/ksud ../manager/app/src/main/jniLibs/arm64-v8a/libksud_magic.so
cp -f ../ksud_magic/armv7-linux-androideabi/release/ksud ../manager/app/src/main/jniLibs/armeabi-v7a/libksud_magic.so
cp -f ../ksud_magic/x86_64-linux-android/release/ksud ../manager/app/src/main/jniLibs/x86_64/libksud_magic.so
- name: Build with Gradle - name: Build with Gradle
run: | run: |
@@ -171,4 +212,4 @@ jobs:
APK=$(find ./app/build/outputs/apk/release -name "*.apk") APK=$(find ./app/build/outputs/apk/release -name "*.apk")
pip3 install telethon pip3 install telethon
python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK python3 $GITHUB_WORKSPACE/scripts/ksunextbot.py $APK
fi fi

View File

@@ -45,4 +45,10 @@ jobs:
- name: Run Clippy - name: Run Clippy
run: | run: |
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target aarch64-linux-android --release cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target aarch64-linux-android --release
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target aarch64-linux-android --release cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target aarch64-linux-android --release
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target armv7-linux-androideabi --release
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target armv7-linux-androideabi --release
cross clippy --manifest-path userspace/ksud_magic/Cargo.toml --target x86_64-linux-android --release
cross clippy --manifest-path userspace/ksud_overlayfs/Cargo.toml --target x86_64-linux-android --release

View File

@@ -198,6 +198,9 @@ jobs:
- name: Make working directory clean to avoid dirty - name: Make working directory clean to avoid dirty
working-directory: android-kernel working-directory: android-kernel
run: | run: |
if [ -f ./common/BUILD.bazel ]; then
sed -i '/^[[:space:]]*"protected_exports_list"[[:space:]]*:[[:space:]]*"android\/abi_gki_protected_exports_aarch64",$/d' ./common/BUILD.bazel
fi
rm common/android/abi_gki_protected_exports_* || echo "No protected exports!" rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
git config --global user.email "bot@kernelsu.org" git config --global user.email "bot@kernelsu.org"
git config --global user.name "KernelSU-NextBot" git config --global user.name "KernelSU-NextBot"
@@ -255,4 +258,4 @@ jobs:
if: ${{ inputs.build_lkm == true }} if: ${{ inputs.build_lkm == true }}
with: with:
name: ${{ inputs.version }}-lkm name: ${{ inputs.version }}-lkm
path: ./output/*_kernelsu.ko path: ./output/*_kernelsu.ko

View File

@@ -37,12 +37,17 @@ jobs:
- name: Import susfsd Libraries - name: Import susfsd Libraries
run: | run: |
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/ cp susfsd-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/ cp susfsd-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/
cp susfsd-linux-android/armeabi-v7a/susfsd ./userspace/ksud_overlayfs/bin/arm/
cp susfsd-linux-android/armeabi-v7a/susfsd ./userspace/ksud_magic/bin/arm/
cp susfsd-linux-android/x86_64/susfsd ./userspace/ksud_overlayfs/bin/x86_64/
cp susfsd-linux-android/x86_64/susfsd ./userspace/ksud_magic/bin/x86_64/
- name: Setup Rust - name: Setup Rust
run: | run: |
rustup update stable rustup update stable
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin rustup target add aarch64-apple-darwin
- name: Cache ksud_overlayfs - name: Cache ksud_overlayfs
@@ -76,4 +81,4 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ksud_magic-${{ inputs.target }} name: ksud_magic-${{ inputs.target }}
path: userspace/ksud_magic/target/**/release/ksud* path: userspace/ksud_magic/target/**/release/ksud*

View File

@@ -21,6 +21,12 @@ jobs:
build-a15-kernel: build-a15-kernel:
uses: ./.github/workflows/build-kernel-a15.yml uses: ./.github/workflows/build-kernel-a15.yml
secrets: inherit secrets: inherit
build-wsa-kernel:
uses: ./.github/workflows/build-kernel-wsa.yml
secrets: inherit
build-arcvm-kernel:
uses: ./.github/workflows/build-kernel-arcvm.yml
secrets: inherit
release: release:
needs: needs:
- build-manager - build-manager
@@ -28,6 +34,8 @@ jobs:
- build-a13-kernel - build-a13-kernel
- build-a14-kernel - build-a14-kernel
- build-a15-kernel - build-a15-kernel
- build-wsa-kernel
- build-arcvm-kernel
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Download artifacts - name: Download artifacts
@@ -41,6 +49,24 @@ jobs:
fi fi
done done
- name: Zip WSA kernel
run: |
for dir in kernel-WSA-*; do
if [ -d "$dir" ]; then
echo "------ Zip $dir ----------"
(cd $dir && zip -r9 "$dir".zip ./* -x .git .gitignore ./*.zip && mv *.zip ..)
fi
done
- name: Zip ChromeOS ARCVM kernel
run: |
for dir in kernel-ARCVM-*; do
if [ -d "$dir" ]; then
echo "------ Zip $dir ----------"
(cd $dir && zip -r9 "$dir".zip ./* -x .git .gitignore ./*.zip && mv *.zip ..)
fi
done
- name: Display structure of downloaded files - name: Display structure of downloaded files
run: ls -R run: ls -R
@@ -52,6 +78,8 @@ jobs:
android*-lkm/*_kernelsu.ko android*-lkm/*_kernelsu.ko
AnyKernel3-*.zip AnyKernel3-*.zip
boot-images-*/Image-*/*.img.gz boot-images-*/Image-*/*.img.gz
ksud_magic/ksud_magic-* kernel-WSA*.zip
ksud_overlayfs/ksud_overlayfs-* kernel-ARCVM*.zip
susfsd/susfsd-* ksud_magic*.zip
ksud_overlayfs*.zip
susfsd*.zip

View File

@@ -1,4 +1,4 @@
name: Build susfsd name: Build susfsd aarch64
on: on:
push: push:
branches: [ "next" ] branches: [ "next" ]
@@ -8,9 +8,6 @@ on:
workflow_dispatch: workflow_dispatch:
workflow_call: workflow_call:
inputs: inputs:
target:
required: true
type: string
os: os:
required: false required: false
type: string type: string
@@ -26,9 +23,9 @@ jobs:
- name: Build susfsd - name: Build susfsd
working-directory: ./userspace/susfsd working-directory: ./userspace/susfsd
run: $ANDROID_NDK/ndk-build run: $ANDROID_NDK/ndk-build
- name: Upload a Build Artifact - name: Upload Build Artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: susfsd-aarch64-linux-android name: susfsd-linux-android
path: ./userspace/susfsd/libs path: ./userspace/susfsd/libs

106
.github/workflows/wsa-kernel.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: Build Kernel - WSA
on:
workflow_call:
inputs:
arch:
required: true
type: string
description: >
Build arch: x86_64 / arm64
version:
required: true
type: string
description: >
Build version
jobs:
build:
name: Build WSA-Kernel-${{ inputs.version }}-${{ inputs.arch }}
runs-on: ubuntu-22.04
env:
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
CCACHE_NOHASHDIR: "true"
CCACHE_HARDLINK: "true"
steps:
- name: Install Build Tools
uses: awalsh128/cache-apt-pkgs-action@v1
with:
packages: bc bison build-essential flex libelf-dev binutils-aarch64-linux-gnu gcc-aarch64-linux-gnu gzip ccache
version: 1.0
- name: Cache LLVM
id: cache-llvm
uses: actions/cache@v4
with:
path: ./llvm
key: llvm-12.0.1
- name: Setup LLVM
uses: KyleMayes/install-llvm-action@v1
with:
version: "12.0.1"
force-version: true
ubuntu-version: "16.04"
cached: ${{ steps.cache-llvm.outputs.cache-hit }}
- name: Checkout KernelSU-Next
uses: actions/checkout@v4
with:
path: KernelSU-Next
fetch-depth: 0
- name: Setup kernel source
uses: actions/checkout@v4
with:
repository: microsoft/WSA-Linux-Kernel
ref: android-lts/latte-2/${{ inputs.version }}
path: WSA-Linux-Kernel
- name: Setup Ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: WSA-Kernel-${{ inputs.version }}-${{ inputs.arch }}
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
max-size: 2G
- name: Setup KernelSU-Next
working-directory: WSA-Linux-Kernel
run: |
echo "[+] KernelSU-Next setup"
KERNEL_ROOT=$GITHUB_WORKSPACE/WSA-Linux-Kernel
echo "[+] KERNEL_ROOT: $KERNEL_ROOT"
echo "[+] Copy KernelSU-Next driver to $KERNEL_ROOT/drivers"
ln -sf $GITHUB_WORKSPACE/KernelSU-Next/kernel $KERNEL_ROOT/drivers/kernelsu
echo "[+] Add KernelSU-Next driver to Makefile"
DRIVER_MAKEFILE=$KERNEL_ROOT/drivers/Makefile
DRIVER_KCONFIG=$KERNEL_ROOT/drivers/Kconfig
grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
echo "[+] Apply KernelSU-Next patches"
cd $KERNEL_ROOT && git apply $GITHUB_WORKSPACE/KernelSU-Next/.github/patches/5.15/*.patch || echo "[-] No patch found"
echo "[+] KernelSU-Next setup done."
cd $GITHUB_WORKSPACE/KernelSU-Next
VERSION=$(($(git rev-list --count HEAD) + 10200))
echo "VERSION: $VERSION"
echo "kernelsu_version=$VERSION" >> $GITHUB_ENV
- name: Build Kernel
working-directory: WSA-Linux-Kernel
run: |
if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
fi
declare -A ARCH_MAP=(["x86_64"]="x64" ["arm64"]="arm64")
cp configs/wsa/config-wsa-${ARCH_MAP[${{ inputs.arch }}]} .config
make olddefconfig
declare -A FILE_NAME=(["x86_64"]="bzImage" ["arm64"]="Image")
make -j`nproc` LLVM=1 ARCH=${{ inputs.arch }} $(if [ "${{ inputs.arch }}" == "arm64" ]; then echo CROSS_COMPILE=aarch64-linux-gnu; fi) ${FILE_NAME[${{ inputs.arch }}]} CCACHE="/usr/bin/ccache"
declare -A ARCH_MAP_FILE=(["x86_64"]="x86" ["arm64"]="arm64")
echo "file_path=WSA-Linux-Kernel/arch/${ARCH_MAP_FILE[${{ inputs.arch }}]}/boot/${FILE_NAME[${{ inputs.arch }}]}" >> $GITHUB_ENV
- name: Upload kernel-${{ inputs.arch }}-${{ inputs.version }}
uses: actions/upload-artifact@v4
with:
name: kernel-WSA-${{ inputs.arch }}-${{ inputs.version }}
path: "${{ env.file_path }}"

View File

@@ -1,4 +1,4 @@
**English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) **English** | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md) | [Українська](README_UA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next officially supports most Android kernels starting from 4.4 up to 6
- GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver. - GKI 1.0 (4.19 - 5.4) kernels need to rebuilt with KernelSU driver.
- EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports). - EOL (<4.14) kernels also need to be rebuilt with KernelSU driver (3.18+ is experimental and may need some function backports).
Currently, only the `arm64-v8a` architecture is supported. Currently, only the `arm64-v8a`, `armeabi-v7a` & `x86_64` architectures are supported.
## Usage ## Usage
- [Installation instruction](https://ksunext.org/pages/installation.html) - [Installation instruction](https://kernelsu-next.github.io/webpage/pages/installation.html)
## Security ## Security

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | **Български** [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | **Български** | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,7 +24,7 @@ KernelSU Next официално поддържа повечето Android яд
- Ядра GKI 1.0 (4.19 - 5.4) изискват прекомпилиране с драйвера на KernelSU - Ядра GKI 1.0 (4.19 - 5.4) изискват прекомпилиране с драйвера на KernelSU
- Остарели ядра (<4.14) също изискват прекомпилиране (3.18+ е експериментална поддръжка) - Остарели ядра (<4.14) също изискват прекомпилиране (3.18+ е експериментална поддръжка)
В момента се поддържа само архитектурата `arm64-v8a`. В момента се поддържа само архитектурата `arm64-v8a`, `armeabi-v7a` & `x86_64`.
## Инсталация ## Инсталация

View File

@@ -1,4 +1,4 @@
[English](README.md) | **简体中文** | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | **简体中文** | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next 支持从 4.4 到 6.6 的大多数安卓内核
- GKI 1.04.19 - 5.4)内核需要使用 KernelSU 内核驱动重新编译 - GKI 1.04.19 - 5.4)内核需要使用 KernelSU 内核驱动重新编译
- EOL (<4.14) 内核也需要使用 KernelSU 内核驱动重新编译 (3.18+ 的版本处于试验阶段,可能需要移植一些功能) - EOL (<4.14) 内核也需要使用 KernelSU 内核驱动重新编译 (3.18+ 的版本处于试验阶段,可能需要移植一些功能)
目前只支持 `arm64-v8a` 架构 目前只支持 `arm64-v8a`, `armeabi-v7a` & `x86_64` 架构
## 用法 ## 用法
- [安装说明](https://KernelSU-Next.github.io/KernelSU-Next/) - [安装说明](https://ksunext.org/pages/installation.html)
## 安全性 ## 安全性

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | **Français** | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | **Français** | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next prend officiellement en charge la plupart des noyaux Android de la
- Les noyaux GKI 1.0 (4.19 - 5.4) doivent être reconstruits avec le pilote KernelSU. - Les noyaux GKI 1.0 (4.19 - 5.4) doivent être reconstruits avec le pilote KernelSU.
- Les noyaux EOL (<4.14) doivent également être reconstruits avec le pilote KernelSU (3.18+ est expérimental et peut nécessiter des rétroportages fonctionnels). - Les noyaux EOL (<4.14) doivent également être reconstruits avec le pilote KernelSU (3.18+ est expérimental et peut nécessiter des rétroportages fonctionnels).
Actuellement, seul `arm64-v8a` est pris en charge. Actuellement, seul `arm64-v8a`, `armeabi-v7a` & `x86_64` est pris en charge.
## Utilisation ## Utilisation
- [Instructions d'installation](https://KernelSU-Next.github.io/KernelSU-Next/) - [Instructions d'installation](https://ksunext.org/pages/installation.html)
## Sécurité ## Sécurité

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | **Bahasa Indonesia** | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | **Bahasa Indonesia** | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next secara resmi mendukung sebagian besar kernel Android mulai dari 4.
- Kernel GKI 1.0 (4.19 - 5.4) perlu dibangun ulang dengan driver KernelSU. - Kernel GKI 1.0 (4.19 - 5.4) perlu dibangun ulang dengan driver KernelSU.
- Kernel EOL (<4.14) juga perlu dibangun ulang dengan driver KernelSU (3.18+ bersifat eksperimental dan mungkin memerlukan beberapa backport fungsi). - Kernel EOL (<4.14) juga perlu dibangun ulang dengan driver KernelSU (3.18+ bersifat eksperimental dan mungkin memerlukan beberapa backport fungsi).
Saat ini, hanya `arm64-v8a` yang didukung. Saat ini, hanya `arm64-v8a`, `armeabi-v7a` & `x86_64` yang didukung.
## Penggunaan ## Penggunaan
- [Petunjuk instalasi](https://KernelSU-Next.github.io/KernelSU-Next/) - [Petunjuk instalasi](https://ksunext.org/pages/installation.html)
## Keamanan ## Keamanan

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | **Italiano** | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | **Italiano** | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next supporta ufficialmente la maggior parte dei kernel Android dalla v
- I kernel GKI 1.0 (4.19 - 5.4) devono essere ricostruiti con il driver KernelSU. - I kernel GKI 1.0 (4.19 - 5.4) devono essere ricostruiti con il driver KernelSU.
- Anche i kernel EOL (<4.14) devono essere ricostruiti con il driver KernelSU (la versione 3.18+ è sperimentale e potrebbe richiedere alcuni backport di funzioni). - Anche i kernel EOL (<4.14) devono essere ricostruiti con il driver KernelSU (la versione 3.18+ è sperimentale e potrebbe richiedere alcuni backport di funzioni).
Attualmente è supportata solo l'architettura `arm64-v8a`. Attualmente è supportata solo l'architettura `arm64-v8a`, `armeabi-v7a` & `x86_64`.
## Utilizzo ## Utilizzo
- [Istruzioni per l'installazione](https://KernelSU-Next.github.io/KernelSU-Next/) - [Istruzioni per l'installazione](https://ksunext.org/pages/installation.html)
## Security ## Security

63
docs/README_JA.md Normal file
View File

@@ -0,0 +1,63 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | **日本語**
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Android デバイス用のカーネルベースな root ソリューション。
[![Latest Release](https://img.shields.io/github/v/release/KernelSU-Next/KernelSU-Next?label=Release&logo=github)](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
[![GitHub License](https://img.shields.io/github/license/KernelSU-Next/KernelSU-Next?logo=gnu)](/LICENSE)
## 機能
1. カーネルベースの `su` および root アクセスの管理。
2. 動的マウントシステム [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) をベースとしたモジュールシステム。
3. [アプリプロファイル](https://kernelsu.org/guide/app-profile.html): root 権限をケージに閉じ込めます。
## 互換性の状態
KernelSU Next は 4.4 から 6.6 までのほとんどの Android カーネルを公式でサポートしています。
- GKI 2.0 (5.10 以降) のカーネルはビルド済みイメージで LKM/KMI を実行できます。
- GKI 1.0 (4.19 - 5.4) のカーネルは、KernelSU ドライバを使用してビルドする必要があります。
- EOL (4.14 未満) のカーネルも KernelSU ドライバを使用して再ビルドする必要があります (3.18 以降は実験中の段階であり、一部の関数のバックポートが必要になる場合があります)。
現在 `arm64-v8a`, `armeabi-v7a` & `x86_64` アーキテクチャのみをサポートしています。
## 使い方
- [インストール手順](https://ksunext.org/pages/installation.html)
## セキュリティ
KernelSU のセキュリティ脆弱性の報告については [SECURITY.md](/SECURITY.md) を参照してください。
## ライセンス
- `kernel` ディレクトリ内のファイルは [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.ja.html) のみライセンス下にあります。
- `kernel` ディレクトリを除くその他すべての部分は [GPL-3.0 またはそれ以降](https://www.gnu.org/licenses/gpl-3.0.html) のライセンス下にあります。
## 寄付
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
- TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
## クレジット
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU のアイデアを考案。
- [Magisk](https://github.com/topjohnwu/Magisk): パワフルな root ツール。
- [genuine](https://github.com/brevent/genuine/): APK v2 署名認証。
- [Diamorphine](https://github.com/m0nad/Diamorphine): いくつかの rootkit スキル。
- [KernelSU](https://github.com/tiann/KernelSU): tiann に感謝を申し上げます。これが存在しなければ KernelSU Next は存在しませんでした。
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff へ KernelSU を救ってくれてありがとう!

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | **한국어** | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | **한국어** | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next는 공식적으로 대부분의 4.4부터 6.6의 안드로이드
- GKI 1.0 (4.19 - 5.4) 커널은 KernelSU 드라이버로 다시 빌드해야 합니다. - GKI 1.0 (4.19 - 5.4) 커널은 KernelSU 드라이버로 다시 빌드해야 합니다.
- EOL (<4.14) 커널도 역시 KernelSU 드라이버로 다시 빌드해야 합니다.(3.18+는 실험적이며 일부 함수의 이식이 필요할 수 있습니다.). - EOL (<4.14) 커널도 역시 KernelSU 드라이버로 다시 빌드해야 합니다.(3.18+는 실험적이며 일부 함수의 이식이 필요할 수 있습니다.).
현재는, `arm64-v8a`만 지원됩니다. 현재는, `arm64-v8a`, `armeabi-v7a` & `x86_64` 만 지원됩니다.
## 사용 방법 ## 사용 방법
- [설치 방법](https://KernelSU-Next.github.io/KernelSU-Next/) - [설치 방법](https://ksunext.org/pages/installation.html)
## 보안 ## 보안

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | **Polski** | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | **Polski** | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next oficjalnie obsługuje większość jąder Androida od wersji 4.4 d
- Jądra GKI 1.0 (4.19 - 5.4) muszą zostać zrekompilowane z dodatkiem sterownika KernelSU. - Jądra GKI 1.0 (4.19 - 5.4) muszą zostać zrekompilowane z dodatkiem sterownika KernelSU.
- Jądra EOL (<4.14) również muszą zostać zrekompilowane z dodatkiem sterownika KernelSU (obsługa 3.18+ jest eksperymentalna i może wymagać backportu pewnych funkcji). - Jądra EOL (<4.14) również muszą zostać zrekompilowane z dodatkiem sterownika KernelSU (obsługa 3.18+ jest eksperymentalna i może wymagać backportu pewnych funkcji).
Obecnie obsługiwana jest tylko architektura `arm64-v8a`. Obecnie obsługiwana jest tylko architektura `arm64-v8a`, `armeabi-v7a` & `x86_64`
## Użycie ## Użycie
- [Instrukcja instalacji](https://KernelSU-Next.github.io/KernelSU-Next/) - [Instrukcja instalacji](https://ksunext.org/pages/installation.html)
## Bezpieczeństwo ## Bezpieczeństwo

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | **Português (Brasil)** | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | **Português (Brasil)** | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next suporta oficialmente a maioria dos kernels Android a partir de 4.4
- Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU. - Os kernels GKI 1.0 (4.19 - 5.4) precisam ser reconstruídos com o driver KernelSU.
- Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções). - Os kernels EOL (<4.14) também precisam ser reconstruídos com o driver KernelSU (3.18+ é experimental e pode precisar portar algumas funções).
Atualmente, apenas a arquitetura `arm64-v8a` é compatível. Atualmente, apenas as arquiteturas `arm64-v8a`, `armeabi-v7a` & `x86_64` são compatíveis.
## Uso ## Uso
- [Instruções de instalação](https://KernelSU-Next.github.io/KernelSU-Next/) - [Instruções de instalação](https://ksunext.org/pages/installation.html)
## Segurança ## Segurança

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | **Русский** | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | **Русский** | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next работает с большинством ядер Android (4.4
- GKI 1.0 (4.19 - 5.4) требуют пересборки с драйвером KernelSU. - GKI 1.0 (4.19 - 5.4) требуют пересборки с драйвером KernelSU.
- EOL (<4.14) также требуют пересборки с драйвером KernelSU (версии 3.18+ экспериментальные и могут потребовать некоторые функции бэкпортов). - EOL (<4.14) также требуют пересборки с драйвером KernelSU (версии 3.18+ экспериментальные и могут потребовать некоторые функции бэкпортов).
Сейчас поддерживается только `arm64-v8a`. Сейчас поддерживается только `arm64-v8a`, `armeabi-v7a` & `x86_64`.
## Использование ## Использование
- [Инструкция по установке](https://KernelSU-Next.github.io/KernelSU-Next/) - [Инструкция по установке](https://ksunext.org/pages/installation.html)
## Безопасность ## Безопасность
@@ -59,5 +59,5 @@ KernelSU Next работает с большинством ядер Android (4.4
- [Magisk](https://github.com/topjohnwu/Magisk): Топовый инструмент для root. - [Magisk](https://github.com/topjohnwu/Magisk): Топовый инструмент для root.
- [genuine](https://github.com/brevent/genuine/): Валидация подписи APK v2. - [genuine](https://github.com/brevent/genuine/): Валидация подписи APK v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine): Некоторые навыки rootkit. - [Diamorphine](https://github.com/m0nad/Diamorphine): Некоторые навыки rootkit.
- [KernelSU](https://github.com/tiann/KernelSU): Спасибо tiann, без него KernelSU Next не релизнулся бы. - [KernelSU](https://github.com/tiann/KernelSU): Спасибо tiann, без него KernelSU Next даже не существовал бы.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff за сохранение KernelSU! - [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff за сохранение KernelSU!

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | **ภาษาไทย** | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | **ภาษาไทย** | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next รองรับแบบเป็นทางการตั้
- GKI 1.0 (4.19 - 5.4) เคอร์เนลจะต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU - GKI 1.0 (4.19 - 5.4) เคอร์เนลจะต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU
- EOL (<4.14) เคอร์เนลก็ต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU เช่นกัน (3.18+ ยังเป็นเวอร์ชั่นทดลอง และยังต้องเขียนฟังก์ชั่นหลังบ้านเพิ่มเติม) - EOL (<4.14) เคอร์เนลก็ต้องรีบิ้วร่วมกับไดร์เวอร์ของ KernelSU เช่นกัน (3.18+ ยังเป็นเวอร์ชั่นทดลอง และยังต้องเขียนฟังก์ชั่นหลังบ้านเพิ่มเติม)
ในขณะนี้, มีแค่สถาปัตยกรรม `arm64-v8a` ที่รองรับเท่านั้น ในขณะนี้, มีแค่สถาปัตยกรรม `arm64-v8a`, `armeabi-v7a` & `x86_64` ที่รองรับเท่านั้น
## การใช้งาน ## การใช้งาน
- [คำแนะนำในการติดตั้ง](https://KernelSU-Next.github.io/KernelSU-Next/) - [คำแนะนำในการติดตั้ง](https://ksunext.org/pages/installation.html)
## ความปลอดภัย ## ความปลอดภัย

View File

@@ -1,49 +1,63 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **Türkçe** | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | **Türkçe** | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo"> <img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Android cihazlar için Kernel tabanlı bir root çözümü. Android cihazlar için çekirdek tabanlı root çözümü.
[![Latest Release](https://img.shields.io/github/v/release/KernelSU-Next/KernelSU-Next?label=Release&logo=github)](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest) [![Son Sürüm](https://img.shields.io/github/v/release/KernelSU-Next/KernelSU-Next?label=Release&logo=github)](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
[![Nightly Release](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager) [![Gece Sürümü](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-orange.svg?logo=gnu)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) [![Lisans: 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/KernelSU-Next/KernelSU-Next?logo=gnu)](/LICENSE) [![GitHub Lisansı](https://img.shields.io/github/license/KernelSU-Next/KernelSU-Next?logo=gnu)](/LICENSE)
## Özellikler ## Özellikler
1. Çekirdek tabanlı `su` ve kök erişim yönetimi. 1. Çekirdek tabanlı `su` ve root erişimi yönetimi.
2. Dinamik montaj sistemine dayalı modül sistemi [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS). 2. Dinamik bağlama sistemi [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS) tabanlı modül sistemi.
3. [App Profile](https://kernelsu.org/guide/app-profile.html): Kök gücünü bir kafese kilitleyin. 3. [Uygulama Profili](https://kernelsu.org/guide/app-profile.html): Root yetkisini bir kafese kilitleyin.
## Uyumluluk Durumu ## Uyumluluk Durumu
KernelSU Next, 4.4'dan başlayarak 6.6'ya kadar çoğu Android çekirdeğini resmi olarak desteklemektedir. KernelSU Next, resmi olarak Android çekirdeklerinin çoğunu 4.4 sürümünden 6.6 sürümüne kadar destekler.
- GKI 2.0 (5.10+) çekirdekleri önceden oluşturulmuş görüntüleri ve LKM/KMI'yi çalıştırabilir. - GKI 2.0 (5.10+) çekirdekleri, hazır imajları ve LKM/KMI desteğini çalıştırabilir.
- GKI 1.0 (4.19 - 5.4) çekirdeklerinin KernelSU sürücüsü ile yeniden oluşturulması gerekir. - GKI 1.0 (4.19 - 5.4) çekirdeklerinin KernelSU sürücüsü ile yeniden derlenmesi gerekir.
- EOL (<4.14) çekirdeklerinin de KernelSU sürücüsü ile yeniden oluşturulması gerekir. (3.18+ deneyseldir ve bazı fonksiyon geri yüklemelerine ihtiyaç duyulabilir.) - EOL (<4.14) çekirdekler de KernelSU sürücüsüyle yeniden derlenmelidir (3.18+ deneysel olup bazı fonksiyonların geri aktarımı gerekebilir).
Şu anda sadece `arm64-v8a` desteklenmektedir. Şu anda yalnızca `arm64-v8a`, `armeabi-v7a` & `x86_64` mimarisi desteklenmektedir.
## Kullanım ## Kullanım
- [Kurulum Talimatı](https://KernelSU-Next.github.io/KernelSU-Next/) - [Kurulum Talimatları](https://ksunext.org/pages/installation.html)
## Güvenlik ## Güvenlik
KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için [SECURITY.md](/SECURITY.md) bölümüne bakın. KernelSU'daki güvenlik açıklarını bildirme hakkında bilgi için bkz: [SECURITY.md](/SECURITY.md)
## Lisans ## Lisans
- `kernel` dizini altındaki dosyalar sadece [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisansına tabiidir. - `kernel` dizinindeki dosyalar [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) lisanslıdır.
- `kernel` dizini dışındaki diğer tüm kısımlar [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html) ya da daha sonraki bir sürüm lisansa tabiidir. - `kernel` dizini dışındaki tüm diğer bölümler [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html) lisansı altındadır.
## Krediler ## Bağışlar
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikri. - 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
- [Magisk](https://github.com/topjohnwu/Magisk): Güçlü kök aracı.
- [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama. - TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
- [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit becerileri.
- [KernelSU](https://github.com/tiann/KernelSU): tiann'a teşekkürler, yoksa KernelSU Next var olamazdı bile. - 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 5ec1cff KernelSU'yu kurtardığınız için!
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
## Katkıda Bulunanlar
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): KernelSU fikrinin temeli.
- [Magisk](https://github.com/topjohnwu/Magisk): Güçlü root aracı.
- [genuine](https://github.com/brevent/genuine/): APK v2 imza doğrulama.
- [Diamorphine](https://github.com/m0nad/Diamorphine): Bazı rootkit teknikleri.
- [KernelSU](https://github.com/tiann/KernelSU): tiann'a teşekkürler, KernelSU Next onun sayesinde var.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): 💜 KernelSU'yu kurtardığı için 5ec1cff'e teşekkürler!

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | **繁體中文** | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | **繁體中文** | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next 正式支持大多數從 4.4 到 6.6 的 Android 內核
- GKI 1.0 (4.19 - 5.4) 內核需要重新編譯 KernelSU 驅動程序 - GKI 1.0 (4.19 - 5.4) 內核需要重新編譯 KernelSU 驅動程序
- EOL (<4.14) 內核也需要重新編譯 KernelSU 驅動程序3.18+ 是實驗性的,可能需要移植一些功能) - EOL (<4.14) 內核也需要重新編譯 KernelSU 驅動程序3.18+ 是實驗性的,可能需要移植一些功能)
目前僅支持 `arm64-v8a` 目前僅支持 `arm64-v8a`, `armeabi-v7a` & `x86_64`
## 用法 ## 用法
- [安裝說明](https://KernelSU-Next.github.io/KernelSU-Next/) - [安裝說明](https://ksunext.org/pages/installation.html)
## 安全性 ## 安全性

63
docs/README_UA.md Normal file
View File

@@ -0,0 +1,63 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | [Tiếng Việt](README_VI.md) | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md) | **Українська**
# KernelSU Next
<img src="/assets/kernelsu_next.png" style="width: 96px;" alt="logo">
Рут-рішення на основі ядра для пристроїв Android.
[![Останній реліз](https://img.shields.io/github/v/release/KernelSU-Next/KernelSU-Next?label=Release&logo=github)](https://github.com/KernelSU-Next/KernelSU-Next/releases/latest)
[![Нічний реліз (Нестабільний)](https://img.shields.io/badge/Nightly%20Release-gray?logo=hackthebox&logoColor=fff)](https://nightly.link/KernelSU-Next/KernelSU-Next/workflows/build-manager-ci/next/Manager)
[![Ліцензія: 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/KernelSU-Next/KernelSU-Next?logo=gnu)](/LICENSE)
## Можливості
1. `su` на основі ядра та можливість контролювати дозволи руту.
2. Module system based on dynamic mount system [Magic Mount](https://topjohnwu.github.io/Magisk/details.html#magic-mount) / [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS).
3. [Профілі додатків](https://kernelsu.org/guide/app-profile.html): Обмеж права руту для додатків.
## Compatibility state
KernelSU Next офіційно підтримує більшість Android ядер починаючи з 4.4 і до 6.6.
- Користувачі GKI 2.0 (5.10+) ядра можуть використовувати готові образи та LKM/KMI.
- Користувачі GKI 1.0 (4.19 - 5.4) ядра мають бути перезібрані з драйвером KernelSU.
- Користувачі EOL (<4.14) ядра також мають бути перезібрані з драйвером KernelSU (Підтримка 3.18+ експерементальна і потребує бекпортів деяких функцій в ядрі).
На даний момент підтримується лише архітектура `arm64-v8a`, `armeabi-v7a` & `x86_64`.
## Спосіб використання
- [Інструкція для встановлення/інтеграції](https://ksunext.org/pages/installation.html)
## Безпека
Для інформації зв'язаною з безпекою дивіться [SECURITY.md](/SECURITY.md).
## Ліцензія
- Всі файли в директорії `kernel` мають ліцензію [GPL-2.0-only](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
- Всі інші файли виключаючи директорію `kernel` мають ліцензію [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html).
## Підтримка розробника
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT BEP20 ]
- TYUVMWGTcnR5svnDoX85DWHyqUAeyQcdjh [ USDT TRC20 ]
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ USDT ERC20 ]
- 0x12b5224b7aca0121c2f003240a901e1d064371c1 [ ETH ERC20 ]
- Ld238uYBuRQdZB5YwdbkuU6ektBAAUByoL [ LTC ]
- 19QgifcjMjSr1wB2DJcea5cxitvWVcXMT6 [ BTC ]
## Подяки
- [Kernel-Assisted Superuser](https://git.zx2c4.com/kernel-assisted-superuser/about/): Ідея KernelSU.
- [Magisk](https://github.com/topjohnwu/Magisk): Потужний засіб руту.
- [genuine](https://github.com/brevent/genuine/): Перевірка підпису APK v2.
- [Diamorphine](https://github.com/m0nad/Diamorphine): Деякі руткіт скіли.
- [KernelSU](https://github.com/tiann/KernelSU): Дякую tiann, інакше KernelSU Next ніколи б не існував.
- [Magic Mount Port](https://github.com/5ec1cff/KernelSU/blob/main/userspace/ksud/src/magic_mount.rs): Дякую 💜 5ec1cff за збереження KernelSU!

View File

@@ -1,4 +1,4 @@
[English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [ภาษาไทย](README_TH.md) | **Tiếng Việt** | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) [English](README.md) | [简体中文](README_CN.md) | [繁體中文](README_TW.md) | [Türkçe](README_TR.md) | [Português (Brasil)](README_PT-BR.md) | [한국어](README_KO.md) | [Français](README_FR.md) | [Bahasa Indonesia](README_ID.md) | [Русский](README_RU.md) | [Український](README_UA.md) | [ภาษาไทย](README_TH.md) | **Tiếng Việt** | [Italiano](README_IT.md) | [Polski](README_PL.md) | [Български](README_BG.md) | [日本語](README_JA.md)
# KernelSU Next # KernelSU Next
@@ -24,11 +24,11 @@ KernelSU Next hỗ trợ chính thức các kernel Android từ phiên bản 4.4
- GKI 1.0 (4.19 - 5.4) kernels cần dược build lại với các nhân KernelSU Next - GKI 1.0 (4.19 - 5.4) kernels cần dược build lại với các nhân KernelSU Next
- EOL (<4.14) kernels cần dược build lại với các nhân KernelSU Next (các kernels 3.18+ đang dược thử nghiệm và có thể cần backports 1 vài thứ ). - EOL (<4.14) kernels cần dược build lại với các nhân KernelSU Next (các kernels 3.18+ đang dược thử nghiệm và có thể cần backports 1 vài thứ ).
Hiện tại kernelSU Next chỉ hỗ trợ những cpu có `arm64-v8a` Hiện tại kernelSU Next chỉ hỗ trợ những cpu có `arm64-v8a`, `armeabi-v7a` & `x86_64`
## Sử dụng ## Sử dụng
- [Hướng dẫn vá KernelSU Next vào Kernel của bạn (yêu cầu kernel source)](https://KernelSU-Next.github.io/KernelSU-Next/) - [Hướng dẫn vá KernelSU Next vào Kernel của bạn (yêu cầu kernel source)](https://ksunext.org/pages/installation.html)
## Bảo mật ## Bảo mật

View File

@@ -9,7 +9,7 @@ config KSU
To compile as a module, choose M here: the To compile as a module, choose M here: the
module will be called kernelsu. module will be called kernelsu.
config KSU_WITH_KPROBES config KSU_KPROBES_HOOK
bool "Use kprobes for kernelsu" bool "Use kprobes for kernelsu"
depends on KSU depends on KSU
depends on KPROBES depends on KPROBES
@@ -32,4 +32,12 @@ config KSU_ALLOWLIST_WORKAROUND
Enable session keyring init workaround for problematic devices. Enable session keyring init workaround for problematic devices.
Useful for situations where the SU allowlist is not kept after a reboot. Useful for situations where the SU allowlist is not kept after a reboot.
config KSU_LSM_SECURITY_HOOKS
bool "use lsm security hooks"
depends on KSU
default y
help
Disabling this is mostly only useful for kernel 4.1 and older.
Make sure to implement manual hooks on security/security.c.
endmenu endmenu

View File

@@ -16,18 +16,32 @@ ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-
obj-$(CONFIG_KSU) += kernelsu.o obj-$(CONFIG_KSU) += kernelsu.o
# .git is a text file while the module is imported by 'git submodule add'. REPO_OWNER := KernelSU-Next
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0) REPO_NAME := KernelSU-Next
$(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin [ -f ../.git/shallow ] && git fetch --unshallow) REPO_BRANCH := next
KSU_GIT_VERSION := $(shell cd $(srctree)/$(src); /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git rev-list --count HEAD)
# ksu_version: major * 10000 + git version + 200 for historical reasons GIT_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin git
$(eval KSU_VERSION=$(shell expr 10000 + $(KSU_GIT_VERSION) + 200)) CURL_BIN := /usr/bin/env PATH="$$PATH":/usr/bin:/usr/local/bin curl
KSU_GITHUB_VERSION := $(shell $(CURL_BIN) -sI "https://api.github.com/repos/$(REPO_OWNER)/$(REPO_NAME)/commits?sha=$(REPO_BRANCH)&per_page=1" | grep -i "link:" | sed -n 's/.*page=\([0-9]*\)>; rel="last".*/\1/p')
ifeq ($(KSU_GITHUB_VERSION),)
ifeq ($(shell test -e $(srctree)/$(src)/../.git; echo $$?),0)
$(shell cd $(srctree)/$(src); [ -f ../.git/shallow ] && $(GIT_BIN) fetch --unshallow)
KSU_LOCAL_VERSION := $(shell cd $(srctree)/$(src); $(GIT_BIN) rev-list --count HEAD)
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_LOCAL_VERSION) + 200))
$(info -- KernelSU-Next version (local .git): $(KSU_VERSION))
else
$(eval KSU_VERSION := 11998)
$(warning -- Could not fetch version online or via local .git! Using fallback version: $(KSU_VERSION))
endif
else
$(eval KSU_VERSION := $(shell expr 10000 + $(KSU_GITHUB_VERSION) + 200))
$(info -- KernelSU-Next version (GitHub): $(KSU_VERSION))
endif
$(info -- KernelSU-Next version: $(KSU_VERSION)) $(info -- KernelSU-Next version: $(KSU_VERSION))
ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION=$(KSU_VERSION)
else # If there is no .git file, the default version will be passed.
$(warning "KSU_GIT_VERSION not defined! It is better to make KernelSU-Next a git submodule!")
ccflags-y += -DKSU_VERSION=11998
endif
ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0) ifeq ($(shell grep -q " current_sid(void)" $(srctree)/security/selinux/include/objsec.h; echo $$?),0)
ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID ccflags-y += -DKSU_COMPAT_HAS_CURRENT_SID

View File

@@ -17,6 +17,7 @@
#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 "throne_tracker.h"
struct sdesc { struct sdesc {
@@ -316,5 +317,21 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,
bool is_manager_apk(char *path) bool is_manager_apk(char *path)
{ {
int tries = 0;
while (tries++ < 10) {
if (!is_lock_held(path))
break;
pr_info("%s: waiting for %s\n", __func__, path);
msleep(100);
}
// let it go, if retry fails, check_v2_signature will fail to open it anyway
if (tries == 10) {
pr_info("%s: timeout for %s\n", __func__, path);
return false;
}
return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH); return check_v2_signature(path, EXPECTED_NEXT_SIZE, EXPECTED_NEXT_HASH);
} }

View File

@@ -7,7 +7,9 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
#include <linux/lsm_hooks.h> #include <linux/lsm_hooks.h>
#endif
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <linux/path.h> #include <linux/path.h>
@@ -116,6 +118,7 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
groups_sort(group_info); groups_sort(group_info);
set_groups(cred, group_info); set_groups(cred, group_info);
put_group_info(group_info);
} }
static void disable_seccomp(void) static void disable_seccomp(void)
@@ -140,27 +143,17 @@ void escape_to_root(void)
{ {
struct cred *cred; struct cred *cred;
#ifdef KSU_GET_CRED_RCU cred = prepare_creds();
rcu_read_lock(); if (!cred) {
pr_warn("prepare_creds failed!\n");
do { return;
cred = (struct cred *)__task_cred((current)); }
BUG_ON(!cred);
} while (!get_cred_rcu(cred));
if (cred->euid.val == 0) { if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n"); pr_warn("Already root, don't escape!\n");
rcu_read_unlock(); abort_creds(cred);
return; return;
} }
#else
cred = (struct cred *)__task_cred(current);
if (cred->euid.val == 0) {
pr_warn("Already root, don't escape!\n");
return;
}
#endif
struct root_profile *profile = ksu_get_root_profile(cred->uid.val); struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
@@ -195,10 +188,8 @@ void escape_to_root(void)
sizeof(cred->cap_ambient)); sizeof(cred->cap_ambient));
setup_groups(profile, cred); setup_groups(profile, cred);
#ifdef KSU_GET_CRED_RCU commit_creds(cred);
rcu_read_unlock();
#endif
// Refer to kernel/seccomp.c: seccomp_set_mode_strict // Refer to kernel/seccomp.c: seccomp_set_mode_strict
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation. // When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
@@ -265,7 +256,7 @@ static void nuke_ext4_sysfs() {
} }
ext4_unregister_sysfs(sb); ext4_unregister_sysfs(sb);
path_put(&path); path_put(&path);
} }
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
@@ -337,6 +328,18 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0; return 0;
} }
if (arg2 == CMD_HOOK_MODE) {
#ifdef CONFIG_KSU_KPROBES_HOOK
const char *mode = "Kprobes";
#else
const char *mode = "Manual";
#endif
if (copy_to_user((void __user *)arg3, mode, strlen(mode) + 1)) {
pr_info("hook: copy_to_user() failed\n");
}
return 0;
}
if (arg2 == CMD_REPORT_EVENT) { if (arg2 == CMD_REPORT_EVENT) {
if (!from_root) { if (!from_root) {
return 0; return 0;
@@ -566,11 +569,13 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
if (path.dentry != path.mnt->mnt_root) { if (path.dentry != path.mnt->mnt_root) {
// it is not root mountpoint, maybe umounted by others already. // it is not root mountpoint, maybe umounted by others already.
path_put(&path);
return; return;
} }
// we are only interest in some specific mounts // we are only interest in some specific mounts
if (check_mnt && !should_umount(&path)) { if (check_mnt && !should_umount(&path)) {
path_put(&path);
return; return;
} }
@@ -634,6 +639,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and // fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb` // filter the mountpoint whose target is `/data/adb`
try_umount("/odm", true, 0);
try_umount("/system", true, 0); try_umount("/system", true, 0);
try_umount("/system_ext", true, 0); try_umount("/system_ext", true, 0);
try_umount("/vendor", true, 0); try_umount("/vendor", true, 0);
@@ -643,7 +649,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
// try umount ksu temp path // try umount ksu temp path
try_umount("/debug_ramdisk", false, MNT_DETACH); try_umount("/debug_ramdisk", false, MNT_DETACH);
try_umount("/sbin", false, MNT_DETACH); try_umount("/sbin", false, MNT_DETACH);
// try umount hosts file // try umount hosts file
try_umount("/system/etc/hosts", false, MNT_DETACH); try_umount("/system/etc/hosts", false, MNT_DETACH);
@@ -723,15 +729,22 @@ __maybe_unused int ksu_kprobe_exit(void)
return 0; return 0;
} }
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3, extern int ksu_handle_devpts(struct inode *inode); // sucompat.c
unsigned long arg4, unsigned long arg5)
static int ksu_inode_permission(struct inode *inode, int mask)
{ {
ksu_handle_prctl(option, arg2, arg3, arg4, arg5); if (unlikely(inode->i_sb && inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)) {
return -ENOSYS; #ifdef CONFIG_KSU_DEBUG
pr_info("%s: devpts inode accessed with mask: %x\n", __func__, mask);
#endif
ksu_handle_devpts(inode);
}
return 0;
} }
// kernel 4.4 and 4.9
// kernel 4.9 and older
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
unsigned perm) unsigned perm)
{ {
if (init_session_keyring != NULL) { if (init_session_keyring != NULL) {
@@ -746,6 +759,15 @@ static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
return 0; return 0;
} }
#endif #endif
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
ksu_handle_prctl(option, arg2, arg3, arg4, arg5);
return -ENOSYS;
}
static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry, static int ksu_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry) struct inode *new_inode, struct dentry *new_dentry)
{ {
@@ -763,6 +785,7 @@ static struct security_hook_list ksu_hooks[] = {
LSM_HOOK_INIT(task_prctl, ksu_task_prctl), LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
LSM_HOOK_INIT(inode_rename, ksu_inode_rename), LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
LSM_HOOK_INIT(inode_permission, ksu_inode_permission),
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
LSM_HOOK_INIT(key_permission, ksu_key_permission) LSM_HOOK_INIT(key_permission, ksu_key_permission)
#endif #endif
@@ -944,16 +967,21 @@ void __init ksu_lsm_hook_init(void)
} }
smp_mb(); smp_mb();
} }
#endif #endif // MODULE
#endif // CONFIG_KSU_LSM_SECURITY_HOOKS
void __init ksu_core_init(void) void __init ksu_core_init(void)
{ {
#ifdef CONFIG_KSU_LSM_SECURITY_HOOKS
ksu_lsm_hook_init(); ksu_lsm_hook_init();
#else
pr_info("ksu_core_init: LSM hooks not in use.\n");
#endif
} }
void ksu_core_exit(void) void ksu_core_exit(void)
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
pr_info("ksu_core_kprobe_exit\n"); pr_info("ksu_core_kprobe_exit\n");
// we dont use this now // we dont use this now
// ksu_kprobe_exit(); // ksu_kprobe_exit();

View File

@@ -57,7 +57,7 @@ int __init kernelsu_init(void)
ksu_throne_tracker_init(); ksu_throne_tracker_init();
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
ksu_sucompat_init(); ksu_sucompat_init();
ksu_ksud_init(); ksu_ksud_init();
#else #else
@@ -80,7 +80,7 @@ void kernelsu_exit(void)
destroy_workqueue(ksu_workqueue); destroy_workqueue(ksu_workqueue);
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
ksu_ksud_exit(); ksu_ksud_exit();
ksu_sucompat_exit(); ksu_sucompat_exit();
#endif #endif

View File

@@ -23,6 +23,7 @@
#define CMD_UID_SHOULD_UMOUNT 13 #define CMD_UID_SHOULD_UMOUNT 13
#define CMD_IS_SU_ENABLED 14 #define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15 #define CMD_ENABLE_SU 15
#define CMD_HOOK_MODE 16
#define EVENT_POST_FS_DATA 1 #define EVENT_POST_FS_DATA 1
#define EVENT_BOOT_COMPLETED 2 #define EVENT_BOOT_COMPLETED 2

View File

@@ -54,7 +54,7 @@ static void stop_vfs_read_hook();
static void stop_execve_hook(); static void stop_execve_hook();
static void stop_input_hook(); static void stop_input_hook();
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
static struct work_struct stop_vfs_read_work; static struct work_struct stop_vfs_read_work;
static struct work_struct stop_execve_hook_work; static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work; static struct work_struct stop_input_hook_work;
@@ -67,6 +67,10 @@ bool ksu_input_hook __read_mostly = true;
u32 ksu_devpts_sid; u32 ksu_devpts_sid;
#ifdef CONFIG_COMPAT
bool ksu_is_compat __read_mostly = false;
#endif
void on_post_fs_data(void) void on_post_fs_data(void)
{ {
static bool done = false; static bool done = false;
@@ -108,6 +112,7 @@ static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
if (get_user(compat, argv.ptr.compat + nr)) if (get_user(compat, argv.ptr.compat + nr))
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
ksu_is_compat = true;
return compat_ptr(compat); return compat_ptr(compat);
} }
#endif #endif
@@ -158,7 +163,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
struct user_arg_ptr *argv, struct user_arg_ptr *argv,
struct user_arg_ptr *envp, int *flags) struct user_arg_ptr *envp, int *flags)
{ {
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_execveat_hook) { if (!ksu_execveat_hook) {
return 0; return 0;
} }
@@ -314,7 +319,7 @@ static ssize_t read_iter_proxy(struct kiocb *iocb, struct iov_iter *to)
int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos) size_t *count_ptr, loff_t **pos)
{ {
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_vfs_read_hook) { if (!ksu_vfs_read_hook) {
return 0; return 0;
} }
@@ -333,7 +338,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
return 0; return 0;
} }
if (!d_is_reg(file->f_path.dentry)) { if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
return 0; return 0;
} }
@@ -391,10 +396,12 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
if (orig_read) { if (orig_read) {
fops_proxy.read = read_proxy; fops_proxy.read = read_proxy;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
orig_read_iter = file->f_op->read_iter; orig_read_iter = file->f_op->read_iter;
if (orig_read_iter) { if (orig_read_iter) {
fops_proxy.read_iter = read_iter_proxy; fops_proxy.read_iter = read_iter_proxy;
} }
#endif
// replace the file_operations // replace the file_operations
file->f_op = &fops_proxy; file->f_op = &fops_proxy;
read_count_append = rc_count; read_count_append = rc_count;
@@ -427,7 +434,7 @@ static bool is_volumedown_enough(unsigned int count)
int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
int *value) int *value)
{ {
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_input_hook) { if (!ksu_input_hook) {
return 0; return 0;
} }
@@ -499,7 +506,7 @@ __maybe_unused int ksu_handle_execve_ksud(const char __user *filename_user,
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL, NULL); return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL, NULL);
} }
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864 // https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
@@ -627,9 +634,32 @@ static void do_stop_input_hook(struct work_struct *work)
} }
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
#include "objsec.h" // task_security_struct
bool is_ksu_transition(const struct task_security_struct *old_tsec,
const struct task_security_struct *new_tsec)
{
static u32 ksu_sid;
char *secdata;
u32 seclen;
bool allowed = false;
if (!ksu_sid)
security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid);
if (security_secid_to_secctx(old_tsec->sid, &secdata, &seclen))
return false;
allowed = (!strcmp("u:r:init:s0", secdata) && new_tsec->sid == ksu_sid);
security_release_secctx(secdata, seclen);
return allowed;
}
#endif
static void stop_vfs_read_hook() static void stop_vfs_read_hook()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
bool ret = schedule_work(&stop_vfs_read_work); bool ret = schedule_work(&stop_vfs_read_work);
pr_info("unregister vfs_read kprobe: %d!\n", ret); pr_info("unregister vfs_read kprobe: %d!\n", ret);
#else #else
@@ -640,7 +670,7 @@ static void stop_vfs_read_hook()
static void stop_execve_hook() static void stop_execve_hook()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
bool ret = schedule_work(&stop_execve_hook_work); bool ret = schedule_work(&stop_execve_hook_work);
pr_info("unregister execve kprobe: %d!\n", ret); pr_info("unregister execve kprobe: %d!\n", ret);
#else #else
@@ -651,7 +681,7 @@ static void stop_execve_hook()
static void stop_input_hook() static void stop_input_hook()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
static bool input_hook_stopped = false; static bool input_hook_stopped = false;
if (input_hook_stopped) { if (input_hook_stopped) {
return; return;
@@ -669,7 +699,7 @@ static void stop_input_hook()
// ksud: module support // ksud: module support
void ksu_ksud_init() void ksu_ksud_init()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
int ret; int ret;
ret = register_kprobe(&execve_kp); ret = register_kprobe(&execve_kp);
@@ -689,7 +719,7 @@ void ksu_ksud_init()
void ksu_ksud_exit() void ksu_ksud_exit()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
unregister_kprobe(&execve_kp); unregister_kprobe(&execve_kp);
// this should be done before unregister vfs_read_kp // this should be done before unregister vfs_read_kp
// unregister_kprobe(&vfs_read_kp); // unregister_kprobe(&vfs_read_kp);

View File

@@ -149,17 +149,45 @@ void apply_kernelsu_rules()
#define CMD_TYPE_CHANGE 8 #define CMD_TYPE_CHANGE 8
#define CMD_GENFSCON 9 #define CMD_GENFSCON 9
#ifdef CONFIG_64BIT
struct sepol_data { struct sepol_data {
u32 cmd; u32 cmd;
u32 subcmd; u32 subcmd;
char __user *sepol1; u64 field_sepol1;
char __user *sepol2; u64 field_sepol2;
char __user *sepol3; u64 field_sepol3;
char __user *sepol4; u64 field_sepol4;
char __user *sepol5; u64 field_sepol5;
char __user *sepol6; u64 field_sepol6;
char __user *sepol7; u64 field_sepol7;
}; };
#ifdef CONFIG_COMPAT
extern bool ksu_is_compat __read_mostly;
struct sepol_compat_data {
u32 cmd;
u32 subcmd;
u32 field_sepol1;
u32 field_sepol2;
u32 field_sepol3;
u32 field_sepol4;
u32 field_sepol5;
u32 field_sepol6;
u32 field_sepol7;
};
#endif // CONFIG_COMPAT
#else
struct sepol_data {
u32 cmd;
u32 subcmd;
u32 field_sepol1;
u32 field_sepol2;
u32 field_sepol3;
u32 field_sepol4;
u32 field_sepol5;
u32 field_sepol6;
u32 field_sepol7;
};
#endif // CONFIG_64BIT
static int get_object(char *buf, char __user *user_object, size_t buf_sz, static int get_object(char *buf, char __user *user_object, size_t buf_sz,
char **object) char **object)
@@ -204,15 +232,59 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
if (!getenforce()) { if (!getenforce()) {
pr_info("SELinux permissive or disabled when handle policy!\n"); pr_info("SELinux permissive or disabled when handle policy!\n");
} }
u32 cmd, subcmd;
char __user *sepol1, *sepol2, *sepol3, *sepol4, *sepol5, *sepol6, *sepol7;
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
if (unlikely(ksu_is_compat)) {
struct sepol_compat_data compat_data;
if (copy_from_user(&compat_data, arg4, sizeof(struct sepol_compat_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
sepol1 = compat_ptr(compat_data.field_sepol1);
sepol2 = compat_ptr(compat_data.field_sepol2);
sepol3 = compat_ptr(compat_data.field_sepol3);
sepol4 = compat_ptr(compat_data.field_sepol4);
sepol5 = compat_ptr(compat_data.field_sepol5);
sepol6 = compat_ptr(compat_data.field_sepol6);
sepol7 = compat_ptr(compat_data.field_sepol7);
cmd = compat_data.cmd;
subcmd = compat_data.subcmd;
} else {
struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n");
return -1;
}
sepol1 = data.field_sepol1;
sepol2 = data.field_sepol2;
sepol3 = data.field_sepol3;
sepol4 = data.field_sepol4;
sepol5 = data.field_sepol5;
sepol6 = data.field_sepol6;
sepol7 = data.field_sepol7;
cmd = data.cmd;
subcmd = data.subcmd;
}
#else
// basically for full native, say (64BIT=y COMPAT=n) || (64BIT=n)
struct sepol_data data; struct sepol_data data;
if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) { if (copy_from_user(&data, arg4, sizeof(struct sepol_data))) {
pr_err("sepol: copy sepol_data failed.\n"); pr_err("sepol: copy sepol_data failed.\n");
return -1; return -1;
} }
sepol1 = data.field_sepol1;
u32 cmd = data.cmd; sepol2 = data.field_sepol2;
u32 subcmd = data.subcmd; sepol3 = data.field_sepol3;
sepol4 = data.field_sepol4;
sepol5 = data.field_sepol5;
sepol6 = data.field_sepol6;
sepol7 = data.field_sepol7;
cmd = data.cmd;
subcmd = data.subcmd;
#endif
rcu_read_lock(); rcu_read_lock();
@@ -226,22 +298,22 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_buf[MAX_SEPOL_LEN]; char perm_buf[MAX_SEPOL_LEN];
char *s, *t, *c, *p; char *s, *t, *c, *p;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) { if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) { if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) { if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (get_object(perm_buf, data.sepol4, sizeof(perm_buf), &p) < if (get_object(perm_buf, sepol4, sizeof(perm_buf), &p) <
0) { 0) {
pr_err("sepol: copy perm failed.\n"); pr_err("sepol: copy perm failed.\n");
goto exit; goto exit;
@@ -271,24 +343,24 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char perm_set[MAX_SEPOL_LEN]; char perm_set[MAX_SEPOL_LEN];
char *s, *t, *c; char *s, *t, *c;
if (get_object(src_buf, data.sepol1, sizeof(src_buf), &s) < 0) { if (get_object(src_buf, sepol1, sizeof(src_buf), &s) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (get_object(tgt_buf, data.sepol2, sizeof(tgt_buf), &t) < 0) { if (get_object(tgt_buf, sepol2, sizeof(tgt_buf), &t) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (get_object(cls_buf, data.sepol3, sizeof(cls_buf), &c) < 0) { if (get_object(cls_buf, sepol3, sizeof(cls_buf), &c) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(operation, data.sepol4, if (strncpy_from_user(operation, sepol4,
sizeof(operation)) < 0) { sizeof(operation)) < 0) {
pr_err("sepol: copy operation failed.\n"); pr_err("sepol: copy operation failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(perm_set, data.sepol5, sizeof(perm_set)) < if (strncpy_from_user(perm_set, sepol5, sizeof(perm_set)) <
0) { 0) {
pr_err("sepol: copy perm_set failed.\n"); pr_err("sepol: copy perm_set failed.\n");
goto exit; goto exit;
@@ -308,7 +380,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_TYPE_STATE) { } else if (cmd == CMD_TYPE_STATE) {
char src[MAX_SEPOL_LEN]; char src[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
@@ -328,11 +400,11 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char type[MAX_SEPOL_LEN]; char type[MAX_SEPOL_LEN];
char attr[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(type, data.sepol1, sizeof(type)) < 0) { if (strncpy_from_user(type, sepol1, sizeof(type)) < 0) {
pr_err("sepol: copy type failed.\n"); pr_err("sepol: copy type failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(attr, data.sepol2, sizeof(attr)) < 0) { if (strncpy_from_user(attr, sepol2, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n"); pr_err("sepol: copy attr failed.\n");
goto exit; goto exit;
} }
@@ -352,7 +424,7 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
} else if (cmd == CMD_ATTR) { } else if (cmd == CMD_ATTR) {
char attr[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN];
if (strncpy_from_user(attr, data.sepol1, sizeof(attr)) < 0) { if (strncpy_from_user(attr, sepol1, sizeof(attr)) < 0) {
pr_err("sepol: copy attr failed.\n"); pr_err("sepol: copy attr failed.\n");
goto exit; goto exit;
} }
@@ -369,28 +441,28 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char default_type[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN];
char object[MAX_SEPOL_LEN]; char object[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) { if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) { if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(default_type, data.sepol4, if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) { sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n"); pr_err("sepol: copy default_type failed.\n");
goto exit; goto exit;
} }
char *real_object; char *real_object;
if (data.sepol5 == NULL) { if (sepol5 == NULL) {
real_object = NULL; real_object = NULL;
} else { } else {
if (strncpy_from_user(object, data.sepol5, if (strncpy_from_user(object, sepol5,
sizeof(object)) < 0) { sizeof(object)) < 0) {
pr_err("sepol: copy object failed.\n"); pr_err("sepol: copy object failed.\n");
goto exit; goto exit;
@@ -409,19 +481,19 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char cls[MAX_SEPOL_LEN]; char cls[MAX_SEPOL_LEN];
char default_type[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN];
if (strncpy_from_user(src, data.sepol1, sizeof(src)) < 0) { if (strncpy_from_user(src, sepol1, sizeof(src)) < 0) {
pr_err("sepol: copy src failed.\n"); pr_err("sepol: copy src failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(tgt, data.sepol2, sizeof(tgt)) < 0) { if (strncpy_from_user(tgt, sepol2, sizeof(tgt)) < 0) {
pr_err("sepol: copy tgt failed.\n"); pr_err("sepol: copy tgt failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(cls, data.sepol3, sizeof(cls)) < 0) { if (strncpy_from_user(cls, sepol3, sizeof(cls)) < 0) {
pr_err("sepol: copy cls failed.\n"); pr_err("sepol: copy cls failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(default_type, data.sepol4, if (strncpy_from_user(default_type, sepol4,
sizeof(default_type)) < 0) { sizeof(default_type)) < 0) {
pr_err("sepol: copy default_type failed.\n"); pr_err("sepol: copy default_type failed.\n");
goto exit; goto exit;
@@ -442,15 +514,15 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4)
char name[MAX_SEPOL_LEN]; char name[MAX_SEPOL_LEN];
char path[MAX_SEPOL_LEN]; char path[MAX_SEPOL_LEN];
char context[MAX_SEPOL_LEN]; char context[MAX_SEPOL_LEN];
if (strncpy_from_user(name, data.sepol1, sizeof(name)) < 0) { if (strncpy_from_user(name, sepol1, sizeof(name)) < 0) {
pr_err("sepol: copy name failed.\n"); pr_err("sepol: copy name failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(path, data.sepol2, sizeof(path)) < 0) { if (strncpy_from_user(path, sepol2, sizeof(path)) < 0) {
pr_err("sepol: copy path failed.\n"); pr_err("sepol: copy path failed.\n");
goto exit; goto exit;
} }
if (strncpy_from_user(context, data.sepol3, sizeof(context)) < if (strncpy_from_user(context, sepol3, sizeof(context)) <
0) { 0) {
pr_err("sepol: copy context failed.\n"); pr_err("sepol: copy context failed.\n");
goto exit; goto exit;

View File

@@ -24,11 +24,9 @@
#define SU_PATH "/system/bin/su" #define SU_PATH "/system/bin/su"
#define SH_PATH "/system/bin/sh" #define SH_PATH "/system/bin/sh"
bool ksu_faccessat_hook __read_mostly = true; #ifndef CONFIG_KSU_KPROBES_HOOK
bool ksu_stat_hook __read_mostly = true; static bool ksu_sucompat_non_kp __read_mostly = true;
bool ksu_execve_sucompat_hook __read_mostly = true; #endif
bool ksu_execveat_sucompat_hook __read_mostly = true;
bool ksu_devpts_hook __read_mostly = true;
extern void escape_to_root(); extern void escape_to_root();
@@ -60,8 +58,8 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
{ {
const char su[] = SU_PATH; const char su[] = SU_PATH;
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_faccessat_hook) { if (!ksu_sucompat_non_kp) {
return 0; return 0;
} }
#endif #endif
@@ -87,8 +85,8 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
// const char sh[] = SH_PATH; // const char sh[] = SH_PATH;
const char su[] = SU_PATH; const char su[] = SU_PATH;
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_stat_hook){ if (!ksu_sucompat_non_kp){
return 0; return 0;
} }
#endif #endif
@@ -137,8 +135,8 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
const char sh[] = KSUD_PATH; const char sh[] = KSUD_PATH;
const char su[] = SU_PATH; const char su[] = SU_PATH;
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_execveat_sucompat_hook) { if (!ksu_sucompat_non_kp) {
return 0; return 0;
} }
#endif #endif
@@ -172,8 +170,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
const char su[] = SU_PATH; const char su[] = SU_PATH;
char path[sizeof(su) + 1]; char path[sizeof(su) + 1];
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_execve_sucompat_hook) { if (!ksu_sucompat_non_kp) {
return 0; return 0;
} }
#endif #endif
@@ -181,8 +179,23 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
if (unlikely(!filename_user)) if (unlikely(!filename_user))
return 0; return 0;
memset(path, 0, sizeof(path)); // nofault variant fails probably due to pagefault_disable
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); // some cpus dont really have that good speculative execution
// substitute set_fs, check if pointer is valid
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
if (!access_ok(VERIFY_READ, *filename_user, sizeof(path)))
return 0;
#else
if (!access_ok(*filename_user, sizeof(path)))
return 0;
#endif
// success = returns number of bytes and should be less than path
long len = strncpy_from_user(path, *filename_user, sizeof(path));
if (len <= 0 || len > sizeof(path))
return 0;
// strncpy_from_user_nofault does this too
path[sizeof(path) - 1] = '\0';
if (likely(memcmp(path, su, sizeof(su)))) if (likely(memcmp(path, su, sizeof(su))))
return 0; return 0;
@@ -200,8 +213,8 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
int ksu_handle_devpts(struct inode *inode) int ksu_handle_devpts(struct inode *inode)
{ {
#ifndef CONFIG_KSU_WITH_KPROBES #ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_devpts_hook) { if (!ksu_sucompat_non_kp) {
return 0; return 0;
} }
#endif #endif
@@ -234,7 +247,7 @@ int ksu_handle_devpts(struct inode *inode)
return 0; return 0;
} }
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{ {
@@ -317,33 +330,25 @@ static struct kprobe *su_kps[4];
// sucompat: permited process can execute 'su' to gain root access. // sucompat: permited process can execute 'su' to gain root access.
void ksu_sucompat_init() void ksu_sucompat_init()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre); su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre);
su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre); su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre);
su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre); su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre);
su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre); su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre);
#else #else
ksu_faccessat_hook = true; ksu_sucompat_non_kp = true;
ksu_stat_hook = true;
ksu_execve_sucompat_hook = true;
ksu_execveat_sucompat_hook = true;
ksu_devpts_hook = true;
pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n"); pr_info("ksu_sucompat_init: hooks enabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif #endif
} }
void ksu_sucompat_exit() void ksu_sucompat_exit()
{ {
#ifdef CONFIG_KSU_WITH_KPROBES #ifdef CONFIG_KSU_KPROBES_HOOK
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) { for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
destroy_kprobe(&su_kps[i]); destroy_kprobe(&su_kps[i]);
} }
#else #else
ksu_faccessat_hook = false; ksu_sucompat_non_kp = false;
ksu_stat_hook = false;
ksu_execve_sucompat_hook = false;
ksu_execveat_sucompat_hook = false;
ksu_devpts_hook = false;
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n"); pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif #endif
} }

View File

@@ -170,7 +170,11 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
return FILLDIR_ACTOR_CONTINUE; return FILLDIR_ACTOR_CONTINUE;
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
strlcpy(data->dirpath, dirpath, DATA_PATH_LEN);
#else
strscpy(data->dirpath, dirpath, DATA_PATH_LEN); strscpy(data->dirpath, dirpath, DATA_PATH_LEN);
#endif
data->depth = my_ctx->depth - 1; data->depth = my_ctx->depth - 1;
list_add_tail(&data->list, my_ctx->data_path_list); list_add_tail(&data->list, my_ctx->data_path_list);
} else { } else {
@@ -212,12 +216,53 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
return FILLDIR_ACTOR_CONTINUE; return FILLDIR_ACTOR_CONTINUE;
} }
/*
* small helper to check if lock is held
* false - file is stable
* true - file is being deleted/renamed
* possibly optional
*
*/
bool is_lock_held(const char *path)
{
struct path kpath;
// kern_path returns 0 on success
if (kern_path(path, 0, &kpath))
return true;
// just being defensive
if (!kpath.dentry) {
path_put(&kpath);
return true;
}
if (!spin_trylock(&kpath.dentry->d_lock)) {
pr_info("%s: lock held, bail out!\n", __func__);
path_put(&kpath);
return true;
}
// we hold it ourselves here!
spin_unlock(&kpath.dentry->d_lock);
path_put(&kpath);
return false;
}
// compat: https://elixir.bootlin.com/linux/v3.9/source/include/linux/fs.h#L771
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
#define S_MAGIC_COMPAT(x) ((x)->f_inode->i_sb->s_magic)
#else
#define S_MAGIC_COMPAT(x) ((x)->f_path.dentry->d_inode->i_sb->s_magic)
#endif
void search_manager(const char *path, int depth, struct list_head *uid_data) void search_manager(const char *path, int depth, struct list_head *uid_data)
{ {
int i, stop = 0; int i, stop = 0;
struct list_head data_path_list; struct list_head data_path_list;
INIT_LIST_HEAD(&data_path_list); INIT_LIST_HEAD(&data_path_list);
unsigned long data_app_magic = 0;
// Initialize APK cache list // Initialize APK cache list
struct apk_path_hash *pos, *n; struct apk_path_hash *pos, *n;
list_for_each_entry(pos, &apk_path_hash_list, list) { list_for_each_entry(pos, &apk_path_hash_list, list) {
@@ -226,7 +271,11 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
// First depth // First depth
struct data_path data; struct data_path data;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
strlcpy(data.dirpath, path, DATA_PATH_LEN);
#else
strscpy(data.dirpath, path, DATA_PATH_LEN); strscpy(data.dirpath, path, DATA_PATH_LEN);
#endif
data.depth = depth; data.depth = depth;
list_add_tail(&data.list, &data_path_list); list_add_tail(&data.list, &data_path_list);
@@ -248,6 +297,24 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file)); pr_err("Failed to open directory: %s, err: %ld\n", pos->dirpath, PTR_ERR(file));
goto skip_iterate; goto skip_iterate;
} }
// grab magic on first folder, which is /data/app
if (!data_app_magic) {
if (S_MAGIC_COMPAT(file)) {
data_app_magic = S_MAGIC_COMPAT(file);
pr_info("%s: dir: %s got magic! 0x%lx\n", __func__, pos->dirpath, data_app_magic);
} else {
filp_close(file, NULL);
goto skip_iterate;
}
}
if (S_MAGIC_COMPAT(file) != data_app_magic) {
pr_info("%s: skip: %s magic: 0x%lx expected: 0x%lx\n", __func__, pos->dirpath,
S_MAGIC_COMPAT(file), data_app_magic);
filp_close(file, NULL);
goto skip_iterate;
}
iterate_dir(file, &ctx.ctx); iterate_dir(file, &ctx.ctx);
filp_close(file, NULL); filp_close(file, NULL);
@@ -286,13 +353,25 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)
void track_throne() void track_throne()
{ {
struct file *fp = struct file *fp;
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0); int tries = 0;
while (tries++ < 10) {
if (!is_lock_held(SYSTEM_PACKAGES_LIST_PATH)) {
fp = ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
if (!IS_ERR(fp))
break;
}
pr_info("%s: waiting for %s\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
msleep(100); // migth as well add a delay
};
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n", __func__, PTR_ERR(fp));
__func__, PTR_ERR(fp));
return; return;
} } else
pr_info("%s: %s found!\n", __func__, SYSTEM_PACKAGES_LIST_PATH);
struct list_head uid_list; struct list_head uid_list;
INIT_LIST_HEAD(&uid_list); INIT_LIST_HEAD(&uid_list);
@@ -361,12 +440,14 @@ void track_throne()
if (ksu_is_manager_uid_valid()) { if (ksu_is_manager_uid_valid()) {
pr_info("manager is uninstalled, invalidate it!\n"); pr_info("manager is uninstalled, invalidate it!\n");
ksu_invalidate_manager_uid(); ksu_invalidate_manager_uid();
goto prune;
} }
pr_info("Searching manager...\n"); pr_info("Searching manager...\n");
search_manager("/data/app", 2, &uid_list); search_manager("/data/app", 2, &uid_list);
pr_info("Search manager finished\n"); pr_info("Search manager finished\n");
} }
prune:
// then prune the allowlist // then prune the allowlist
ksu_prune_allowlist(is_uid_exist, &uid_list); ksu_prune_allowlist(is_uid_exist, &uid_list);
out: out:

View File

@@ -7,4 +7,6 @@ void ksu_throne_tracker_exit();
void track_throne(); void track_throne();
bool is_lock_held(const char *path);
#endif #endif

View File

@@ -34,7 +34,6 @@ android {
} }
buildFeatures { buildFeatures {
aidl = true
buildConfig = true buildConfig = true
compose = true compose = true
prefab = true prefab = true
@@ -133,4 +132,9 @@ dependencies {
implementation(libs.androidx.webkit) implementation(libs.androidx.webkit)
implementation(libs.lsposed.cxx) implementation(libs.lsposed.cxx)
implementation(libs.mmrl.platform)
compileOnly(libs.mmrl.hidden.api)
implementation(libs.mmrl.ui)
implementation(libs.mmrl.webui)
} }

View File

@@ -0,0 +1,47 @@
-verbose
-optimizationpasses 5
-dontwarn org.conscrypt.**
-dontwarn kotlinx.serialization.**
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn com.google.auto.service.AutoService
-dontwarn com.google.j2objc.annotations.RetainedWith
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.AnnotationMirror
-dontwarn javax.lang.model.element.AnnotationValue
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.ElementKind
-dontwarn javax.lang.model.element.ElementVisitor
-dontwarn javax.lang.model.element.ExecutableElement
-dontwarn javax.lang.model.element.Modifier
-dontwarn javax.lang.model.element.Name
-dontwarn javax.lang.model.element.PackageElement
-dontwarn javax.lang.model.element.TypeElement
-dontwarn javax.lang.model.element.TypeParameterElement
-dontwarn javax.lang.model.element.VariableElement
-dontwarn javax.lang.model.type.ArrayType
-dontwarn javax.lang.model.type.DeclaredType
-dontwarn javax.lang.model.type.ExecutableType
-dontwarn javax.lang.model.type.TypeKind
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVariable
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.util.AbstractAnnotationValueVisitor8
-dontwarn javax.lang.model.util.AbstractTypeVisitor8
-dontwarn javax.lang.model.util.ElementFilter
-dontwarn javax.lang.model.util.Elements
-dontwarn javax.lang.model.util.SimpleElementVisitor8
-dontwarn javax.lang.model.util.SimpleTypeVisitor7
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
-dontwarn javax.lang.model.util.Types
-dontwarn javax.tools.Diagnostic$Kind
# MMRL:webui reflection
-keep class com.dergoogler.mmrl.webui.model.ModId { *; }
-keep class com.dergoogler.mmrl.webui.interfaces.** { *; }
-keep class com.rifsxd.ksunext.ui.webui.WebViewInterface { *; }
-keep,allowobfuscation class * extends com.dergoogler.mmrl.platform.content.IService { *; }

View File

@@ -24,6 +24,15 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/zip" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:pathPattern=".*\\.zip" />
</intent-filter>
</activity> </activity>
<activity <activity
@@ -33,6 +42,13 @@
android:exported="false" android:exported="false"
android:theme="@style/Theme.KernelSU.WebUI" /> android:theme="@style/Theme.KernelSU.WebUI" />
<activity
android:name=".ui.webui.WebUIXActivity"
android:autoRemoveFromRecents="true"
android:documentLaunchMode="intoExisting"
android:exported="false"
android:theme="@style/Theme.KernelSU.WebUI" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider" android:authorities="${applicationId}.fileprovider"

View File

@@ -1,9 +0,0 @@
// IKsuInterface.aidl
package com.rifsxd.ksunext;
import android.content.pm.PackageInfo;
import rikka.parcelablelist.ParcelableListSlice;
interface IKsuInterface {
ParcelableListSlice<PackageInfo> getPackages(int flags);
}

View File

@@ -25,6 +25,13 @@ Java_com_rifsxd_ksunext_Natives_getVersion(JNIEnv *env, jobject) {
return get_version(); return get_version();
} }
extern "C"
JNIEXPORT jstring JNICALL
Java_com_rifsxd_ksunext_Natives_getHookMode(JNIEnv *env, jobject) {
const char* mode = get_hook_mode();
return env->NewStringUTF(mode);
}
extern "C" extern "C"
JNIEXPORT jintArray JNICALL JNIEXPORT jintArray JNICALL
Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) { Java_com_rifsxd_ksunext_Natives_getAllowList(JNIEnv *env, jobject) {

View File

@@ -29,6 +29,7 @@
#define CMD_IS_UID_SHOULD_UMOUNT 13 #define CMD_IS_UID_SHOULD_UMOUNT 13
#define CMD_IS_SU_ENABLED 14 #define CMD_IS_SU_ENABLED 14
#define CMD_ENABLE_SU 15 #define CMD_ENABLE_SU 15
#define CMD_HOOK_MODE 16
static bool ksuctl(int cmd, void* arg1, void* arg2) { static bool ksuctl(int cmd, void* arg1, void* arg2) {
int32_t result = 0; int32_t result = 0;
@@ -61,6 +62,12 @@ int get_version() {
return version; return version;
} }
const char* get_hook_mode() {
static char mode[16];
ksuctl(CMD_HOOK_MODE, mode, nullptr);
return mode;
}
bool get_allow_list(int *uids, int *size) { bool get_allow_list(int *uids, int *size) {
return ksuctl(CMD_GET_SU_LIST, uids, size); return ksuctl(CMD_GET_SU_LIST, uids, size);
} }

View File

@@ -11,6 +11,8 @@ bool become_manager(const char *);
int get_version(); int get_version();
const char* get_hook_mode();
bool get_allow_list(int *uids, int *size); bool get_allow_list(int *uids, int *size);
bool uid_should_umount(int uid); bool uid_should_umount(int uid);

View File

@@ -4,12 +4,17 @@ import android.app.Application
import android.system.Os import android.system.Os
import coil.Coil import coil.Coil
import coil.ImageLoader import coil.ImageLoader
import com.dergoogler.mmrl.platform.Platform
import me.zhanghai.android.appiconloader.coil.AppIconFetcher import me.zhanghai.android.appiconloader.coil.AppIconFetcher
import me.zhanghai.android.appiconloader.coil.AppIconKeyer import me.zhanghai.android.appiconloader.coil.AppIconKeyer
import okhttp3.Cache import okhttp3.Cache
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.io.File import java.io.File
import java.util.Locale import java.util.Locale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import com.rifsxd.ksunext.ui.webui.initPlatform
lateinit var ksuApp: KernelSUApplication lateinit var ksuApp: KernelSUApplication
@@ -21,6 +26,11 @@ class KernelSUApplication : Application() {
super.onCreate() super.onCreate()
ksuApp = this ksuApp = this
Platform.setHiddenApiExemptions()
// Pre-initialize WX Platform as early as possible
launchPlatformInit()
val context = this val context = this
val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size) val iconSize = resources.getDimensionPixelSize(android.R.dimen.app_icon_size)
Coil.setImageLoader( Coil.setImageLoader(
@@ -51,5 +61,11 @@ class KernelSUApplication : Application() {
}.build() }.build()
} }
private fun launchPlatformInit() {
// Use a coroutine to avoid blocking the main thread
GlobalScope.launch(Dispatchers.IO) {
initPlatform()
}
}
} }

View File

@@ -26,6 +26,19 @@ data class KernelVersion(val major: Int, val patchLevel: Int, val subLevel: Int)
return false return false
} }
fun isULegacy(): Boolean {
return major == 3
}
fun isLegacy(): Boolean {
return major == 4 && patchLevel in 1..18
}
fun isGKI1(): Boolean {
return (major == 4 && patchLevel >= 19) || (major == 5 && patchLevel < 10)
}
} }
fun parseKernelVersion(version: String): KernelVersion { fun parseKernelVersion(version: String): KernelVersion {

View File

@@ -24,6 +24,10 @@ object Natives {
// 12404: Support disable sucompat mode // 12404: Support disable sucompat mode
const val MINIMAL_SUPPORTED_SU_COMPAT = 12404 const val MINIMAL_SUPPORTED_SU_COMPAT = 12404
// 12569: support get hook mode
const val MINIMAL_SUPPORTED_HOOK_MODE = 12569
const val KERNEL_SU_DOMAIN = "u:r:su:s0" const val KERNEL_SU_DOMAIN = "u:r:su:s0"
const val ROOT_UID = 0 const val ROOT_UID = 0
@@ -50,6 +54,16 @@ object Natives {
external fun uidShouldUmount(uid: Int): Boolean external fun uidShouldUmount(uid: Int): Boolean
/**
* Get a string indicating the SU hook mode enabled in kernel.
* The return values are:
* - "Manual": Manual hooks was enabled.
* - "Kprobes": Kprobes hooks was enabled (CONFIG_KSU_KPROBES_HOOK).
*
* @return return hook mode, or null if unavailable.
*/
external fun getHookMode(): String?
/** /**
* Get the profile of the given package. * Get the profile of the given package.
* @param key usually the package name * @param key usually the package name

View File

@@ -1,77 +0,0 @@
package com.rifsxd.ksunext.ui;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import androidx.annotation.NonNull;
import com.topjohnwu.superuser.ipc.RootService;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import com.rifsxd.ksunext.IKsuInterface;
import rikka.parcelablelist.ParcelableListSlice;
/**
* @author weishu
* @date 2023/4/18.
*/
public class KsuService extends RootService {
private static final String TAG = "KsuService";
class Stub extends IKsuInterface.Stub {
@Override
public ParcelableListSlice<PackageInfo> getPackages(int flags) {
List<PackageInfo> list = getInstalledPackagesAll(flags);
Log.i(TAG, "getPackages: " + list.size());
return new ParcelableListSlice<>(list);
}
}
@Override
public IBinder onBind(@NonNull Intent intent) {
return new Stub();
}
List<Integer> getUserIds() {
List<Integer> result = new ArrayList<>();
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
List<UserHandle> userProfiles = um.getUserProfiles();
for (UserHandle userProfile : userProfiles) {
int userId = userProfile.hashCode();
result.add(userProfile.hashCode());
}
return result;
}
ArrayList<PackageInfo> getInstalledPackagesAll(int flags) {
ArrayList<PackageInfo> packages = new ArrayList<>();
for (Integer userId : getUserIds()) {
Log.i(TAG, "getInstalledPackagesAll: " + userId);
packages.addAll(getInstalledPackagesAsUser(flags, userId));
}
return packages;
}
List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
try {
PackageManager pm = getPackageManager();
Method getInstalledPackagesAsUser = pm.getClass().getDeclaredMethod("getInstalledPackagesAsUser", int.class, int.class);
return (List<PackageInfo>) getInstalledPackagesAsUser.invoke(pm, flags, userId);
} catch (Throwable e) {
Log.e(TAG, "err", e);
}
return new ArrayList<>();
}
}

View File

@@ -1,5 +1,8 @@
package com.rifsxd.ksunext.ui package com.rifsxd.ksunext.ui
import android.content.Intent
import android.net.Uri
import android.content.Context
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
@@ -21,6 +24,8 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union import androidx.compose.foundation.layout.union
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
@@ -29,11 +34,13 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavBackStackEntry import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
@@ -49,10 +56,13 @@ import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.ui.screen.BottomBarDestination import com.rifsxd.ksunext.ui.screen.BottomBarDestination
import com.rifsxd.ksunext.ui.theme.KernelSUTheme import com.rifsxd.ksunext.ui.theme.KernelSUTheme
import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.rootAvailable import com.rifsxd.ksunext.ui.util.rootAvailable
import com.rifsxd.ksunext.ui.util.install import com.rifsxd.ksunext.ui.util.install
import com.rifsxd.ksunext.ui.util.* import com.rifsxd.ksunext.ui.util.isSuCompatDisabled
import com.rifsxd.ksunext.ui.screen.FlashIt
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@@ -67,14 +77,62 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = Natives.becomeManager(ksuApp.packageName)
if (isManager) install() if (isManager) install()
val zipUri: Uri? = when (intent?.action) {
Intent.ACTION_VIEW, Intent.ACTION_SEND -> {
val uri = intent.data ?: intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
uri?.let {
val name = when (it.scheme) {
"file" -> it.lastPathSegment ?: ""
"content" -> {
contentResolver.query(it, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
if (cursor.moveToFirst() && nameIndex != -1) {
cursor.getString(nameIndex)
} else {
it.lastPathSegment ?: ""
}
} ?: (it.lastPathSegment ?: "")
}
else -> it.lastPathSegment ?: ""
}
if (name.lowercase().endsWith(".zip")) it else null
}
}
else -> null
}
setContent { setContent {
KernelSUTheme { // Read AMOLED mode preference
val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
val amoledMode = prefs.getBoolean("enable_amoled", false)
val moduleViewModel: ModuleViewModel = viewModel()
val moduleUpdateCount = moduleViewModel.moduleList.count {
moduleViewModel.checkUpdate(it).first.isNotEmpty()
}
KernelSUTheme (
amoledMode = amoledMode
) {
val navController = rememberNavController() val navController = rememberNavController()
val snackBarHostState = remember { SnackbarHostState() } val snackBarHostState = remember { SnackbarHostState() }
val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination val currentDestination = navController.currentBackStackEntryAsState()?.value?.destination
val navigator = navController.rememberDestinationsNavigator()
LaunchedEffect(zipUri) {
if (zipUri != null) {
navigator.navigate(
FlashScreenDestination(
FlashIt.FlashModules(listOf(zipUri)),
finishIntent = true
)
)
}
}
val showBottomBar = when (currentDestination?.route) { val showBottomBar = when (currentDestination?.route) {
FlashScreenDestination.route -> false // Hide for FlashScreenDestination FlashScreenDestination.route -> false // Hide for FlashScreenDestination
ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen ExecuteModuleActionScreenDestination.route -> false // Hide for ExecuteModuleActionScreen
@@ -88,7 +146,7 @@ class MainActivity : ComponentActivity() {
enter = slideInVertically(initialOffsetY = { it }) + fadeIn(), enter = slideInVertically(initialOffsetY = { it }) + fadeIn(),
exit = slideOutVertically(targetOffsetY = { it }) + fadeOut() exit = slideOutVertically(targetOffsetY = { it }) + fadeOut()
) { ) {
BottomBar(navController) BottomBar(navController, moduleUpdateCount)
} }
}, },
contentWindowInsets = WindowInsets(0, 0, 0, 0) contentWindowInsets = WindowInsets(0, 0, 0, 0)
@@ -115,43 +173,70 @@ class MainActivity : ComponentActivity() {
} }
@Composable @Composable
private fun BottomBar(navController: NavHostController) { private fun BottomBar(navController: NavHostController, moduleUpdateCount: Int) {
val navigator = navController.rememberDestinationsNavigator() val navigator = navController.rememberDestinationsNavigator()
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = Natives.becomeManager(ksuApp.packageName)
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable() val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
val suCompatDisabled = isSuCompatDisabled()
val suSFS = getSuSFS()
val susSUMode = susfsSUS_SU_Mode()
NavigationBar( NavigationBar(
tonalElevation = 8.dp, tonalElevation = 8.dp,
windowInsets = WindowInsets.systemBars.union(WindowInsets.displayCutout).only( windowInsets = WindowInsets.systemBars.union(WindowInsets.displayCutout).only(
WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom
) )
) { ) {
BottomBarDestination.entries.forEach { destination -> BottomBarDestination.entries
if (!fullFeatured && destination.rootRequired) return@forEach .filter {
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction) // Hide SuperUser and Module when su compat is disabled
NavigationBarItem( if (suCompatDisabled) {
selected = isCurrentDestOnBackStack, if (suSFS == "Supported" && susSUMode == "2") {
onClick = { true
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else { } else {
Icon(destination.iconNotSelected, stringResource(destination.label)) // hide SuperUser and Module
it != BottomBarDestination.SuperUser && it != BottomBarDestination.Module
} }
}, } else true
label = { Text(stringResource(destination.label)) }, }
alwaysShowLabel = true .forEach { destination ->
) if (!fullFeatured && destination.rootRequired) return@forEach
} val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
NavigationBarItem(
selected = isCurrentDestOnBackStack,
onClick = {
if (isCurrentDestOnBackStack) {
navigator.popBackStack(destination.direction, false)
}
navigator.navigate(destination.direction) {
popUpTo(NavGraphs.root) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {
// Show badge for Module icon if moduleUpdateCount > 0
if (destination == BottomBarDestination.Module && moduleUpdateCount > 0) {
BadgedBox(badge = { Badge { Text(moduleUpdateCount.toString()) } }) {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
}
} else {
if (isCurrentDestOnBackStack) {
Icon(destination.iconSelected, stringResource(destination.label))
} else {
Icon(destination.iconNotSelected, stringResource(destination.label))
}
}
},
label = { Text(stringResource(destination.label)) },
alwaysShowLabel = true
)
}
} }
} }

View File

@@ -5,14 +5,18 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import com.dergoogler.mmrl.ui.component.LabelItem
import com.dergoogler.mmrl.ui.component.text.TextRow
@Composable @Composable
fun SwitchItem( fun SwitchItem(
@@ -21,9 +25,11 @@ fun SwitchItem(
summary: String? = null, summary: String? = null,
checked: Boolean, checked: Boolean,
enabled: Boolean = true, enabled: Boolean = true,
onCheckedChange: (Boolean) -> Unit beta: Boolean = false,
onCheckedChange: (Boolean) -> Unit,
) { ) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
val stateAlpha = remember(checked, enabled) { Modifier.alpha(if (enabled) 1f else 0.5f) }
ListItem( ListItem(
modifier = Modifier modifier = Modifier
@@ -36,10 +42,30 @@ fun SwitchItem(
onValueChange = onCheckedChange onValueChange = onCheckedChange
), ),
headlineContent = { headlineContent = {
Text(title) TextRow(
leadingContent = if (beta) {
{
LabelItem(
modifier = Modifier.then(stateAlpha),
text = "Beta"
)
}
} else null
) {
Text(
modifier = Modifier.then(stateAlpha),
text = title,
)
}
}, },
leadingContent = icon?.let { leadingContent = icon?.let {
{ Icon(icon, title) } {
Icon(
modifier = Modifier.then(stateAlpha),
imageVector = icon,
contentDescription = title
)
}
}, },
trailingContent = { trailingContent = {
Switch( Switch(
@@ -51,7 +77,10 @@ fun SwitchItem(
}, },
supportingContent = { supportingContent = {
if (summary != null) { if (summary != null) {
Text(summary) Text(
modifier = Modifier.then(stateAlpha),
text = summary
)
} }
} }
) )

View File

@@ -56,6 +56,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.dropUnlessResumed import androidx.lifecycle.compose.dropUnlessResumed
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage import coil.compose.AsyncImage
import coil.request.ImageRequest import coil.request.ImageRequest
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
@@ -94,6 +95,7 @@ fun AppProfileScreen(
val snackBarHost = LocalSnackbarHost.current val snackBarHost = LocalSnackbarHost.current
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val viewModel: SuperUserViewModel = viewModel()
val failToUpdateAppProfile = stringResource(R.string.failed_to_update_app_profile).format(appInfo.label) val failToUpdateAppProfile = stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
val failToUpdateSepolicy = stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label) val failToUpdateSepolicy = stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
val suNotAllowed = stringResource(R.string.su_not_allowed).format(appInfo.label) val suNotAllowed = stringResource(R.string.su_not_allowed).format(appInfo.label)
@@ -160,6 +162,7 @@ fun AppProfileScreen(
snackBarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid)) snackBarHost.showSnackbar(failToUpdateAppProfile.format(appInfo.uid))
} else { } else {
profile = it profile = it
viewModel.updateAppProfile(packageName, it)
} }
} }
}, },

View File

@@ -1,15 +1,8 @@
package com.rifsxd.ksunext.ui.screen package com.rifsxd.ksunext.ui.screen
import android.content.Context import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.only
@@ -25,7 +18,6 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -37,54 +29,32 @@ import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import androidx.lifecycle.compose.dropUnlessResumed import androidx.lifecycle.compose.dropUnlessResumed
import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.IconSource
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.list.ListDialog
import com.maxkeppeler.sheets.list.models.ListOption
import com.maxkeppeler.sheets.list.models.ListSelection
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import com.rifsxd.ksunext.BuildConfig
import com.rifsxd.ksunext.Natives import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.R import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.AboutDialog
import com.rifsxd.ksunext.ui.component.ConfirmResult import com.rifsxd.ksunext.ui.component.ConfirmResult
import com.rifsxd.ksunext.ui.component.DialogHandle
import com.rifsxd.ksunext.ui.component.SwitchItem
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.rememberCustomDialog
import com.rifsxd.ksunext.ui.component.rememberLoadingDialog import com.rifsxd.ksunext.ui.component.rememberLoadingDialog
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.getBugreportFile
import com.rifsxd.ksunext.ui.util.* import com.rifsxd.ksunext.ui.util.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
/** /**
* @author rifsxd * @author rifsxd
@@ -195,9 +165,7 @@ fun BackupRestoreScreen(navigator: DestinationsNavigator) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var useOverlayFs by rememberSaveable { var useOverlayFs by rememberSaveable {
mutableStateOf( mutableStateOf(readMountSystemFile())
prefs.getBoolean("use_overlay_fs", false)
)
} }
val moduleRestore = stringResource(id = R.string.module_restore) val moduleRestore = stringResource(id = R.string.module_restore)

View File

@@ -0,0 +1,178 @@
package com.rifsxd.ksunext.ui.screen
import android.content.Context
import android.content.Intent
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.*
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.SwitchItem
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.*
/**
* @author rifsxd
* @date 2025/6/1.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun CustomizationScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
Scaffold(
topBar = {
TopBar(
onBack = dropUnlessResumed {
navigator.popBackStack()
},
scrollBehavior = scrollBehavior
)
},
snackbarHost = { SnackbarHost(snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var useBanner by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_banner", true)
)
}
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.ViewCarousel,
title = stringResource(id = R.string.settings_banner),
summary = stringResource(id = R.string.settings_banner_summary),
checked = useBanner
) {
prefs.edit().putBoolean("use_banner", it).apply()
useBanner = it
}
}
var enableAmoled by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_amoled", false)
)
}
var showRestartDialog by remember { mutableStateOf(false) }
if (isSystemInDarkTheme()) {
SwitchItem(
icon = Icons.Filled.Contrast,
title = stringResource(id = R.string.settings_amoled_mode),
summary = stringResource(id = R.string.settings_amoled_mode_summary),
checked = enableAmoled
) { checked ->
prefs.edit().putBoolean("enable_amoled", checked).apply()
enableAmoled = checked
showRestartDialog = true
}
if (showRestartDialog) {
AlertDialog(
onDismissRequest = { showRestartDialog = false },
title = { Text(stringResource(R.string.restart_required)) },
text = { Text(stringResource(R.string.restart_app_message)) },
confirmButton = {
TextButton(onClick = {
showRestartDialog = false
// Restart the app
val packageManager = context.packageManager
val intent = packageManager.getLaunchIntentForPackage(context.packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
Runtime.getRuntime().exit(0)
}) {
Text(stringResource(R.string.restart_app))
}
},
dismissButton = {
TextButton(onClick = { showRestartDialog = false }) {
Text(stringResource(R.string.later))
}
}
)
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
onBack: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.customization)) }, navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Preview
@Composable
private fun CustomizationPreview() {
CustomizationScreen(EmptyDestinationsNavigator)
}

View File

@@ -0,0 +1,185 @@
package com.rifsxd.ksunext.ui.screen
import android.content.Context
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.*
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.dergoogler.mmrl.platform.Platform
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.launch
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.SwitchItem
import com.rifsxd.ksunext.ui.util.LocalSnackbarHost
import com.rifsxd.ksunext.ui.util.*
/**
* @author rifsxd
* @date 2025/6/15.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>
@Composable
fun DeveloperScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
Scaffold(
topBar = {
TopBar(
onBack = { navigator.popBackStack() },
scrollBehavior = scrollBehavior
)
},
snackbarHost = { SnackbarHost(snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.verticalScroll(rememberScrollState())
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
// --- Developer Options Switch ---
var developerOptionsEnabled by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_developer_options", false)
)
}
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.DeveloperMode,
title = stringResource(id = R.string.enable_developer_options),
summary = stringResource(id = R.string.enable_developer_options_summary),
checked = developerOptionsEnabled
) {
prefs.edit().putBoolean("enable_developer_options", it).apply()
developerOptionsEnabled = it
}
}
var useWebUIX by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_webuix", true)
)
}
if (ksuVersion != null) {
SwitchItem(
beta = false,
enabled = Platform.isAlive && developerOptionsEnabled,
icon = Icons.Filled.WebAsset,
title = stringResource(id = R.string.use_webuix),
summary = stringResource(id = R.string.use_webuix_summary),
checked = useWebUIX
) {
prefs.edit().putBoolean("use_webuix", it).apply()
useWebUIX = it
}
}
var enableWebDebugging by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_web_debugging", false)
)
}
if (ksuVersion != null) {
SwitchItem(
enabled = developerOptionsEnabled,
icon = Icons.Filled.Web,
title = stringResource(id = R.string.enable_web_debugging),
summary = stringResource(id = R.string.enable_web_debugging_summary),
checked = enableWebDebugging
) {
prefs.edit().putBoolean("enable_web_debugging", it).apply()
enableWebDebugging = it
}
}
var useWebUIXEruda by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_webuix_eruda", false)
)
}
if (ksuVersion != null) {
SwitchItem(
beta = false,
enabled = Platform.isAlive && useWebUIX && enableWebDebugging,
icon = Icons.Filled.FormatListNumbered,
title = stringResource(id = R.string.use_webuix_eruda),
summary = stringResource(id = R.string.use_webuix_eruda_summary),
checked = useWebUIXEruda
) {
prefs.edit().putBoolean("use_webuix_eruda", it).apply()
useWebUIXEruda = it
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TopBar(
onBack: () -> Unit = {},
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.developer)) }, navigationIcon = {
IconButton(
onClick = onBack
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
},
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
scrollBehavior = scrollBehavior
)
}
@Preview
@Composable
private fun DeveloperPreview() {
DeveloperScreen(EmptyDestinationsNavigator)
}

View File

@@ -1,5 +1,6 @@
package com.rifsxd.ksunext.ui.screen package com.rifsxd.ksunext.ui.screen
import android.content.Context
import android.os.Environment import android.os.Environment
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -27,6 +28,7 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -34,8 +36,10 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.key
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -67,6 +71,19 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String
var actionResult: Boolean var actionResult: Boolean
var isActionRunning by rememberSaveable { mutableStateOf(true) } var isActionRunning by rememberSaveable { mutableStateOf(true) }
val context = LocalContext.current
// Read developer options from SharedPreferences
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
val view = LocalView.current
DisposableEffect(isActionRunning) {
view.keepScreenOn = isActionRunning
onDispose {
view.keepScreenOn = false
}
}
BackHandler(enabled = isActionRunning) { BackHandler(enabled = isActionRunning) {
// Disable back button if action is running // Disable back button if action is running
} }
@@ -148,7 +165,7 @@ fun ExecuteModuleActionScreen(navigator: DestinationsNavigator, moduleId: String
} }
Text( Text(
modifier = Modifier.padding(8.dp), modifier = Modifier.padding(8.dp),
text = text, text = if (developerOptionsEnabled) logContent.toString() else text,
fontSize = MaterialTheme.typography.bodySmall.fontSize, fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight, lineHeight = MaterialTheme.typography.bodySmall.lineHeight,

View File

@@ -1,5 +1,6 @@
package com.rifsxd.ksunext.ui.screen package com.rifsxd.ksunext.ui.screen
import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Environment import android.os.Environment
import android.os.Parcelable import android.os.Parcelable
@@ -33,6 +34,7 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -44,6 +46,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@@ -59,6 +63,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import com.rifsxd.ksunext.R import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.component.ConfirmResult
import com.rifsxd.ksunext.ui.component.KeyEventBlocker import com.rifsxd.ksunext.ui.component.KeyEventBlocker
import com.rifsxd.ksunext.ui.util.FlashResult import com.rifsxd.ksunext.ui.util.FlashResult
import com.rifsxd.ksunext.ui.util.LkmSelection import com.rifsxd.ksunext.ui.util.LkmSelection
@@ -73,12 +79,21 @@ import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import androidx.compose.ui.platform.LocalContext
import android.app.Activity
enum class FlashingStatus { enum class FlashingStatus {
FLASHING, FLASHING,
SUCCESS, SUCCESS,
FAILED FAILED
} }
fun Context.findActivity(): Activity? = when (this) {
is Activity -> this
is android.content.ContextWrapper -> baseContext.findActivity()
else -> null
}
// Lets you flash modules sequentially when mutiple zipUris are selected // Lets you flash modules sequentially when mutiple zipUris are selected
fun flashModulesSequentially( fun flashModulesSequentially(
uris: List<Uri>, uris: List<Uri>,
@@ -102,7 +117,11 @@ fun flashModulesSequentially(
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@Destination<RootGraph> @Destination<RootGraph>
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) { fun FlashScreen(
navigator: DestinationsNavigator,
flashIt: FlashIt,
finishIntent: Boolean = false
) {
var text by rememberSaveable { mutableStateOf("") } var text by rememberSaveable { mutableStateOf("") }
var tempText: String var tempText: String
@@ -117,16 +136,64 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
mutableStateOf(FlashingStatus.FLASHING) mutableStateOf(FlashingStatus.FLASHING)
} }
BackHandler(enabled = flashing == FlashingStatus.FLASHING) { val context = LocalContext.current
// Disable back button if flashing is running
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
val activity = context.findActivity()
val view = LocalView.current
DisposableEffect(flashing) {
view.keepScreenOn = flashing == FlashingStatus.FLASHING
onDispose {
view.keepScreenOn = false
}
} }
LaunchedEffect(Unit) { BackHandler(enabled = flashing != FlashingStatus.FLASHING) {
if (text.isNotEmpty()) { navigator.popBackStack()
return@LaunchedEffect if (finishIntent) activity?.finish()
}
val confirmDialog = rememberConfirmDialog()
var confirmed by rememberSaveable { mutableStateOf(flashIt !is FlashIt.FlashModules) }
var pendingFlashIt by rememberSaveable { mutableStateOf<FlashIt?>(null) }
var hasFlashed by rememberSaveable { mutableStateOf(false) }
LaunchedEffect(flashIt) {
if (flashIt is FlashIt.FlashModules && !confirmed) {
val uris = flashIt.uris
val moduleNames =
uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }
.joinToString("")
val confirmContent =
context.getString(R.string.module_install_prompt_with_name, moduleNames)
val confirmTitle = context.getString(R.string.module)
val result = confirmDialog.awaitConfirm(
title = confirmTitle,
content = confirmContent,
markdown = true
)
if (result == ConfirmResult.Confirmed) {
confirmed = true
pendingFlashIt = flashIt
} else {
// User cancelled, go back
navigator.popBackStack()
if (finishIntent) activity?.finish()
}
} else {
confirmed = true
pendingFlashIt = flashIt
} }
}
LaunchedEffect(confirmed, pendingFlashIt) {
if (!confirmed || pendingFlashIt == null || text.isNotEmpty() || hasFlashed) return@LaunchedEffect
hasFlashed = true
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
flashIt(flashIt, onStdout = { flashIt(pendingFlashIt!!, onStdout = {
tempText = "$it\n" tempText = "$it\n"
if (tempText.startsWith("")) { // clear command if (tempText.startsWith("")) { // clear command
text = tempText.substring(6) text = tempText.substring(6)
@@ -155,6 +222,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
flashing, flashing,
onBack = dropUnlessResumed { onBack = dropUnlessResumed {
navigator.popBackStack() navigator.popBackStack()
if (finishIntent) activity?.finish()
}, },
onSave = { onSave = {
scope.launch { scope.launch {
@@ -194,19 +262,49 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
icon = { Icon(Icons.Filled.Close, contentDescription = null) }, icon = { Icon(Icons.Filled.Close, contentDescription = null) },
onClick = { onClick = {
navigator.popBackStack() navigator.popBackStack()
if (finishIntent) activity?.finish()
} }
) )
} }
if (flashIt is FlashIt.FlashBoot && (flashing == FlashingStatus.SUCCESS || flashing == FlashingStatus.FAILED)) { if (flashIt is FlashIt.FlashBoot && (flashing == FlashingStatus.SUCCESS || flashing == FlashingStatus.FAILED)) {
// Close button for LKM flashing val isLocalPatch = flashIt.boot != null && !flashIt.ota
ExtendedFloatingActionButton( val isDirectOrOta = flashIt.boot == null || flashIt.ota
text = { Text(text = stringResource(R.string.close)) },
icon = { Icon(Icons.Filled.Close, contentDescription = null) }, if (flashing == FlashingStatus.FAILED) {
onClick = { // Always show close on failure
navigator.popBackStack() ExtendedFloatingActionButton(
text = { Text(text = stringResource(R.string.close)) },
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
onClick = {
navigator.popBackStack()
}
)
} else if (flashing == FlashingStatus.SUCCESS) {
if (isLocalPatch) {
// Local patching: show only Close
ExtendedFloatingActionButton(
text = { Text(text = stringResource(R.string.close)) },
icon = { Icon(Icons.Filled.Close, contentDescription = null) },
onClick = {
navigator.popBackStack()
}
)
} else if (isDirectOrOta) {
// Direct install or OTA inactive slot: show only Reboot
ExtendedFloatingActionButton(
onClick = {
scope.launch {
withContext(Dispatchers.IO) {
reboot()
}
}
},
icon = { Icon(Icons.Filled.Refresh, contentDescription = stringResource(R.string.reboot)) },
text = { Text(text = stringResource(R.string.reboot)) }
)
} }
) }
} }
}, },
contentWindowInsets = WindowInsets.safeDrawing, contentWindowInsets = WindowInsets.safeDrawing,
@@ -227,7 +325,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
} }
Text( Text(
modifier = Modifier.padding(8.dp), modifier = Modifier.padding(8.dp),
text = text, text = if (developerOptionsEnabled) logContent.toString() else text,
fontSize = MaterialTheme.typography.bodySmall.fontSize, fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight, lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
@@ -236,6 +334,19 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
} }
} }
fun Uri.getFileName(context: Context): String {
val contentResolver = context.contentResolver
val cursor = contentResolver.query(this, null, null, null, null)
return cursor?.use {
val nameIndex = it.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
if (it.moveToFirst() && nameIndex != -1) {
it.getString(nameIndex)
} else {
this.lastPathSegment ?: "unknown.zip"
}
} ?: (this.lastPathSegment ?: "unknown.zip")
}
@Parcelize @Parcelize
sealed class FlashIt : Parcelable { sealed class FlashIt : Parcelable {
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) : data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean) :

View File

@@ -6,9 +6,14 @@ import android.os.PowerManager
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.system.Os import android.system.Os
import android.widget.Toast
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@@ -29,9 +34,15 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.toUpperCase
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.pm.PackageInfoCompat import androidx.core.content.pm.PackageInfoCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import com.dergoogler.mmrl.ui.component.LabelItem
import com.dergoogler.mmrl.ui.component.LabelItemDefaults
import com.dergoogler.mmrl.ui.component.text.TextRow
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
@@ -43,6 +54,8 @@ import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ui.component.rememberConfirmDialog import com.rifsxd.ksunext.ui.component.rememberConfirmDialog
import com.rifsxd.ksunext.ui.util.* import com.rifsxd.ksunext.ui.util.*
import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo import com.rifsxd.ksunext.ui.util.module.LatestVersionInfo
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
import com.rifsxd.ksunext.ui.viewmodel.SuperUserViewModel
import java.util.* import java.util.*
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -55,6 +68,10 @@ fun HomeScreen(navigator: DestinationsNavigator) {
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null val ksuVersion = if (isManager) Natives.version else null
val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
Scaffold( Scaffold(
topBar = { topBar = {
TopBar( TopBar(
@@ -79,6 +96,20 @@ fun HomeScreen(navigator: DestinationsNavigator) {
val lkmMode = ksuVersion?.let { val lkmMode = ksuVersion?.let {
if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null if (it >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && kernelVersion.isGKI()) Natives.isLkmMode else null
} }
val superUserViewModel: SuperUserViewModel = viewModel()
val moduleViewModel: ModuleViewModel = viewModel()
LaunchedEffect(Unit) {
if (superUserViewModel.appList.isEmpty()) {
superUserViewModel.fetchAppList()
}
if (moduleViewModel.moduleList.isEmpty()) {
moduleViewModel.fetchModuleList()
}
}
StatusCard(kernelVersion, ksuVersion, lkmMode) { StatusCard(kernelVersion, ksuVersion, lkmMode) {
navigator.navigate(InstallScreenDestination) navigator.navigate(InstallScreenDestination)
@@ -97,12 +128,12 @@ fun HomeScreen(navigator: DestinationsNavigator) {
} }
val checkUpdate = val checkUpdate =
LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE) LocalContext.current.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("check_update", true) .getBoolean("check_update", false)
if (checkUpdate) { if (checkUpdate) {
UpdateCard() UpdateCard()
} }
//NextCard() //NextCard()
InfoCard() InfoCard(autoExpand = developerOptionsEnabled)
IssueReportCard() IssueReportCard()
//EXperimentalCard() //EXperimentalCard()
Spacer(Modifier) Spacer(Modifier)
@@ -162,6 +193,19 @@ fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
}) })
} }
@Composable
fun getSeasonalIcon(): ImageVector {
val month = Calendar.getInstance().get(Calendar.MONTH) // 0-11 for January-December
return when (month) {
Calendar.DECEMBER, Calendar.JANUARY, Calendar.FEBRUARY -> Icons.Filled.AcUnit // Winter
Calendar.MARCH, Calendar.APRIL, Calendar.MAY -> Icons.Filled.Spa // Spring
Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -> Icons.Filled.WbSunny // Summer
Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER -> Icons.Filled.Forest // Fall
else -> Icons.Filled.Whatshot // Fallback icon
}
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TopBar( private fun TopBar(
@@ -170,15 +214,51 @@ private fun TopBar(
onInstallClick: () -> Unit, onInstallClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null
) { ) {
var isSpinning by remember { mutableStateOf(false) }
val rotation by animateFloatAsState(
targetValue = if (isSpinning) 360f else 0f,
animationSpec = tween(durationMillis = 800),
finishedListener = {
isSpinning = false
}
)
LaunchedEffect(Unit) {
isSpinning = true
}
TopAppBar( TopAppBar(
title = { Text(stringResource(R.string.app_name)) }, title = {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {
if (!isSpinning) isSpinning = true
}
) {
Icon(
imageVector = getSeasonalIcon(),
contentDescription = null,
modifier = Modifier
.padding(end = 8.dp)
.graphicsLayer {
rotationZ = rotation
}
)
Text(stringResource(R.string.app_name))
}
},
actions = { actions = {
if (kernelVersion.isGKI()) { if (ksuVersion != null) {
IconButton(onClick = onInstallClick) { if (kernelVersion.isGKI()) {
Icon( IconButton(onClick = onInstallClick) {
imageVector = Icons.Filled.Archive, Icon(
contentDescription = stringResource(id = R.string.install) imageVector = Icons.Filled.Archive,
) contentDescription = stringResource(id = R.string.install)
)
}
} }
} }
@@ -188,7 +268,7 @@ private fun TopBar(
showDropdown = true showDropdown = true
}) { }) {
Icon( Icon(
imageVector = Icons.Filled.Refresh, imageVector = Icons.Filled.PowerSettingsNew,
contentDescription = stringResource(id = R.string.reboot) contentDescription = stringResource(id = R.string.reboot)
) )
@@ -197,7 +277,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")
@@ -215,93 +296,141 @@ private fun TopBar(
) )
} }
@Composable
fun getSeasonalIcon(): ImageVector {
val month = Calendar.getInstance().get(Calendar.MONTH) // 0-11 for January-December
return when (month) {
Calendar.DECEMBER, Calendar.JANUARY, Calendar.FEBRUARY -> Icons.Filled.AcUnit // Winter
Calendar.MARCH, Calendar.APRIL, Calendar.MAY -> Icons.Filled.Spa // Spring
Calendar.JUNE, Calendar.JULY, Calendar.AUGUST -> Icons.Filled.WbSunny // Summer
Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER -> Icons.Filled.Forest // Fall
else -> Icons.Filled.Whatshot // Fallback icon
}
}
@Composable @Composable
private fun StatusCard( private fun StatusCard(
kernelVersion: KernelVersion, kernelVersion: KernelVersion,
ksuVersion: Int?, ksuVersion: Int?,
lkmMode: Boolean?, lkmMode: Boolean?,
moduleUpdateCount: Int = 0,
onClickInstall: () -> Unit = {} onClickInstall: () -> Unit = {}
) { ) {
val context = LocalContext.current
var tapCount by remember { mutableStateOf(0) }
ElevatedCard( ElevatedCard(
colors = CardDefaults.elevatedCardColors(containerColor = run { colors = CardDefaults.elevatedCardColors(containerColor = run {
if (ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer if (ksuVersion != null) MaterialTheme.colorScheme.secondaryContainer
else MaterialTheme.colorScheme.errorContainer else MaterialTheme.colorScheme.errorContainer
}) })
) { ) {
Row(modifier = Modifier Row(
.fillMaxWidth() modifier = Modifier
.clickable { .fillMaxWidth()
if (kernelVersion.isGKI()) { .clickable {
onClickInstall() tapCount++
if (tapCount == 5) {
Toast.makeText(context, "What are you doing? 🤔", Toast.LENGTH_SHORT).show()
} else if (tapCount == 10) {
Toast.makeText(context, "Never gonna give you up! 💜", Toast.LENGTH_SHORT).show()
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
val intent = android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(url))
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
if (ksuVersion != null) {
context.startActivity(intent)
} else if (ksuVersion == null && kernelVersion.isGKI()) {
onClickInstall()
} else {
Toast.makeText(context, "Something weird happened... 🤔", Toast.LENGTH_SHORT).show()
}
} else if (ksuVersion == null && kernelVersion.isGKI()) {
onClickInstall()
}
} }
} .padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
when { when {
ksuVersion != null -> { ksuVersion != null -> {
val safeMode = when { val workingMode = when {
Natives.isSafeMode -> " [${stringResource(id = R.string.safe_mode)}]" lkmMode == true -> "LKM"
else -> "" lkmMode == false || kernelVersion.isGKI() -> "GKI2"
lkmMode == null && kernelVersion.isULegacy() -> "U-LEGACY"
lkmMode == null && kernelVersion.isLegacy() -> "LEGACY"
lkmMode == null && kernelVersion.isGKI1() -> "GKI1"
else -> "NON-STANDARD"
} }
val workingMode = when (lkmMode) {
null -> " <LTS>"
true -> " <LKM>"
else -> " <GKI>"
}
val workingText =
"${stringResource(id = R.string.home_working)}$workingMode$safeMode"
Icon( Icon(
getSeasonalIcon(), // Use dynamic seasonal icon imageVector = Icons.Filled.CheckCircle,
contentDescription = stringResource(R.string.home_working) contentDescription = stringResource(R.string.home_working)
) )
Column(Modifier.padding(start = 20.dp)) { Column(
Text( modifier = Modifier.padding(start = 20.dp),
text = workingText, verticalArrangement = Arrangement.spacedBy(4.dp)
style = MaterialTheme.typography.titleMedium ) {
) val labelStyle = LabelItemDefaults.style
Spacer(Modifier.height(4.dp)) TextRow(
trailingContent = {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
LabelItem(
icon = if (Natives.isSafeMode) {
{
Icon(
tint = labelStyle.contentColor,
imageVector = Icons.Filled.Security,
contentDescription = null
)
}
} else {
null
},
text = {
Text(
text = workingMode,
style = labelStyle.textStyle.copy(color = labelStyle.contentColor),
)
}
)
if (isSuCompatDisabled()) {
LabelItem(
icon = {
Icon(
tint = labelStyle.contentColor,
imageVector = Icons.Filled.Warning,
contentDescription = null
)
},
text = {
Text(
text = stringResource(R.string.sucompat_disabled),
style = labelStyle.textStyle.copy(
color = labelStyle.contentColor,
)
)
}
)
}
}
}
) {
Text(
text = stringResource(id = R.string.home_working),
style = MaterialTheme.typography.titleMedium
)
}
Text( Text(
text = stringResource(R.string.home_working_version, ksuVersion), text = stringResource(R.string.home_working_version, ksuVersion),
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium
) )
Spacer(Modifier.height(4.dp))
Text( Text(
text = stringResource( text = stringResource(
R.string.home_superuser_count, getSuperuserCount() R.string.home_superuser_count, getSuperuserCount()
), style = MaterialTheme.typography.bodyMedium ), style = MaterialTheme.typography.bodyMedium
) )
Spacer(Modifier.height(4.dp))
Text( Text(
text = stringResource(R.string.home_module_count, getModuleCount()), text = stringResource(R.string.home_module_count, getModuleCount()),
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium
) )
Spacer(Modifier.height(4.dp))
val suSFS = getSuSFS()
if (suSFS == "Supported") {
Text(
text = "SuSFS: " + stringResource(R.string.susfs_supported),
style = MaterialTheme.typography.bodyMedium
)
}
} }
} }
kernelVersion.isGKI() -> { kernelVersion.isGKI() -> {
Icon(Icons.Filled.AutoFixHigh, stringResource(R.string.home_not_installed)) Icon(Icons.Filled.NewReleases, stringResource(R.string.home_not_installed))
Column(Modifier.padding(start = 20.dp)) { Column(Modifier.padding(start = 20.dp)) {
Text( Text(
text = stringResource(R.string.home_not_installed), text = stringResource(R.string.home_not_installed),
@@ -316,7 +445,7 @@ private fun StatusCard(
} }
else -> { else -> {
Icon(Icons.Filled.Dangerous, stringResource(R.string.home_failure)) Icon(Icons.Filled.Cancel, stringResource(R.string.home_failure))
Column(Modifier.padding(start = 20.dp)) { Column(Modifier.padding(start = 20.dp)) {
Text( Text(
text = stringResource(R.string.home_failure), text = stringResource(R.string.home_failure),
@@ -357,21 +486,21 @@ fun WarningCard(
} }
@Composable @Composable
private fun InfoCard() { private fun InfoCard(autoExpand: Boolean = false) {
val context = LocalContext.current val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var useOverlayFs by rememberSaveable {
mutableStateOf(prefs.getBoolean("use_overlay_fs", false))
}
val isManager = Natives.becomeManager(ksuApp.packageName) val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null val ksuVersion = if (isManager) Natives.version else null
LaunchedEffect(Unit) { var expanded by rememberSaveable { mutableStateOf(false) }
useOverlayFs = prefs.getBoolean("use_overlay_fs", false)
} LaunchedEffect(autoExpand) {
if (autoExpand) {
expanded = true
}
}
ElevatedCard { ElevatedCard {
Column( Column(
@@ -379,9 +508,6 @@ private fun InfoCard() {
.fillMaxWidth() .fillMaxWidth()
.padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp) .padding(start = 24.dp, top = 24.dp, end = 24.dp, bottom = 16.dp)
) { ) {
val contents = StringBuilder()
val uname = Os.uname()
@Composable @Composable
fun InfoCardItem(label: String, content: String, icon: Any? = null) { fun InfoCardItem(label: String, content: String, icon: Any? = null) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
@@ -411,60 +537,103 @@ private fun InfoCard() {
) )
} }
} }
} }
Column {
InfoCardItem( val managerVersion = getManagerVersion(context)
label = stringResource(R.string.home_kernel),
content = uname.release,
icon = painterResource(R.drawable.ic_linux),
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_android),
content = "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})",
icon = Icons.Filled.Android,
)
Spacer(Modifier.height(16.dp))
val managerVersion = getManagerVersion(context)
InfoCardItem(
label = stringResource(R.string.home_manager_version),
content = "${managerVersion.first} (${managerVersion.second})",
icon = painterResource(R.drawable.ic_ksu_next),
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_selinux_status),
content = getSELinuxStatus(),
icon = Icons.Filled.Security,
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_mount_system),
content = currentMountSystem().ifEmpty { stringResource(R.string.unavailable) },
icon = Icons.Filled.SettingsSuggest,
)
val suSFS = getSuSFS()
if (suSFS == "Supported") {
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
val susSUMode = if (isSUS_SU) {
val mode = susfsSUS_SU_Mode()
val modeString = if (mode == "2") stringResource(R.string.enabled) else stringResource(R.string.disabled)
"| SuS SU: $modeString"
} else ""
Spacer(Modifier.height(16.dp))
InfoCardItem( InfoCardItem(
label = stringResource(R.string.home_susfs_version), label = stringResource(R.string.home_manager_version),
content = "${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode", content = "${managerVersion.first} (${managerVersion.second})",
icon = painterResource(R.drawable.ic_sus), icon = painterResource(R.drawable.ic_ksu_next),
) )
if (Natives.version >= Natives.MINIMAL_SUPPORTED_HOOK_MODE) {
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.hook_mode),
content = Natives.getHookMode() ?: stringResource(R.string.unavailable),
icon = Icons.Filled.Phishing,
)
}
if (ksuVersion != null) {
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_mount_system),
content = currentMountSystem().ifEmpty { stringResource(R.string.unavailable) },
icon = Icons.Filled.SettingsSuggest,
)
val suSFS = getSuSFS()
if (suSFS == "Supported") {
val isSUS_SU = getSuSFSFeatures() == "CONFIG_KSU_SUSFS_SUS_SU"
val susSUMode = if (isSUS_SU) {
val mode = susfsSUS_SU_Mode()
val modeString =
if (mode == "2") stringResource(R.string.enabled) else stringResource(R.string.disabled)
"| SuS SU: $modeString"
} else ""
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_susfs_version),
content = "${stringResource(R.string.susfs_supported)} | ${getSuSFSVersion()} (${getSuSFSVariant()}) $susSUMode",
icon = painterResource(R.drawable.ic_sus),
)
}
}
if (!expanded) {
Spacer(Modifier.height(12.dp))
Row(
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
IconButton(
onClick = { expanded = true },
modifier = Modifier.size(36.dp)
) {
Icon(
imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = "Show more"
)
}
}
}
AnimatedVisibility(visible = expanded) {
val uname = Os.uname()
Column {
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_kernel),
content = "${uname.release} (${uname.machine})",
icon = painterResource(R.drawable.ic_linux),
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_android),
content = "${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})",
icon = Icons.Filled.Android,
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_abi),
content = Build.SUPPORTED_ABIS.joinToString(", "),
icon = Icons.Filled.Memory,
)
Spacer(Modifier.height(16.dp))
InfoCardItem(
label = stringResource(R.string.home_selinux_status),
content = getSELinuxStatus(),
icon = Icons.Filled.Security,
)
}
}
} }
} }
} }
@@ -477,12 +646,13 @@ fun NextCard() {
ElevatedCard { ElevatedCard {
Row(modifier = Modifier Row(
.fillMaxWidth() modifier = Modifier
.clickable { .fillMaxWidth()
uriHandler.openUri(url) .clickable {
} uriHandler.openUri(url)
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) { }
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
Column { Column {
Text( Text(
text = stringResource(R.string.home_next_kernelsu), text = stringResource(R.string.home_next_kernelsu),
@@ -506,13 +676,15 @@ fun EXperimentalCard() {
ElevatedCard { ElevatedCard {
Row(modifier = Modifier Row(
.fillMaxWidth() modifier = Modifier
/*.clickable { .fillMaxWidth()
uriHandler.openUri(url) /*.clickable {
} uriHandler.openUri(url)
*/ }
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) { */
.padding(24.dp), verticalAlignment = Alignment.CenterVertically
) {
Column { Column {
Text( Text(
text = stringResource(R.string.home_experimental_kernelsu), text = stringResource(R.string.home_experimental_kernelsu),

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.FileUpload import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -30,6 +31,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
@@ -39,6 +41,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -77,6 +80,32 @@ import com.rifsxd.ksunext.ui.util.rootAvailable
@Destination<RootGraph> @Destination<RootGraph>
@Composable @Composable
fun InstallScreen(navigator: DestinationsNavigator) { fun InstallScreen(navigator: DestinationsNavigator) {
var showLkmWarning by rememberSaveable { mutableStateOf(true) }
if (showLkmWarning) {
AlertDialog(
onDismissRequest = {
showLkmWarning = false
navigator.popBackStack()
},
title = { Text(stringResource(R.string.warning)) },
text = { Text(stringResource(R.string.lkm_warning_message)) },
confirmButton = {
TextButton(onClick = { showLkmWarning = false }) {
Text(stringResource(R.string.proceed))
}
},
dismissButton = {
TextButton(onClick = {
showLkmWarning = false
navigator.popBackStack()
}) {
Text(stringResource(R.string.cancel))
}
}
)
}
var installMethod by remember { var installMethod by remember {
mutableStateOf<InstallMethod?>(null) mutableStateOf<InstallMethod?>(null)
} }

View File

@@ -1,5 +1,6 @@
package com.rifsxd.ksunext.ui.screen package com.rifsxd.ksunext.ui.screen
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -8,7 +9,14 @@ import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.LocalIndication import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -20,6 +28,7 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.only
@@ -29,6 +38,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Wysiwyg import androidx.compose.material.icons.automirrored.outlined.Wysiwyg
import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.filled.*
@@ -67,6 +77,10 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -75,12 +89,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.dergoogler.mmrl.platform.Platform
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination import com.ramcosta.composedestinations.generated.destinations.ExecuteModuleActionScreenDestination
@@ -90,6 +105,8 @@ import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.rifsxd.ksunext.Natives import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.R import com.rifsxd.ksunext.R
import com.rifsxd.ksunext.ksuApp import com.rifsxd.ksunext.ksuApp
@@ -108,6 +125,9 @@ import com.rifsxd.ksunext.ui.util.uninstallModule
import com.rifsxd.ksunext.ui.util.restoreModule import com.rifsxd.ksunext.ui.util.restoreModule
import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel import com.rifsxd.ksunext.ui.viewmodel.ModuleViewModel
import com.rifsxd.ksunext.ui.webui.WebUIActivity import com.rifsxd.ksunext.ui.webui.WebUIActivity
import com.rifsxd.ksunext.ui.webui.WebUIXActivity
import com.dergoogler.mmrl.ui.component.LabelItem
import com.topjohnwu.superuser.io.SuFile
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph> @Destination<RootGraph>
@@ -120,9 +140,11 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
viewModel.sortAToZ = prefs.getBoolean("module_sort_a_to_z", true)
viewModel.sortZToA = prefs.getBoolean("module_sort_z_to_a", false)
viewModel.sortSizeLowToHigh = prefs.getBoolean("module_sort_size_low_to_high", false)
viewModel.sortSizeHighToLow = prefs.getBoolean("module_sort_size_high_to_low", false)
if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) { if (viewModel.moduleList.isEmpty() || viewModel.isNeedRefresh) {
viewModel.sortAToZ = prefs.getBoolean("module_sort_a_to_z", true)
viewModel.sortZToA = prefs.getBoolean("module_sort_z_to_a", false)
viewModel.fetchModuleList() viewModel.fetchModuleList()
} }
} }
@@ -175,9 +197,13 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
onClick = { onClick = {
viewModel.sortAToZ = !viewModel.sortAToZ viewModel.sortAToZ = !viewModel.sortAToZ
viewModel.sortZToA = false viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
prefs.edit() prefs.edit()
.putBoolean("module_sort_a_to_z", viewModel.sortAToZ) .putBoolean("module_sort_a_to_z", viewModel.sortAToZ)
.putBoolean("module_sort_z_to_a", false) .putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.apply() .apply()
scope.launch { scope.launch {
viewModel.fetchModuleList() viewModel.fetchModuleList()
@@ -195,9 +221,61 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
onClick = { onClick = {
viewModel.sortZToA = !viewModel.sortZToA viewModel.sortZToA = !viewModel.sortZToA
viewModel.sortAToZ = false viewModel.sortAToZ = false
viewModel.sortSizeLowToHigh = false
viewModel.sortSizeHighToLow = false
prefs.edit() prefs.edit()
.putBoolean("module_sort_z_to_a", viewModel.sortZToA) .putBoolean("module_sort_z_to_a", viewModel.sortZToA)
.putBoolean("module_sort_a_to_z", false) .putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_size_low_to_high", false)
.putBoolean("module_sort_size_high_to_low", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_size_low_to_high))
},
trailingIcon = {
Checkbox(checked = viewModel.sortSizeLowToHigh, onCheckedChange = null)
},
onClick = {
viewModel.sortSizeLowToHigh = !viewModel.sortSizeLowToHigh
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeHighToLow = false
prefs.edit()
.putBoolean("module_sort_size_low_to_high", viewModel.sortSizeLowToHigh)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_high_to_low", false)
.apply()
scope.launch {
viewModel.fetchModuleList()
}
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.module_size_high_to_low))
},
trailingIcon = {
Checkbox(checked = viewModel.sortSizeHighToLow, onCheckedChange = null)
},
onClick = {
viewModel.sortSizeHighToLow = !viewModel.sortSizeHighToLow
viewModel.sortAToZ = false
viewModel.sortZToA = false
viewModel.sortSizeLowToHigh = false
prefs.edit()
.putBoolean("module_sort_size_high_to_low", viewModel.sortSizeHighToLow)
.putBoolean("module_sort_a_to_z", false)
.putBoolean("module_sort_z_to_a", false)
.putBoolean("module_sort_size_low_to_high", false)
.apply() .apply()
scope.launch { scope.launch {
viewModel.fetchModuleList() viewModel.fetchModuleList()
@@ -213,12 +291,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
floatingActionButton = { floatingActionButton = {
if (!hideInstallButton) { if (!hideInstallButton) {
val moduleInstall = stringResource(id = R.string.module_install) val moduleInstall = stringResource(id = R.string.module_install)
val confirmTitle = stringResource(R.string.module)
var zipUris by remember { mutableStateOf<List<Uri>>(emptyList()) }
val confirmDialog = rememberConfirmDialog(onConfirm = {
navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(zipUris)))
viewModel.markNeedRefresh()
})
val selectZipLauncher = rememberLauncherForActivityResult( val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult() contract = ActivityResultContracts.StartActivityForResult()
) { result -> ) { result ->
@@ -237,16 +309,13 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
data.data?.let { uris.add(it) } data.data?.let { uris.add(it) }
} }
// Show confirm dialog with selected zip file(s) name(s) if (uris.isEmpty()) return@rememberLauncherForActivityResult
val moduleNames = uris.mapIndexed { index, uri -> "\n${index + 1}. ${uri.getFileName(context)}" }.joinToString("")
val confirmContent = context.getString(R.string.module_install_prompt_with_name, moduleNames) viewModel.updateZipUris(uris)
zipUris = uris
confirmDialog.showConfirm( navigator.navigate(FlashScreenDestination(FlashIt.FlashModules(uris)))
title = confirmTitle, viewModel.clearZipUris()
content = confirmContent, viewModel.markNeedRefresh()
markdown = true
)
} }
ExtendedFloatingActionButton( ExtendedFloatingActionButton(
@@ -281,6 +350,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
) )
} }
} }
else -> { else -> {
ModuleList( ModuleList(
navigator, navigator,
@@ -292,11 +362,22 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
}, },
onClickModule = { id, name, hasWebUi -> onClickModule = { id, name, hasWebUi ->
if (hasWebUi) { if (hasWebUi) {
val wxEngine = Intent(context, WebUIXActivity::class.java)
.setData("kernelsu://webuix/$id".toUri())
.putExtra("id", id)
.putExtra("name", name)
val ksuEngine = Intent(context, WebUIActivity::class.java)
.setData("kernelsu://webui/$id".toUri())
.putExtra("id", id)
.putExtra("name", name)
webUILauncher.launch( webUILauncher.launch(
Intent(context, WebUIActivity::class.java) if (prefs.getBoolean("use_webuix", true) && Platform.isAlive) {
.setData(Uri.parse("kernelsu://webui/$id")) wxEngine
.putExtra("id", id) } else {
.putExtra("name", name) ksuEngine
}
) )
} }
}, },
@@ -318,7 +399,7 @@ private fun ModuleList(
onInstallModule: (Uri) -> Unit, onInstallModule: (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,
) { ) {
val failedEnable = stringResource(R.string.module_failed_to_enable) val failedEnable = stringResource(R.string.module_failed_to_enable)
val failedDisable = stringResource(R.string.module_failed_to_disable) val failedDisable = stringResource(R.string.module_failed_to_disable)
@@ -342,22 +423,19 @@ private fun ModuleList(
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val hasShownWarning = rememberSaveable { mutableStateOf(prefs.getBoolean("has_shown_warning", false)) } val hasShownWarning =
rememberSaveable { mutableStateOf(prefs.getBoolean("has_shown_warning", false)) }
var useOverlayFs by rememberSaveable {
mutableStateOf(
prefs.getBoolean("use_overlay_fs", false)
)
}
val loadingDialog = rememberLoadingDialog() val loadingDialog = rememberLoadingDialog()
val confirmDialog = rememberConfirmDialog() val confirmDialog = rememberConfirmDialog()
var expandedModuleId by rememberSaveable { mutableStateOf<String?>(null) }
suspend fun onModuleUpdate( suspend fun onModuleUpdate(
module: ModuleViewModel.ModuleInfo, module: ModuleViewModel.ModuleInfo,
changelogUrl: String, changelogUrl: String,
downloadUrl: String, downloadUrl: String,
fileName: String fileName: String,
) { ) {
val changelogResult = loadingDialog.withLoading { val changelogResult = loadingDialog.withLoading {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
@@ -504,20 +582,6 @@ private fun ModuleList(
}, },
) { ) {
when { when {
useOverlayFs && !viewModel.isOverlayAvailable -> {
item {
Box(
modifier = Modifier.fillParentMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = stringResource(R.string.module_overlay_fs_not_available),
textAlign = TextAlign.Center
)
}
}
}
viewModel.moduleList.isEmpty() -> { viewModel.moduleList.isEmpty() -> {
item { item {
Box( Box(
@@ -535,9 +599,9 @@ private fun ModuleList(
else -> { else -> {
items(viewModel.moduleList) { module -> items(viewModel.moduleList) { module ->
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val updatedModule by produceState(initialValue = Triple("", "", "")) { val updatedModule by produceState(key1 = module.id, initialValue = Triple("", "", "")) {
scope.launch(Dispatchers.IO) { value = withContext(Dispatchers.IO) {
value = viewModel.checkUpdate(module) viewModel.checkUpdate(module)
} }
} }
@@ -570,7 +634,8 @@ private fun ModuleList(
reboot() reboot()
} }
} else { } else {
val message = if (module.enabled) failedDisable else failedEnable val message =
if (module.enabled) failedDisable else failedEnable
snackBarHost.showSnackbar(message.format(module.name)) snackBarHost.showSnackbar(message.format(module.name))
} }
} }
@@ -583,10 +648,15 @@ private fun ModuleList(
updatedModule.first, updatedModule.first,
"${module.name}-${updatedModule.second}.zip" "${module.name}-${updatedModule.second}.zip"
) )
viewModel.markNeedRefresh()
} }
}, },
onClick = { onClick = {
onClickModule(it.dirId, it.name, it.hasWebUi) onClickModule(it.dirId, it.name, it.hasWebUi)
},
expanded = expandedModuleId == module.id,
onExpandToggle = {
expandedModuleId = if (expandedModuleId == module.id) null else module.id
} }
) )
@@ -611,265 +681,425 @@ fun ModuleItem(
onRestore: (ModuleViewModel.ModuleInfo) -> Unit, onRestore: (ModuleViewModel.ModuleInfo) -> Unit,
onCheckChanged: (Boolean) -> Unit, onCheckChanged: (Boolean) -> Unit,
onUpdate: (ModuleViewModel.ModuleInfo) -> Unit, onUpdate: (ModuleViewModel.ModuleInfo) -> Unit,
onClick: (ModuleViewModel.ModuleInfo) -> Unit onClick: (ModuleViewModel.ModuleInfo) -> Unit,
expanded: Boolean,
onExpandToggle: () -> Unit,
) { ) {
val viewModel = viewModel<ModuleViewModel>()
ElevatedCard( ElevatedCard(
modifier = Modifier.fillMaxWidth() modifier = Modifier
) { .fillMaxWidth()
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough .clip(MaterialTheme.shapes.medium)
val interactionSource = remember { MutableInteractionSource() } .clickable(
val indication = LocalIndication.current onClick = onExpandToggle
val viewModel = viewModel<ModuleViewModel>()
val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
var developerOptionsEnabled by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_developer_options", false)
) )
} ) {
Box(
LaunchedEffect(Unit) {
developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
}
Column(
modifier = Modifier modifier = Modifier
.padding(22.dp, 18.dp, 22.dp, 12.dp) .fillMaxWidth()
) { ) {
Row( val context = LocalContext.current
modifier = Modifier.fillMaxWidth(), val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
horizontalArrangement = Arrangement.SpaceBetween,
) { val useBanner = prefs.getBoolean("use_banner", true)
val moduleVersion = stringResource(id = R.string.module_version)
val moduleAuthor = stringResource(id = R.string.module_author) if (useBanner && module.banner.isNotEmpty()) {
val moduleId = stringResource(id = R.string.module_id) val isDark = isSystemInDarkTheme()
val moduleVersionCode = stringResource(id = R.string.module_version_code) val colorScheme = MaterialTheme.colorScheme
val moduleUpdateJson = stringResource(id = R.string.module_update_json) val context = LocalContext.current
val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty) val amoledMode = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
.getBoolean("amoled_mode", false)
val isDynamic = colorScheme.primary != colorScheme.secondary
val fadeColor = when {
amoledMode && isDark -> Color.Black
isDynamic -> colorScheme.surface
isDark -> Color(0xFF222222)
else -> Color.White
}
Box(
modifier = Modifier
.matchParentSize(),
contentAlignment = Alignment.Center
) {
if (module.banner.startsWith("https", true) || module.banner.startsWith("http", true)) {
AsyncImage(
model = module.banner,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
contentScale = ContentScale.Crop,
alpha = 0.18f
)
} else {
val bannerData = remember(module.banner) {
try {
val file = SuFile("/data/adb/modules/${module.id}/${module.banner}")
file.newInputStream().use { it.readBytes() }
} catch (e: Exception) {
null
}
}
if (bannerData != null) {
AsyncImage(
model = ImageRequest.Builder(context)
.data(bannerData)
.build(),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
contentScale = ContentScale.Crop,
alpha = 0.18f
)
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.background(
Brush.verticalGradient(
colors = listOf(
fadeColor.copy(alpha = 0.0f),
fadeColor.copy(alpha = 0.8f)
),
startY = 0f,
endY = Float.POSITIVE_INFINITY
)
)
)
}
}
Column {
val interactionSource = remember { MutableInteractionSource() }
var developerOptionsEnabled by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_developer_options", false)
)
}
LaunchedEffect(Unit) {
developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false)
}
Column( Column(
modifier = Modifier.fillMaxWidth(0.8f) modifier = Modifier
.padding(22.dp, 18.dp, 22.dp, 12.dp)
) { ) {
Text( Row(
text = module.name, modifier = Modifier.fillMaxWidth(),
fontSize = MaterialTheme.typography.titleMedium.fontSize, horizontalArrangement = Arrangement.SpaceBetween,
fontWeight = FontWeight.SemiBold, ) {
lineHeight = MaterialTheme.typography.bodySmall.lineHeight, val moduleVersion = stringResource(id = R.string.module_version)
fontFamily = MaterialTheme.typography.titleMedium.fontFamily, val moduleAuthor = stringResource(id = R.string.module_author)
textDecoration = textDecoration, val moduleId = stringResource(id = R.string.module_id)
) val moduleVersionCode = stringResource(id = R.string.module_version_code)
val moduleUpdateJson = stringResource(id = R.string.module_update_json)
val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty)
Column(
modifier = Modifier.fillMaxWidth(0.8f)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp)
) {
LabelItem(
text = formatSize(module.size),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
)
)
if (module.remove) {
LabelItem(
text = stringResource(R.string.uninstall),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.onErrorContainer
)
)
}
if (updateUrl.isNotEmpty() && !module.remove && !module.update) {
LabelItem(
text = stringResource(R.string.module_update),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
)
)
}
if (!module.remove) {
if (module.update) {
LabelItem(
text = stringResource(R.string.module_updated),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer
)
)
}
}
if (module.enabled && !module.remove) {
if (module.hasWebUi) {
LabelItem(
text = stringResource(R.string.webui),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
)
)
}
if (module.hasActionScript) {
LabelItem(
text = stringResource(R.string.action),
style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
)
)
}
}
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = module.name,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontWeight = FontWeight.SemiBold,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.titleMedium.fontFamily
)
Text(
text = "$moduleVersion: ${module.version}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
)
Text(
text = "$moduleAuthor: ${module.author}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
)
if (developerOptionsEnabled) {
Text(
text = "$moduleId: ${module.id}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
)
Text(
text = "$moduleVersionCode: ${module.versionCode}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
)
Text(
text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily
)
}
}
Spacer(modifier = Modifier.weight(1f))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
) {
Switch(
enabled = !module.update,
checked = module.enabled,
onCheckedChange = onCheckChanged,
interactionSource = if (!module.hasWebUi) interactionSource else null
)
}
}
Spacer(modifier = Modifier.height(12.dp))
Text( Text(
text = "$moduleVersion: ${module.version}", text = module.description,
fontSize = MaterialTheme.typography.bodySmall.fontSize, fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily, fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
Text(
text = "$moduleAuthor: ${module.author}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight, lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily, fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
textDecoration = textDecoration overflow = TextOverflow.Ellipsis,
maxLines = 4
) )
if (developerOptionsEnabled) { Spacer(modifier = Modifier.height(2.dp))
Text( if (expanded) {
text = "$moduleId: ${module.id}", Spacer(modifier = Modifier.height(10.dp))
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
Text(
text = "$moduleVersionCode: ${module.versionCode}",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
Text(
text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty",
fontSize = MaterialTheme.typography.bodySmall.fontSize,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
textDecoration = textDecoration
)
} }
}
Spacer(modifier = Modifier.weight(1f)) AnimatedVisibility(
visible = expanded,
Row( enter = fadeIn() + expandVertically(),
modifier = Modifier.fillMaxWidth(), exit = shrinkVertically() + fadeOut()
horizontalArrangement = Arrangement.End,
) {
Switch(
enabled = !module.update,
checked = module.enabled,
onCheckedChange = onCheckChanged,
interactionSource = if (!module.hasWebUi) interactionSource else null
)
}
}
Spacer(modifier = Modifier.height(12.dp))
Text(
text = module.description,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
lineHeight = MaterialTheme.typography.bodySmall.lineHeight,
fontWeight = MaterialTheme.typography.bodySmall.fontWeight,
overflow = TextOverflow.Ellipsis,
maxLines = 4,
textDecoration = textDecoration
)
Spacer(modifier = Modifier.height(16.dp))
HorizontalDivider(thickness = Dp.Hairline)
Spacer(modifier = Modifier.height(4.dp))
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
if (module.hasActionScript) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove && module.enabled,
onClick = {
navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId))
viewModel.markNeedRefresh()
},
contentPadding = ButtonDefaults.TextButtonContentPadding
) { ) {
Icon( Row(
modifier = Modifier.size(20.dp), horizontalArrangement = Arrangement.SpaceBetween,
imageVector = Icons.Outlined.PlayArrow, verticalAlignment = Alignment.CenterVertically
contentDescription = null ) {
) if (module.hasActionScript) {
if (!module.hasWebUi && updateUrl.isEmpty()) { FilledTonalButton(
Text( modifier = Modifier.defaultMinSize(52.dp, 32.dp),
modifier = Modifier.padding(start = 7.dp), enabled = !module.remove && module.enabled,
text = stringResource(R.string.action), onClick = {
fontFamily = MaterialTheme.typography.labelMedium.fontFamily, navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId))
fontSize = MaterialTheme.typography.labelMedium.fontSize viewModel.markNeedRefresh()
) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Terminal,
contentDescription = null
)
if (!module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
text = stringResource(R.string.action),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.hasWebUi) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove && module.enabled,
onClick = { onClick(module) },
interactionSource = interactionSource,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentDescription = null
)
if (!module.hasActionScript && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
}
Spacer(modifier = Modifier.weight(1f, true))
if (updateUrl.isNotEmpty() && !module.remove && !module.update) {
Button(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove,
onClick = { onUpdate(module) },
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.module_update)
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.remove) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onRestore(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Restore,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.restore)
)
}
}
} else {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = true,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.uninstall)
)
}
}
}
} }
} }
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.hasWebUi) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove && module.enabled,
onClick = { onClick(module) },
interactionSource = interactionSource,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.AutoMirrored.Outlined.Wysiwyg,
contentDescription = null
)
if (!module.hasActionScript && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.open)
)
}
}
}
Spacer(modifier = Modifier.weight(1f, true))
if (updateUrl.isNotEmpty()) {
Button(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = !module.remove,
onClick = { onUpdate(module) },
shape = ButtonDefaults.textShape,
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Download,
contentDescription = null
)
if (!module.hasActionScript || !module.hasWebUi) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.module_update)
)
}
}
Spacer(modifier = Modifier.weight(0.1f, true))
}
if (module.remove) {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
onClick = { onRestore(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Restore,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.restore)
)
}
}
} else {
FilledTonalButton(
modifier = Modifier.defaultMinSize(52.dp, 32.dp),
enabled = true,
onClick = { onUninstall(module) },
contentPadding = ButtonDefaults.TextButtonContentPadding
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) {
Text(
modifier = Modifier.padding(start = 7.dp),
fontFamily = MaterialTheme.typography.labelMedium.fontFamily,
fontSize = MaterialTheme.typography.labelMedium.fontSize,
text = stringResource(R.string.uninstall)
)
}
}
} }
} }
} }
} }
} }
fun formatSize(size: Long): String {
val kb = 1024
val mb = kb * 1024
val gb = mb * 1024
return when {
size >= gb -> String.format("%.2f GB", size.toDouble() / gb)
size >= mb -> String.format("%.2f MB", size.toDouble() / mb)
size >= kb -> String.format("%.2f KB", size.toDouble() / kb)
else -> "$size B"
}
}
@Preview @Preview
@Composable @Composable
fun ModuleItemPreview() { fun ModuleItemPreview() {
@@ -886,7 +1116,9 @@ fun ModuleItemPreview() {
updateJson = "", updateJson = "",
hasWebUi = false, hasWebUi = false,
hasActionScript = false, hasActionScript = false,
dirId = "dirId" dirId = "dirId",
size = 12345678L,
banner = ""
) )
ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}) ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}, false, {})
} }

View File

@@ -7,6 +7,7 @@ import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@@ -53,6 +54,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import com.dergoogler.mmrl.platform.Platform
import com.maxkeppeker.sheets.core.models.base.Header import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.IconSource import com.maxkeppeker.sheets.core.models.base.IconSource
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
@@ -64,6 +66,8 @@ import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
import com.ramcosta.composedestinations.generated.destinations.BackupRestoreScreenDestination import com.ramcosta.composedestinations.generated.destinations.BackupRestoreScreenDestination
import com.ramcosta.composedestinations.generated.destinations.CustomizationScreenDestination
import com.ramcosta.composedestinations.generated.destinations.DeveloperScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -162,7 +166,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
title = stringResource(id = R.string.settings_umount_modules_default), title = stringResource(id = R.string.settings_umount_modules_default),
summary = stringResource(id = R.string.settings_umount_modules_default_summary), summary = stringResource(id = R.string.settings_umount_modules_default_summary),
checked = umountChecked checked = umountChecked
) { ) {
if (Natives.setDefaultUmountModules(it)) { if (Natives.setDefaultUmountModules(it)) {
umountChecked = it umountChecked = it
@@ -221,14 +225,18 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
var useOverlayFs by rememberSaveable { var useOverlayFs by rememberSaveable {
mutableStateOf( mutableStateOf(readMountSystemFile())
prefs.getBoolean("use_overlay_fs", false) }
)
LaunchedEffect(Unit) {
useOverlayFs = readMountSystemFile()
} }
var showRebootDialog by remember { mutableStateOf(false) } var showRebootDialog by remember { mutableStateOf(false) }
if (ksuVersion != null) { val isOverlayAvailable = overlayFsAvailable()
if (ksuVersion != null && isOverlayAvailable) {
SwitchItem( SwitchItem(
icon = Icons.Filled.Build, icon = Icons.Filled.Build,
title = stringResource(id = R.string.use_overlay_fs), title = stringResource(id = R.string.use_overlay_fs),
@@ -239,8 +247,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
useOverlayFs = it useOverlayFs = it
if (useOverlayFs) { if (useOverlayFs) {
moduleBackup() moduleBackup()
updateMountSystemFile(true)
} else { } else {
moduleMigration() moduleMigration()
updateMountSystemFile(false)
} }
if (isManager) install() if (isManager) install()
showRebootDialog = true showRebootDialog = true
@@ -271,7 +281,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
var checkUpdate by rememberSaveable { var checkUpdate by rememberSaveable {
mutableStateOf( mutableStateOf(
prefs.getBoolean("check_update", true) prefs.getBoolean("check_update", false)
) )
} }
SwitchItem( SwitchItem(
@@ -284,58 +294,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
checkUpdate = it checkUpdate = it
} }
var enableWebDebugging by rememberSaveable { if (isOverlayAvailable && useOverlayFs) {
mutableStateOf(
prefs.getBoolean("enable_web_debugging", false)
)
}
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.Web,
title = stringResource(id = R.string.enable_web_debugging),
summary = stringResource(id = R.string.enable_web_debugging_summary),
checked = enableWebDebugging
) {
prefs.edit().putBoolean("enable_web_debugging", it).apply()
enableWebDebugging = it
}
}
var developerOptionsEnabled by rememberSaveable {
mutableStateOf(
prefs.getBoolean("enable_developer_options", false)
)
}
if (ksuVersion != null) {
SwitchItem(
icon = Icons.Filled.DeveloperMode,
title = stringResource(id = R.string.enable_developer_options),
summary = stringResource(id = R.string.enable_developer_options_summary),
checked = developerOptionsEnabled
) {
prefs.edit().putBoolean("enable_developer_options", it).apply()
developerOptionsEnabled = it
}
}
if (ksuVersion != null) {
val backupRestore = stringResource(id = R.string.backup_restore)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Backup,
backupRestore
)
},
headlineContent = { Text(backupRestore) },
modifier = Modifier.clickable {
navigator.navigate(BackupRestoreScreenDestination)
}
)
}
if (useOverlayFs) {
val shrink = stringResource(id = R.string.shrink_sparse_image) val shrink = stringResource(id = R.string.shrink_sparse_image)
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message) val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
ListItem( ListItem(
@@ -359,6 +318,51 @@ fun SettingScreen(navigator: DestinationsNavigator) {
) )
} }
val customization = stringResource(id = R.string.customization)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Palette,
customization
)
},
headlineContent = { Text(customization) },
modifier = Modifier.clickable {
navigator.navigate(CustomizationScreenDestination)
}
)
if (ksuVersion != null) {
val backupRestore = stringResource(id = R.string.backup_restore)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Backup,
backupRestore
)
},
headlineContent = { Text(backupRestore) },
modifier = Modifier.clickable {
navigator.navigate(BackupRestoreScreenDestination)
}
)
}
val developer = stringResource(id = R.string.developer)
if (ksuVersion != null) {
ListItem(
leadingContent = {
Icon(
Icons.Filled.DeveloperBoard,
developer
)
},
headlineContent = { Text(developer) },
modifier = Modifier.clickable {
navigator.navigate(DeveloperScreenDestination)
}
)
}
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
if (lkmMode) { if (lkmMode) {
@@ -496,7 +500,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
@Composable @Composable
fun UninstallItem( fun UninstallItem(
navigator: DestinationsNavigator, navigator: DestinationsNavigator,
withLoading: suspend (suspend () -> Unit) -> Unit withLoading: suspend (suspend () -> Unit) -> Unit,
) { ) {
val context = LocalContext.current val context = LocalContext.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
@@ -598,7 +602,7 @@ fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TopBar( private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null scrollBehavior: TopAppBarScrollBehavior? = null,
) { ) {
TopAppBar( TopAppBar(
title = { Text(stringResource(R.string.settings)) }, title = { Text(stringResource(R.string.settings)) },

View File

@@ -13,6 +13,7 @@ import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -24,6 +25,9 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage import coil.compose.AsyncImage
import coil.request.ImageRequest import coil.request.ImageRequest
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.ui.component.LabelItem
import com.dergoogler.mmrl.ui.component.LabelItemDefaults
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination
@@ -43,26 +47,13 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val listState = rememberLazyListState() val listState = rememberLazyListState()
LaunchedEffect(key1 = navigator) { LaunchedEffect(navigator) {
viewModel.search = "" viewModel.search = ""
if (viewModel.appList.isEmpty()) { if (viewModel.appList.isEmpty()) {
viewModel.fetchAppList() viewModel.fetchAppList()
} }
} }
LaunchedEffect(viewModel.search) {
if (viewModel.search.isEmpty()) {
listState.scrollToItem(0)
}
}
LaunchedEffect(Unit) {
if (viewModel.refreshOnReturn) {
viewModel.fetchAppList()
viewModel.refreshOnReturn = false
}
}
Scaffold( Scaffold(
topBar = { topBar = {
SearchAppBar( SearchAppBar(
@@ -101,7 +92,7 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
} }
) )
}, onClick = { }, onClick = {
viewModel.showSystemApps = !viewModel.showSystemApps viewModel.updateShowSystemApps(!viewModel.showSystemApps)
showDropdown = false showDropdown = false
}) })
} }
@@ -127,7 +118,6 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
) { ) {
items(viewModel.appList, key = { it.packageName + it.uid }) { app -> items(viewModel.appList, key = { it.packageName + it.uid }) { app ->
AppItem(app) { AppItem(app) {
viewModel.refreshOnReturn = true
navigator.navigate(AppProfileScreenDestination(app)) navigator.navigate(AppProfileScreenDestination(app))
} }
} }
@@ -148,16 +138,35 @@ private fun AppItem(
supportingContent = { supportingContent = {
Column { Column {
Text(app.packageName) Text(app.packageName)
FlowRow {
Spacer(modifier = Modifier.height(4.dp))
FlowRow(
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
if (app.allowSu) { if (app.allowSu) {
LabelText(label = "ROOT") LabelItem(
text = "ROOT",
)
} else { } else {
if (Natives.uidShouldUmount(app.uid)) { if (Natives.uidShouldUmount(app.uid)) {
LabelText(label = "UMOUNT") LabelItem(
text = "UMOUNT",
style = LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer
)
)
} }
} }
if (app.hasCustomProfile) { if (app.hasCustomProfile) {
LabelText(label = "CUSTOM") LabelItem(
text = "CUSTOM",
style = LabelItemDefaults.style.copy(
containerColor = MaterialTheme.colorScheme.onTertiary,
contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
)
)
} }
} }
} }

View File

@@ -2,9 +2,14 @@ package com.rifsxd.ksunext.ui.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
val YELLOW = Color(0xFFeed502) val PRIMARY = Color(0xFF8AADF4) // Catppuccin Blue
val YELLOW_LIGHT = Color(0xFFffff52) val PRIMARY_LIGHT = Color(0xFFB7BDF8) // Catppuccin Lavender
val SECONDARY_LIGHT = Color(0xffa9817f) val SECONDARY_LIGHT = Color(0xFFA6DA95) // Catppuccin Green
val YELLOW_DARK = Color(0xFFb7a400) val PRIMARY_DARK = Color(0xFF7DC4E4) // Catppuccin Sky
val SECONDARY_DARK = Color(0xFF4c2b2b) val SECONDARY_DARK = Color(0xFFF5BDE6) // Catppuccin Pink
val AMOLED_BLACK = Color(0xFF000000) // Pure black for AMOLED
val DARK_PURPLE = Color(0xFF6E6CB6) // Catppuccin Mauve (dark purple)
val DARK_GREY = Color(0xFF363A4F) // Catppuccin Surface (dark grey)

View File

@@ -1,6 +1,9 @@
package com.rifsxd.ksunext.ui.theme package com.rifsxd.ksunext.ui.theme
import android.os.Build import android.os.Build
import androidx.activity.SystemBarStyle
import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
@@ -8,39 +11,112 @@ import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme( private val DarkColorScheme = darkColorScheme(
primary = YELLOW, primary = PRIMARY,
secondary = YELLOW_DARK, secondary = PRIMARY_DARK,
tertiary = SECONDARY_DARK tertiary = SECONDARY_DARK
) )
private val LightColorScheme = lightColorScheme( private val LightColorScheme = lightColorScheme(
primary = YELLOW, primary = PRIMARY,
secondary = YELLOW_LIGHT, secondary = PRIMARY_LIGHT,
tertiary = SECONDARY_LIGHT tertiary = SECONDARY_LIGHT
) )
fun Color.blend(other: Color, ratio: Float): Color {
val inverse = 1f - ratio
return Color(
red = red * inverse + other.red * ratio,
green = green * inverse + other.green * ratio,
blue = blue * inverse + other.blue * ratio,
alpha = alpha
)
}
@Composable @Composable
fun KernelSUTheme( fun KernelSUTheme(
darkTheme: Boolean = isSystemInDarkTheme(), darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+ // Dynamic color is available on Android 12+
dynamicColor: Boolean = true, dynamicColor: Boolean = true,
amoledMode: Boolean = false,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val colorScheme = when { val colorScheme = when {
amoledMode && darkTheme && dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
val dynamicScheme = dynamicDarkColorScheme(context)
dynamicScheme.copy(
background = AMOLED_BLACK,
surface = AMOLED_BLACK,
surfaceVariant = dynamicScheme.surfaceVariant.blend(AMOLED_BLACK, 0.6f),
surfaceContainer = dynamicScheme.surfaceContainer.blend(AMOLED_BLACK, 0.6f),
surfaceContainerLow = dynamicScheme.surfaceContainerLow.blend(AMOLED_BLACK, 0.6f),
surfaceContainerLowest = dynamicScheme.surfaceContainerLowest.blend(AMOLED_BLACK, 0.6f),
surfaceContainerHigh = dynamicScheme.surfaceContainerHigh.blend(AMOLED_BLACK, 0.6f),
surfaceContainerHighest = dynamicScheme.surfaceContainerHighest.blend(AMOLED_BLACK, 0.6f),
)
}
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
} }
amoledMode && darkTheme -> {
DarkColorScheme.copy(
background = AMOLED_BLACK,
surface = AMOLED_BLACK,
surfaceVariant = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
surfaceContainer = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
surfaceContainerLow = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
surfaceContainerLowest = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
surfaceContainerHigh = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
surfaceContainerHighest = DARK_GREY.blend(AMOLED_BLACK, 0.8f),
)
}
darkTheme -> DarkColorScheme darkTheme -> DarkColorScheme
else -> LightColorScheme else -> LightColorScheme
} }
SystemBarStyle(
darkMode = darkTheme
)
MaterialTheme( MaterialTheme(
colorScheme = colorScheme, colorScheme = colorScheme,
typography = Typography, typography = Typography,
content = content content = content
) )
} }
@Composable
private fun SystemBarStyle(
darkMode: Boolean,
statusBarScrim: Color = Color.Transparent,
navigationBarScrim: Color = Color.Transparent,
) {
val context = LocalContext.current
val activity = context as ComponentActivity
SideEffect {
activity.enableEdgeToEdge(
statusBarStyle = SystemBarStyle.auto(
statusBarScrim.toArgb(),
statusBarScrim.toArgb(),
) { darkMode },
navigationBarStyle = when {
darkMode -> SystemBarStyle.dark(
navigationBarScrim.toArgb()
)
else -> SystemBarStyle.light(
navigationBarScrim.toArgb(),
navigationBarScrim.toArgb(),
)
}
)
}
}

View File

@@ -37,10 +37,16 @@ private fun ksuDaemonOverlayfsPath(): String {
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud_overlayfs.so" return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libksud_overlayfs.so"
} }
fun readMountSystemFile(): Boolean {
val shell = getRootShell()
val filePath = "/data/adb/ksu/mount_system"
val result = ShellUtils.fastCmd(shell, "cat $filePath").trim()
return result == "OVERLAYFS"
}
// Get the path based on the user's choice // Get the path based on the user's choice
fun getKsuDaemonPath(): String { fun getKsuDaemonPath(): String {
val prefs = ksuApp.getSharedPreferences("settings", Context.MODE_PRIVATE) val useOverlayFs = readMountSystemFile()
val useOverlayFs = prefs.getBoolean("use_overlay_fs", false)
return if (useOverlayFs) { return if (useOverlayFs) {
ksuDaemonOverlayfsPath() ksuDaemonOverlayfsPath()
@@ -49,6 +55,16 @@ fun getKsuDaemonPath(): String {
} }
} }
fun updateMountSystemFile(useOverlayFs: Boolean) {
val shell = getRootShell()
val filePath = "/data/adb/ksu/mount_system"
if (useOverlayFs) {
ShellUtils.fastCmd(shell, "echo -n OVERLAYFS > $filePath")
} else {
ShellUtils.fastCmd(shell, "echo -n MAGIC_MOUNT > $filePath")
}
}
data class FlashResult(val code: Int, val err: String, val showReboot: Boolean) { data class FlashResult(val code: Int, val err: String, val showReboot: Boolean) {
constructor(result: Shell.Result, showReboot: Boolean) : this(result.code, result.err.joinToString("\n"), showReboot) constructor(result: Shell.Result, showReboot: Boolean) : this(result.code, result.err.joinToString("\n"), showReboot)
constructor(result: Shell.Result) : this(result, result.isSuccess) constructor(result: Shell.Result) : this(result, result.isSuccess)
@@ -89,17 +105,17 @@ fun createRootShell(globalMnt: Boolean = false): Shell {
val builder = Shell.Builder.create() val builder = Shell.Builder.create()
return try { return try {
if (globalMnt) { if (globalMnt) {
builder.build(getKsuDaemonPath(), "debug", "su", "-g") builder.build(ksuDaemonMagicPath(), "debug", "su", "-g")
} else { } else {
builder.build(getKsuDaemonPath(), "debug", "su") builder.build(ksuDaemonMagicPath(), "debug", "su")
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Log.w(TAG, "ksu failed: ", e) Log.w(TAG, "ksu failed: ", e)
try { try {
if (globalMnt) { if (globalMnt) {
builder.build("su")
} else {
builder.build("su", "-mm") builder.build("su", "-mm")
} else {
builder.build("su")
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Log.e(TAG, "su failed: ", e) Log.e(TAG, "su failed: ", e)
@@ -443,7 +459,7 @@ fun getFileName(context: Context, uri: Uri): String {
fun moduleBackupDir(): String? { fun moduleBackupDir(): String? {
val shell = getRootShell() val shell = getRootShell()
val baseBackupDir = "/data/adb/ksu/modules_bak" val baseBackupDir = "/sdcard/.ksunext/modules"
val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim() val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim()
if (resultBase.isNotEmpty()) return null if (resultBase.isNotEmpty()) return null
@@ -462,60 +478,42 @@ fun moduleBackup(): Boolean {
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/modules)\" ]; then echo 'empty'; fi" val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/modules)\" ]; then echo 'empty'; fi"
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim() val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
if (resultCheckEmpty == "empty") { if (resultCheckEmpty == "empty") {
return false return false
} }
val backupDir = moduleBackupDir() ?: return false val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
val command = "cp -rp /data/adb/modules/* $backupDir" if (timestamp.isEmpty()) return false
val result = ShellUtils.fastCmd(shell, command).trim()
return result.isEmpty() val tarName = "modules_backup_$timestamp.tar"
} val tarPath = "/data/local/tmp/$tarName"
val internalBackupDir = "/sdcard/.ksunext/modules"
val internalBackupPath = "$internalBackupDir/$tarName"
fun moduleMigration(): Boolean { val tarCmd = "tar -cpf $tarPath -C /data/adb/modules $(ls /data/adb/modules)"
val shell = getRootShell() val tarResult = ShellUtils.fastCmd(shell, tarCmd).trim()
val command = "cp -rp /data/adb/modules/* /data/adb/modules_update" if (tarResult.isNotEmpty()) return false
val result = ShellUtils.fastCmd(shell, command).trim()
return result.isEmpty() ShellUtils.fastCmd(shell, "mkdir -p $internalBackupDir")
val cpResult = ShellUtils.fastCmd(shell, "cp $tarPath $internalBackupPath").trim()
if (cpResult.isNotEmpty()) return false
ShellUtils.fastCmd(shell, "rm -f $tarPath")
return true
} }
fun moduleRestore(): Boolean { fun moduleRestore(): Boolean {
val shell = getRootShell() val shell = getRootShell()
val command = "ls -t /data/adb/ksu/modules_bak | head -n 1" val findTarCmd = "ls -t /sdcard/.ksunext/modules/modules_backup_*.tar 2>/dev/null | head -n 1"
val latestBackupDir = ShellUtils.fastCmd(shell, command).trim() val tarPath = ShellUtils.fastCmd(shell, findTarCmd).trim()
if (tarPath.isEmpty()) return false
if (latestBackupDir.isEmpty()) return false val extractCmd = "tar -xpf $tarPath -C /data/adb/modules_update"
val extractResult = ShellUtils.fastCmd(shell, extractCmd).trim()
val sourceDir = "/data/adb/ksu/modules_bak/$latestBackupDir" return extractResult.isEmpty()
val destinationDir = "/data/adb/modules_update"
val createDestDirCommand = "mkdir -p $destinationDir"
ShellUtils.fastCmd(shell, createDestDirCommand)
val moveCommand = "cp -rp $sourceDir/* $destinationDir"
val result = ShellUtils.fastCmd(shell, moveCommand).trim()
return result.isEmpty()
}
fun allowlistBackupDir(): String? {
val shell = getRootShell()
val baseBackupDir = "/data/adb/ksu/allowlist_bak"
val resultBase = ShellUtils.fastCmd(shell, "mkdir -p $baseBackupDir").trim()
if (resultBase.isNotEmpty()) return null
val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
if (timestamp.isEmpty()) return null
val newBackupDir = "$baseBackupDir/$timestamp"
val resultNewDir = ShellUtils.fastCmd(shell, "mkdir -p $newBackupDir").trim()
if (resultNewDir.isEmpty()) return newBackupDir
return null
} }
fun allowlistBackup(): Boolean { fun allowlistBackup(): Boolean {
@@ -523,34 +521,50 @@ fun allowlistBackup(): Boolean {
val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/ksu/.allowlist)\" ]; then echo 'empty'; fi" val checkEmptyCommand = "if [ -z \"$(ls -A /data/adb/ksu/.allowlist)\" ]; then echo 'empty'; fi"
val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim() val resultCheckEmpty = ShellUtils.fastCmd(shell, checkEmptyCommand).trim()
if (resultCheckEmpty == "empty") { if (resultCheckEmpty == "empty") {
return false return false
} }
val backupDir = allowlistBackupDir() ?: return false val timestamp = ShellUtils.fastCmd(shell, "date +%Y%m%d_%H%M%S").trim()
val command = "cp -rp /data/adb/ksu/.allowlist $backupDir" if (timestamp.isEmpty()) return false
val result = ShellUtils.fastCmd(shell, command).trim()
return result.isEmpty() val tarName = "allowlist_backup_$timestamp.tar"
val tarPath = "/data/local/tmp/$tarName"
val internalBackupDir = "/sdcard/.ksunext/allowlist"
val internalBackupPath = "$internalBackupDir/$tarName"
val tarCmd = "tar -cpf $tarPath -C /data/adb/ksu .allowlist"
val tarResult = ShellUtils.fastCmd(shell, tarCmd).trim()
if (tarResult.isNotEmpty()) return false
ShellUtils.fastCmd(shell, "mkdir -p $internalBackupDir")
val cpResult = ShellUtils.fastCmd(shell, "cp $tarPath $internalBackupPath").trim()
if (cpResult.isNotEmpty()) return false
ShellUtils.fastCmd(shell, "rm -f $tarPath")
return true
} }
fun allowlistRestore(): Boolean { fun allowlistRestore(): Boolean {
val shell = getRootShell() val shell = getRootShell()
val command = "ls -t /data/adb/ksu/allowlist_bak | head -n 1" // Find the latest allowlist tar backup in /sdcard/.ksunext/allowlist
val latestBackupDir = ShellUtils.fastCmd(shell, command).trim() val findTarCmd = "ls -t /sdcard/.ksunext/allowlist/allowlist_backup_*.tar 2>/dev/null | head -n 1"
val tarPath = ShellUtils.fastCmd(shell, findTarCmd).trim()
if (tarPath.isEmpty()) return false
if (latestBackupDir.isEmpty()) return false // Extract the tar to /data/adb/ksu (restores .allowlist folder with permissions)
val extractCmd = "tar -xpf $tarPath -C /data/adb/ksu"
val extractResult = ShellUtils.fastCmd(shell, extractCmd).trim()
return extractResult.isEmpty()
}
val sourceDir = "/data/adb/ksu/allowlist_bak/$latestBackupDir" fun moduleMigration(): Boolean {
val destinationDir = "/data/adb/ksu/" val shell = getRootShell()
val command = "cp -rp /data/adb/modules/* /data/adb/modules_update"
val createDestDirCommand = "mkdir -p $destinationDir" val result = ShellUtils.fastCmd(shell, command).trim()
ShellUtils.fastCmd(shell, createDestDirCommand)
val moveCommand = "cp -rp $sourceDir/.allowlist $destinationDir"
val result = ShellUtils.fastCmd(shell, moveCommand).trim()
return result.isEmpty() return result.isEmpty()
} }
@@ -607,6 +621,17 @@ fun currentMountSystem(): String {
return result.substringAfter(":").substringAfter(" ").trim() return result.substringAfter(":").substringAfter(" ").trim()
} }
fun getModuleSize(dir: File): Long {
val shell = getRootShell()
val cmd = "du -sb '${dir.absolutePath}' | awk '{print \$1}'"
val result = ShellUtils.fastCmd(shell, cmd).trim()
return result.toLongOrNull() ?: 0L
}
fun isSuCompatDisabled(): Boolean {
return Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT && !Natives.isSuEnabled()
}
fun setAppProfileTemplate(id: String, template: String): Boolean { fun setAppProfileTemplate(id: String, template: String): Boolean {
val shell = getRootShell() val shell = getRootShell()
val escapedTemplate = template.replace("\"", "\\\"") val escapedTemplate = template.replace("\"", "\\\"")

View File

@@ -1,5 +1,6 @@
package com.rifsxd.ksunext.ui.viewmodel package com.rifsxd.ksunext.ui.viewmodel
import android.net.Uri
import android.os.SystemClock import android.os.SystemClock
import android.util.Log import android.util.Log
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
@@ -8,14 +9,20 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
import kotlinx.coroutines.delay
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import java.io.File
import java.text.Collator import java.text.Collator
import java.util.Locale import java.util.Locale
import com.rifsxd.ksunext.ksuApp import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.ui.util.HanziToPinyin import com.rifsxd.ksunext.ui.util.HanziToPinyin
import com.rifsxd.ksunext.ui.util.listModules import com.rifsxd.ksunext.ui.util.listModules
import com.rifsxd.ksunext.ui.util.overlayFsAvailable import com.rifsxd.ksunext.ui.util.getModuleSize
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
@@ -39,7 +46,9 @@ class ModuleViewModel : ViewModel() {
val updateJson: String, val updateJson: String,
val hasWebUi: Boolean, val hasWebUi: Boolean,
val hasActionScript: Boolean, val hasActionScript: Boolean,
val dirId: String val dirId: String,
val size: Long,
val banner: String
) )
data class ModuleUpdateInfo( data class ModuleUpdateInfo(
@@ -49,9 +58,6 @@ class ModuleViewModel : ViewModel() {
val changelog: String, val changelog: String,
) )
var isOverlayAvailable by mutableStateOf(overlayFsAvailable())
private set
var isRefreshing by mutableStateOf(false) var isRefreshing by mutableStateOf(false)
private set private set
@@ -59,11 +65,15 @@ class ModuleViewModel : ViewModel() {
var sortAToZ by mutableStateOf(false) var sortAToZ by mutableStateOf(false)
var sortZToA by mutableStateOf(false) var sortZToA by mutableStateOf(false)
var sortSizeLowToHigh by mutableStateOf(false)
var sortSizeHighToLow by mutableStateOf(false)
val moduleList by derivedStateOf { val moduleList by derivedStateOf {
val comparator = when { val comparator = when {
sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() } sortAToZ -> compareBy<ModuleInfo> { it.name.lowercase() }
sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() } sortZToA -> compareByDescending<ModuleInfo> { it.name.lowercase() }
sortSizeLowToHigh -> compareBy<ModuleInfo> { it.size }
sortSizeHighToLow -> compareByDescending<ModuleInfo> { it.size }
else -> compareBy<ModuleInfo> { it.dirId } else -> compareBy<ModuleInfo> { it.dirId }
}.thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id) }.thenBy(Collator.getInstance(Locale.getDefault()), ModuleInfo::id)
@@ -84,58 +94,91 @@ class ModuleViewModel : ViewModel() {
isNeedRefresh = true isNeedRefresh = true
} }
var zipUris by mutableStateOf<List<Uri>>(emptyList())
fun updateZipUris(uris: List<Uri>) {
zipUris = uris
}
fun clearZipUris() {
zipUris = emptyList()
}
fun fetchModuleList() { fun fetchModuleList() {
viewModelScope.launch(Dispatchers.IO) {
isRefreshing = true viewModelScope.launch {
val oldModuleList = modules withContext(Dispatchers.Main) {
isRefreshing = true
val start = SystemClock.elapsedRealtime()
kotlin.runCatching {
isOverlayAvailable = overlayFsAvailable()
val result = listModules()
Log.i(TAG, "result: $result")
val array = JSONArray(result)
modules = (0 until array.length())
.asSequence()
.map { array.getJSONObject(it) }
.map { obj ->
ModuleInfo(
obj.getString("id"),
obj.optString("name"),
obj.optString("author", "Unknown"),
obj.optString("version", "Unknown"),
obj.optInt("versionCode", 0),
obj.optString("description"),
obj.getBoolean("enabled"),
obj.getBoolean("update"),
obj.getBoolean("remove"),
obj.optString("updateJson"),
obj.optBoolean("web"),
obj.optBoolean("action"),
obj.getString("dir_id")
)
}.toList()
isNeedRefresh = false
}.onFailure { e ->
Log.e(TAG, "fetchModuleList: ", e)
isRefreshing = false
} }
// when both old and new is kotlin.collections.EmptyList withContext(Dispatchers.IO) {
// moduleList update will don't trigger withTimeoutOrNull(TIMEOUT_MILLIS) {
if (oldModuleList === modules) { while (!Platform.isAlive) {
isRefreshing = false delay(500)
} }
} ?: run {
isRefreshing = false
Log.e(TAG, "Platform is not alive, aborting fetchModuleList")
return@withContext
}
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}, modules: $modules") val start = SystemClock.elapsedRealtime()
val oldModuleList = modules
kotlin.runCatching {
val result = listModules()
Log.i(TAG, "result: $result")
val array = JSONArray(result)
modules = (0 until array.length())
.asSequence()
.map { array.getJSONObject(it) }
.map { obj ->
val id = obj.getString("id")
val dirId = obj.getString("dir_id")
val moduleDir = File("/data/adb/modules/$dirId")
val size = getModuleSize(moduleDir)
ModuleInfo(
id,
obj.optString("name"),
obj.optString("author", "Unknown"),
obj.optString("version", "Unknown"),
obj.optInt("versionCode", 0),
obj.optString("description"),
obj.getBoolean("enabled"),
obj.getBoolean("update"),
obj.getBoolean("remove"),
obj.optString("updateJson"),
obj.optBoolean("web"),
obj.optBoolean("action"),
dirId,
size,
obj.optString("banner")
)
}.toList()
isNeedRefresh = false
}.onFailure { e ->
Log.e(TAG, "fetchModuleList: ", e)
isRefreshing = false
}
// when both old and new is kotlin.collections.EmptyList
// moduleList update will don't trigger
if (oldModuleList === modules) {
isRefreshing = false
}
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}, modules: $modules")
}
} }
} }
private fun sanitizeVersionString(version: String): String {
return version.replace(Regex("[^a-zA-Z0-9.\\-_]"), "_")
}
fun checkUpdate(m: ModuleInfo): Triple<String, String, String> { fun checkUpdate(m: ModuleInfo): Triple<String, String, String> {
val empty = Triple("", "", "") val empty = Triple("", "", "")
if (m.updateJson.isEmpty() || m.remove || m.update || !m.enabled) { if (m.updateJson.isEmpty() || m.remove || m.update || !m.enabled) {
@@ -165,7 +208,8 @@ class ModuleViewModel : ViewModel() {
JSONObject(result) JSONObject(result)
}.getOrNull() ?: return empty }.getOrNull() ?: return empty
val version = updateJson.optString("version", "") var version = updateJson.optString("version", "")
version = sanitizeVersionString(version)
val versionCode = updateJson.optInt("versionCode", 0) val versionCode = updateJson.optInt("versionCode", 0)
val zipUrl = updateJson.optString("zipUrl", "") val zipUrl = updateJson.optString("zipUrl", "")
val changelog = updateJson.optString("changelog", "") val changelog = updateJson.optString("changelog", "")

View File

@@ -1,42 +1,44 @@
package com.rifsxd.ksunext.ui.viewmodel package com.rifsxd.ksunext.ui.viewmodel
import android.content.ComponentName import android.content.ComponentName
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.os.IBinder
import android.os.Parcelable import android.os.Parcelable
import android.os.SystemClock import android.os.SystemClock
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.topjohnwu.superuser.Shell import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.TIMEOUT_MILLIS
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import com.rifsxd.ksunext.IKsuInterface
import com.rifsxd.ksunext.Natives import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp import com.rifsxd.ksunext.ksuApp
import com.rifsxd.ksunext.ui.KsuService
import com.rifsxd.ksunext.ui.util.HanziToPinyin import com.rifsxd.ksunext.ui.util.HanziToPinyin
import com.rifsxd.ksunext.ui.util.KsuCli import com.rifsxd.ksunext.ui.webui.getInstalledPackagesAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeoutOrNull
import java.text.Collator import java.text.Collator
import java.util.* import java.util.*
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
import androidx.core.content.edit
class SuperUserViewModel : ViewModel() { class SuperUserViewModel : ViewModel() {
val isPlatformAlive get() = Platform.isAlive
var refreshOnReturn by mutableStateOf(false)
public set
companion object { companion object {
private const val TAG = "SuperUserViewModel" private const val TAG = "SuperUserViewModel"
private var apps by mutableStateOf<List<AppInfo>>(emptyList()) private var apps by mutableStateOf<List<AppInfo>>(emptyList())
private var profileOverrides by mutableStateOf<Map<String, Natives.Profile>>(emptyMap())
} }
@Parcelize @Parcelize
@@ -66,16 +68,26 @@ class SuperUserViewModel : ViewModel() {
} }
} }
private val prefs = ksuApp.getSharedPreferences("settings", Context.MODE_PRIVATE)!!
var search by mutableStateOf("") var search by mutableStateOf("")
var showSystemApps by mutableStateOf(false) var showSystemApps by mutableStateOf(prefs.getBoolean("show_system_apps", false))
private set
var isRefreshing by mutableStateOf(false) var isRefreshing by mutableStateOf(false)
private set private set
fun updateShowSystemApps(newValue: Boolean) {
showSystemApps = newValue
prefs.edit { putBoolean("show_system_apps", newValue) }
}
private val sortedList by derivedStateOf { private val sortedList by derivedStateOf {
val comparator = compareBy<AppInfo> { val comparator = compareBy<AppInfo> {
when { when {
it.allowSu -> 0 it.profile != null && it.profile.allowSu -> 0
it.hasCustomProfile -> 1 it.profile != null && (
if (it.profile.allowSu) !it.profile.rootUseDefault else !it.profile.nonRootUseDefault
) -> 1
else -> 2 else -> 2
} }
}.then(compareBy(Collator.getInstance(Locale.getDefault()), AppInfo::label)) }.then(compareBy(Collator.getInstance(Locale.getDefault()), AppInfo::label))
@@ -85,7 +97,9 @@ class SuperUserViewModel : ViewModel() {
} }
val appList by derivedStateOf { val appList by derivedStateOf {
sortedList.filter { sortedList.map { app ->
profileOverrides[app.packageName]?.let { app.copy(profile = it) } ?: app
}.filter {
it.label.contains(search, true) || it.packageName.contains( it.label.contains(search, true) || it.packageName.contains(
search, search,
true true
@@ -97,56 +111,30 @@ class SuperUserViewModel : ViewModel() {
} }
} }
private suspend inline fun connectKsuService( fun updateAppProfile(packageName: String, newProfile: Natives.Profile) {
crossinline onDisconnect: () -> Unit = {} profileOverrides = profileOverrides.toMutableMap().apply {
): Pair<IBinder, ServiceConnection> = suspendCoroutine { put(packageName, newProfile)
val connection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
onDisconnect()
}
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
it.resume(binder as IBinder to this)
}
} }
val intent = Intent(ksuApp, KsuService::class.java)
val task = KsuService.bindOrTask(
intent,
Shell.EXECUTOR,
connection,
)
val shell = KsuCli.SHELL
task?.let { it1 -> shell.execTask(it1) }
}
private fun stopKsuService() {
val intent = Intent(ksuApp, KsuService::class.java)
KsuService.stop(intent)
} }
suspend fun fetchAppList() { suspend fun fetchAppList() {
isRefreshing = true isRefreshing = true
val result = connectKsuService {
Log.w(TAG, "KsuService disconnected")
}
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
withTimeoutOrNull(TIMEOUT_MILLIS) {
while (!isPlatformAlive) {
delay(500)
}
} ?: return@withContext // Exit early if timeout
val pm = ksuApp.packageManager val pm = ksuApp.packageManager
val start = SystemClock.elapsedRealtime() val start = SystemClock.elapsedRealtime()
val binder = result.first val packages = Platform.getInstalledPackagesAll {
val allPackages = IKsuInterface.Stub.asInterface(binder).getPackages(0) Log.e(TAG, "getInstalledPackagesAll:", it)
Toast.makeText(ksuApp, "Something went wrong, check logs", Toast.LENGTH_SHORT).show()
withContext(Dispatchers.Main) {
stopKsuService()
} }
val packages = allPackages.list
apps = packages.map { apps = packages.map {
val appInfo = it.applicationInfo val appInfo = it.applicationInfo
val uid = appInfo!!.uid val uid = appInfo!!.uid
@@ -157,6 +145,7 @@ class SuperUserViewModel : ViewModel() {
profile = profile, profile = profile,
) )
}.filter { it.packageName != ksuApp.packageName } }.filter { it.packageName != ksuApp.packageName }
profileOverrides = emptyMap()
Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}") Log.i(TAG, "load cost: ${SystemClock.elapsedRealtime() - start}")
} }
} }

View File

@@ -0,0 +1,73 @@
package com.rifsxd.ksunext.ui.webui
import android.content.ServiceConnection
import android.content.pm.PackageInfo
import android.util.Log
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.hiddenApi.HiddenPackageManager
import com.dergoogler.mmrl.platform.hiddenApi.HiddenUserManager
import com.dergoogler.mmrl.platform.model.IProvider
import com.dergoogler.mmrl.platform.model.PlatformIntent
import com.rifsxd.ksunext.Natives
import com.rifsxd.ksunext.ksuApp
import com.topjohnwu.superuser.ipc.RootService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
class KsuLibSuProvider : IProvider {
override val name = "KsuLibSu"
override fun isAvailable() = true
override suspend fun isAuthorized() = Natives.becomeManager(ksuApp.packageName)
private val serviceIntent
get() = PlatformIntent(
ksuApp,
Platform.KsuNext,
SuService::class.java
)
override fun bind(connection: ServiceConnection) {
RootService.bind(serviceIntent.intent, connection)
}
override fun unbind(connection: ServiceConnection) {
RootService.stop(serviceIntent.intent)
}
}
suspend fun initPlatform() = withContext(Dispatchers.IO) {
try {
val active = Platform.init {
this.context = ksuApp
this.platform = Platform.KsuNext
this.provider = from(KsuLibSuProvider())
}
while (!active) {
delay(1000)
}
return@withContext active
} catch (e: Exception) {
Log.e("KsuLibSu", "Failed to initialize platform", e)
return@withContext false
}
}
fun Platform.Companion.getInstalledPackagesAll(catch: (Exception) -> Unit = {}): List<PackageInfo> =
try {
val packages = mutableListOf<PackageInfo>()
val userInfos = userManager.getUsers()
for (userInfo in userInfos) {
packages.addAll(packageManager.getInstalledPackages(0, userInfo.id))
}
packages
} catch (e: Exception) {
catch(e)
packageManager.getInstalledPackages(0, userManager.myUserId)
}

View File

@@ -0,0 +1,14 @@
package com.rifsxd.ksunext.ui.webui
import android.content.Intent
import android.os.IBinder
import com.dergoogler.mmrl.platform.model.PlatformIntent.Companion.getPlatform
import com.dergoogler.mmrl.platform.service.ServiceManager
import com.topjohnwu.superuser.ipc.RootService
class SuService : RootService() {
override fun onBind(intent: Intent): IBinder {
val mode = intent.getPlatform()
return ServiceManager(mode)
}
}

View File

@@ -15,6 +15,8 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.webkit.WebViewAssetLoader import androidx.webkit.WebViewAssetLoader
import com.dergoogler.mmrl.platform.model.ModId
import com.dergoogler.mmrl.webui.interfaces.WXOptions
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.rifsxd.ksunext.ui.util.createRootShell import com.rifsxd.ksunext.ui.util.createRootShell
import java.io.File import java.io.File
@@ -39,9 +41,10 @@ class WebUIActivity : ComponentActivity() {
val name = intent.getStringExtra("name")!! val name = intent.getStringExtra("name")!!
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name")) setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name"))
} else { } else {
val taskDescription = ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build() val taskDescription =
ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build()
setTaskDescription(taskDescription) setTaskDescription(taskDescription)
} }
@@ -62,7 +65,7 @@ class WebUIActivity : ComponentActivity() {
val webViewClient = object : WebViewClient() { val webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest( override fun shouldInterceptRequest(
view: WebView, view: WebView,
request: WebResourceRequest request: WebResourceRequest,
): WebResourceResponse? { ): WebResourceResponse? {
return webViewAssetLoader.shouldInterceptRequest(request.url) return webViewAssetLoader.shouldInterceptRequest(request.url)
} }
@@ -82,7 +85,9 @@ class WebUIActivity : ComponentActivity() {
settings.javaScriptEnabled = true settings.javaScriptEnabled = true
settings.domStorageEnabled = true settings.domStorageEnabled = true
settings.allowFileAccess = false settings.allowFileAccess = false
webviewInterface = WebViewInterface(this@WebUIActivity, this, moduleDir) webviewInterface = WebViewInterface(
WXOptions(this@WebUIActivity, this, ModId(moduleId))
)
addJavascriptInterface(webviewInterface, "ksu") addJavascriptInterface(webviewInterface, "ksu")
setWebViewClient(webViewClient) setWebViewClient(webViewClient)
loadUrl("https://mui.kernelsu.org/index.html") loadUrl("https://mui.kernelsu.org/index.html")

View File

@@ -0,0 +1,113 @@
package com.rifsxd.ksunext.ui.webui
import android.app.ActivityManager
import android.os.Build
import android.os.Bundle
import android.webkit.WebView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.lifecycleScope
import com.dergoogler.mmrl.platform.Platform
import com.dergoogler.mmrl.platform.model.ModId
import com.dergoogler.mmrl.ui.component.Loading
import com.dergoogler.mmrl.webui.screen.WebUIScreen
import com.dergoogler.mmrl.webui.util.rememberWebUIOptions
import com.rifsxd.ksunext.BuildConfig
import com.rifsxd.ksunext.ui.theme.KernelSUTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class WebUIXActivity : ComponentActivity() {
private lateinit var webView: WebView
private val userAgent
get(): String {
val ksuVersion = BuildConfig.VERSION_CODE
val platform = Platform.get("Unknown") {
platform.name
}
val platformVersion = Platform.get(-1) {
moduleManager.versionCode
}
val osVersion = Build.VERSION.RELEASE
val deviceModel = Build.MODEL
return "KernelSU Next/$ksuVersion (Linux; Android $osVersion; $deviceModel; $platform/$platformVersion)"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
webView = WebView(this)
lifecycleScope.launch {
initPlatform()
}
val moduleId = intent.getStringExtra("id")!!
val name = intent.getStringExtra("name")!!
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
@Suppress("DEPRECATION")
setTaskDescription(ActivityManager.TaskDescription("KernelSU Next - $name"))
} else {
val taskDescription =
ActivityManager.TaskDescription.Builder().setLabel("KernelSU Next - $name").build()
setTaskDescription(taskDescription)
}
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
setContent {
KernelSUTheme {
var isLoading by remember { mutableStateOf(true) }
LaunchedEffect(Platform.isAlive) {
while (!Platform.isAlive) {
delay(1000)
}
isLoading = false
}
if (isLoading) {
Loading()
return@KernelSUTheme
}
val webDebugging = prefs.getBoolean("enable_web_debugging", false)
val erudaInject = prefs.getBoolean("use_webuix_eruda", false)
val dark = isSystemInDarkTheme()
val options = rememberWebUIOptions(
modId = ModId(moduleId),
debug = webDebugging,
appVersionCode = BuildConfig.VERSION_CODE,
isDarkMode = dark,
enableEruda = erudaInject,
cls = WebUIXActivity::class.java,
userAgentString = userAgent
)
WebUIScreen(
webView = webView,
options = options,
interfaces = listOf(
WebViewInterface.factory()
)
)
}
}
}
}

View File

@@ -1,16 +1,17 @@
package com.rifsxd.ksunext.ui.webui package com.rifsxd.ksunext.ui.webui
import android.app.Activity import android.app.Activity
import android.content.Context
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.text.TextUtils import android.text.TextUtils
import android.view.Window import android.view.Window
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.widget.Toast import android.widget.Toast
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import com.dergoogler.mmrl.webui.interfaces.WXInterface
import com.dergoogler.mmrl.webui.interfaces.WXOptions
import com.dergoogler.mmrl.webui.model.JavaScriptInterface
import com.topjohnwu.superuser.CallbackList import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.ShellUtils import com.topjohnwu.superuser.ShellUtils
import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.internal.UiThreadHandler
@@ -23,10 +24,15 @@ import java.io.File
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class WebViewInterface( class WebViewInterface(
val context: Context, wxOptions: WXOptions,
private val webView: WebView, ) : WXInterface(wxOptions) {
private val modDir: String override var name: String = "ksu"
) {
companion object {
fun factory() = JavaScriptInterface(WebViewInterface::class.java)
}
private val modDir get() = "/data/adb/modules/${modId.id}"
@JavascriptInterface @JavascriptInterface
fun exec(cmd: String): String { fun exec(cmd: String): String {
@@ -59,7 +65,7 @@ class WebViewInterface(
fun exec( fun exec(
cmd: String, cmd: String,
options: String?, options: String?,
callbackFunc: String callbackFunc: String,
) { ) {
val finalCommand = StringBuilder() val finalCommand = StringBuilder()
processOptions(finalCommand, options) processOptions(finalCommand, options)
@@ -168,9 +174,9 @@ class WebViewInterface(
if (context is Activity) { if (context is Activity) {
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
if (enable) { if (enable) {
hideSystemUI(context.window) hideSystemUI(activity.window)
} else { } else {
showSystemUI(context.window) showSystemUI(activity.window)
} }
} }
} }
@@ -179,7 +185,7 @@ class WebViewInterface(
@JavascriptInterface @JavascriptInterface
fun moduleInfo(): String { fun moduleInfo(): String {
val moduleInfos = JSONArray(listModules()) val moduleInfos = JSONArray(listModules())
var currentModuleInfo = JSONObject() val currentModuleInfo = JSONObject()
currentModuleInfo.put("moduleDir", modDir) currentModuleInfo.put("moduleDir", modDir)
val moduleId = File(modDir).getName() val moduleId = File(modDir).getName()
for (i in 0 until moduleInfos.length()) { for (i in 0 until moduleInfos.length()) {
@@ -189,7 +195,7 @@ class WebViewInterface(
continue continue
} }
var keys = currentInfo.keys() val keys = currentInfo.keys()
for (key in keys) { for (key in keys) {
currentModuleInfo.put(key, currentInfo.get(key)) currentModuleInfo.put(key, currentInfo.get(key))
} }
@@ -202,8 +208,12 @@ class WebViewInterface(
fun hideSystemUI(window: Window) = fun hideSystemUI(window: Window) =
WindowInsetsControllerCompat(window, window.decorView).let { controller -> WindowInsetsControllerCompat(window, window.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.systemBars()) controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} }
fun showSystemUI(window: Window) = fun showSystemUI(window: Window) =
WindowInsetsControllerCompat(window, window.decorView).show(WindowInsetsCompat.Type.systemBars()) WindowInsetsControllerCompat(
window,
window.decorView
).show(WindowInsetsCompat.Type.systemBars())

Binary file not shown.

View File

@@ -32,11 +32,11 @@
<string name="selinux_status_enforcing">مفعل</string> <string name="selinux_status_enforcing">مفعل</string>
<string name="selinux_status_permissive">مرن</string> <string name="selinux_status_permissive">مرن</string>
<string name="selinux_status_unknown">غير معروف</string> <string name="selinux_status_unknown">غير معروف</string>
<string name="superuser">مستخدم خارق</string> <string name="superuser">المستخدم خارق</string>
<string name="module_failed_to_enable">فشل في تشغيل إضافة: %s</string> <string name="module_failed_to_enable">فشل في تشغيل إضافة: %s</string>
<string name="module_failed_to_disable">فشل في إيقاف إضافة: %s</string> <string name="module_failed_to_disable">فشل في إيقاف إضافة: %s</string>
<string name="module_empty">لا توجد إضافات مثبته</string> <string name="module_empty">لا توجد إضافات مثبته</string>
<string name="module">الإضافة</string> <string name="module">الإضافات</string>
<string name="module_install_prompt_with_name">الإضافة/ات التالية سيتم تثبيتها: %1$s</string> <string name="module_install_prompt_with_name">الإضافة/ات التالية سيتم تثبيتها: %1$s</string>
<string name="module_sort_a_to_z">تصنيف (أ-ي)</string> <string name="module_sort_a_to_z">تصنيف (أ-ي)</string>
<string name="module_sort_z_to_a">تصنيف (ي-أ)</string> <string name="module_sort_z_to_a">تصنيف (ي-أ)</string>
@@ -49,7 +49,7 @@
<string name="reboot_userspace">إعادة تشغيل سريعة</string> <string name="reboot_userspace">إعادة تشغيل سريعة</string>
<string name="reboot_recovery">إعادة التشغيل إلى وضع الريكفري</string> <string name="reboot_recovery">إعادة التشغيل إلى وضع الريكفري</string>
<string name="reboot_bootloader">إعادة التشغيل إلى وضع bootloader</string> <string name="reboot_bootloader">إعادة التشغيل إلى وضع bootloader</string>
<string name="reboot_download">إعادة التشغيل إلى وضع التحميل</string> <string name="reboot_download">إعادة التشغيل إلى وضع التنزيل</string>
<string name="reboot_edl">إعادة التشغيل إلى وضع EDL</string> <string name="reboot_edl">إعادة التشغيل إلى وضع EDL</string>
<string name="about">حول</string> <string name="about">حول</string>
<string name="module_uninstall_confirm">هل انت متأكد من حذف تلك الإضافة %s؟</string> <string name="module_uninstall_confirm">هل انت متأكد من حذف تلك الإضافة %s؟</string>
@@ -75,11 +75,11 @@
<string name="reboot_to_apply">إعادة التشغيل لتطبيق التغييرات</string> <string name="reboot_to_apply">إعادة التشغيل لتطبيق التغييرات</string>
<string name="module_magisk_conflict">الإضافات غير متاحة بسبب تعارض مع Magisk!</string> <string name="module_magisk_conflict">الإضافات غير متاحة بسبب تعارض مع Magisk!</string>
<string name="home_mount_system">نظام الإضافات</string> <string name="home_mount_system">نظام الإضافات</string>
<string name="home_magic_mount">Mount السحري</string> <string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string> <string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">غير متاح</string> <string name="unavailable">غير متاح</string>
<string name="use_overlay_fs">استخدام OverlayFS</string> <string name="use_overlay_fs">استخدام OverlayFS</string>
<string name="use_overlay_fs_summary">التبديل بين استخدام OverlayFS أو Mount السحري لنظام Mount الخاص بـ KernelSU Next.</string> <string name="use_overlay_fs_summary">التبديل بين استخدام OverlayFS أو Magic Mount لنظام Mount الخاص بـKernelSU Next.</string>
<string name="reboot_required">إعادة التشغيل مطلوبة</string> <string name="reboot_required">إعادة التشغيل مطلوبة</string>
<string name="reboot_message">ستدخل التغييرات حيز التنفيذ بعد إعادة تشغيل النظام. هل تريد إعادة التشغيل الآن؟</string> <string name="reboot_message">ستدخل التغييرات حيز التنفيذ بعد إعادة تشغيل النظام. هل تريد إعادة التشغيل الآن؟</string>
<string name="module_restore">استعادة الإضافة</string> <string name="module_restore">استعادة الإضافة</string>
@@ -105,7 +105,7 @@
<string name="home_experimental_kernelsu_body_point_1"> • استخدم على مسؤوليتك: قد تحدث أعطال أو سلوك غير متوقع أو مشاكل في النظام.</string> <string name="home_experimental_kernelsu_body_point_1"> • استخدم على مسؤوليتك: قد تحدث أعطال أو سلوك غير متوقع أو مشاكل في النظام.</string>
<string name="home_experimental_kernelsu_body_point_2"> • لا ضمان: المطورون غير مسؤولين عن أي فقدان للبيانات أو تلف النظام أو عواقب أخرى ناتجة عن استخدامه.</string> <string name="home_experimental_kernelsu_body_point_2"> • لا ضمان: المطورون غير مسؤولين عن أي فقدان للبيانات أو تلف النظام أو عواقب أخرى ناتجة عن استخدامه.</string>
<string name="home_experimental_kernelsu_body_point_3"> • لأغراض الاختبار فقط: مخصص للمستخدمين الذين يفهمون المخاطر ويشعرون بالراحة في حل المشكلات.</string> <string name="home_experimental_kernelsu_body_point_3"> • لأغراض الاختبار فقط: مخصص للمستخدمين الذين يفهمون المخاطر ويشعرون بالراحة في حل المشكلات.</string>
<string name="about_source_code"><![CDATA[عرض الشيفرة المصدرية في %1$s]]></string> <string name="about_source_code"><![CDATA[عرض رمز المصدر في %1$s]]></string>
<string name="profile" translatable="false">ملف التطبيق</string> <string name="profile" translatable="false">ملف التطبيق</string>
<string name="profile_default">افتراضي</string> <string name="profile_default">افتراضي</string>
<string name="profile_template">قالب</string> <string name="profile_template">قالب</string>

View File

@@ -120,7 +120,7 @@
<string name="require_kernel_version">Die aktuelle KernelSU Next Version %1$d ist zu veraltet, damit der Manager richtig funktioniert. aktualisieren Sie bitte auf Version %2$d oder höher!</string> <string name="require_kernel_version">Die aktuelle KernelSU Next Version %1$d ist zu veraltet, damit der Manager richtig funktioniert. aktualisieren Sie bitte auf Version %2$d oder höher!</string>
<string name="settings_umount_modules_default">Umount Module</string> <string name="settings_umount_modules_default">Umount Module</string>
<string name="settings_umount_modules_default_summary">Der globale Standardwert für \„Umount Module\“ in App Profile. Wenn er aktiviert ist, werden alle Moduländerungen im System für Anwendungen entfernt, für die kein Profil festgelegt wurde.</string> <string name="settings_umount_modules_default_summary">Der globale Standardwert für \„Umount Module\“ in App Profile. Wenn er aktiviert ist, werden alle Moduländerungen im System für Anwendungen entfernt, für die kein Profil festgelegt wurde.</string>
<string name="settings_susfs_toggle">verstecke kprobe hooks</string> <string name="settings_susfs_toggle">verstecke kprobes hook</string>
<string name="settings_susfs_toggle_summary">Diese Option deaktiviert die von ksu erzeugten kprobe-hooks und aktiviert stattdessen die eingebetteten nicht-kprobe-hooks, die die gleiche Funktionalität implementieren, die auf einen Nicht-GKI-Kernel angewendet würde, der kprobe nicht unterstützt.</string> <string name="settings_susfs_toggle_summary">Diese Option deaktiviert die von ksu erzeugten kprobe-hooks und aktiviert stattdessen die eingebetteten nicht-kprobe-hooks, die die gleiche Funktionalität implementieren, die auf einen Nicht-GKI-Kernel angewendet würde, der kprobe nicht unterstützt.</string>
<string name="profile_umount_modules_summary">Wenn Sie diese Option aktivieren, kann KernelSU Next alle von den Modulen für diese Anwendung geänderten Dateien wiederherstellen.</string> <string name="profile_umount_modules_summary">Wenn Sie diese Option aktivieren, kann KernelSU Next alle von den Modulen für diese Anwendung geänderten Dateien wiederherstellen.</string>
<string name="profile_selinux_domain">Domain</string> <string name="profile_selinux_domain">Domain</string>

View File

@@ -0,0 +1,197 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">مشکلی دارید؟</string>
<string name="issue_report_body">با خطا مواجه شده‌اید یا نظری دارید؟</string>
<string name="issue_report_body_2">هرچه زودتر گزارش دهید!</string>
<string name="issue_report_github">گزارش در گیت‌هاب</string>
<string name="issue_report_telegram">تماس از طریق تلگرام</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">تأیید</string>
<string name="app_name" translatable="false">KernelSU Next</string>
<string name="home">خانه</string>
<string name="home_not_installed">نصب نشده</string>
<string name="home_click_to_install">برای نصب کلیک کنید</string>
<string name="home_working">در حال کار</string>
<string name="home_working_version">نسخه: %d</string>
<string name="home_superuser_count">کاربران ویژه: %d</string>
<string name="home_module_count">ماژول‌ها: %d</string>
<string name="home_failure">امضای KernelSU Next v2 در هسته یافت نشد! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">از توسعه‌دهنده هسته خود بخواهید KernelSU Next را یکپارچه کند!</string>
<string name="home_kernel">نسخه هسته</string>
<string name="enabled">فعال</string>
<string name="disabled">غیرفعال</string>
<string name="susfs_supported">پشتیبانی‌شده</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">نسخه SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">نسخه اندروید</string>
<string name="home_manager_version">نسخه مدیر</string>
<string name="home_selinux_status">وضعیت SELinux</string>
<string name="selinux_status_disabled">غیرفعال</string>
<string name="selinux_status_enforcing">اجباری</string>
<string name="selinux_status_permissive">مجاز</string>
<string name="selinux_status_unknown">ناشناخته</string>
<string name="superuser">کاربر ویژه</string>
<string name="module_failed_to_enable">فعال‌سازی ماژول شکست خورد: %s</string>
<string name="module_failed_to_disable">غیرفعال‌سازی ماژول شکست خورد: %s</string>
<string name="module_empty">هیچ ماژولی نصب نشده</string>
<string name="module">ماژول</string>
<string name="module_install_prompt_with_name">ماژول(های) زیر نصب خواهد شد: %1$s</string>
<string name="module_sort_a_to_z">مرتب‌سازی (الف-ی)</string>
<string name="module_sort_z_to_a">مرتب‌سازی (ی-الف)</string>
<string name="uninstall">حذف نصب</string>
<string name="restore">بازیابی</string>
<string name="module_install">نصب</string>
<string name="install">نصب</string>
<string name="reboot">راه‌اندازی مجدد</string>
<string name="settings">تنظیمات</string>
<string name="reboot_userspace">راه‌اندازی نرم</string>
<string name="reboot_recovery">راه‌اندازی به حالت ریکاوری</string>
<string name="reboot_bootloader">راه‌اندازی به حالت بوت‌لودر</string>
<string name="reboot_download">راه‌اندازی به حالت دانلود</string>
<string name="reboot_edl">راه‌اندازی به حالت EDL</string>
<string name="about">درباره</string>
<string name="module_uninstall_confirm">آیا مطمئن هستید که می‌خواهید ماژول %s را حذف کنید؟</string>
<string name="module_uninstall_success">ماژول %s حذف شد</string>
<string name="module_uninstall_failed">حذف ماژول شکست خورد: %s</string>
<string name="module_restore_confirm">آیا مطمئن هستید که می‌خواهید ماژول %s را بازیابی کنید؟</string>
<string name="module_restore_success">ماژول %s بازیابی شد</string>
<string name="module_restore_failed">بازیابی ماژول شکست خورد: %s</string>
<string name="module_version">نسخه</string>
<string name="module_author">سازنده</string>
<string name="module_id">شناسه</string>
<string name="module_version_code">کد نسخه</string>
<string name="module_update_json">به‌روزرسانی JSON</string>
<string name="module_update_json_empty">خالی</string>
<string name="enable_developer_options">فعال‌سازی گزینه‌های توسعه‌دهنده</string>
<string name="enable_developer_options_summary">نمایش تنظیمات مخفی و اطلاعات اشکال‌زدایی که فقط برای توسعه‌دهندگان مفید است.</string>
<string name="module_overlay_fs_not_available">ماژول‌ها به دلیل غیرفعال بودن OverlayFS توسط هسته در دسترس نیستند.</string>
<string name="refresh">تازه‌سازی</string>
<string name="show_system_apps">نمایش برنامه‌های سیستمی</string>
<string name="hide_system_apps">پنهان کردن برنامه‌های سیستمی</string>
<string name="export_log">صدور گزارش‌ها</string>
<string name="safe_mode">حالت ایمن</string>
<string name="reboot_to_apply">برای اعمال تغییرات راه‌اندازی مجدد کنید</string>
<string name="module_magisk_conflict">ماژول‌ها به دلیل تداخل با Magisk در دسترس نیستند!</string>
<string name="home_mount_system">نصب سیستم</string>
<string name="home_magic_mount">نصب جادویی</string>
<string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">در دسترس نیست</string>
<string name="use_overlay_fs">استفاده از OverlayFS</string>
<string name="use_overlay_fs_summary">تغییر بین استفاده از OverlayFS و نصب جادویی برای سیستم نصب KernelSU Next.</string>
<string name="reboot_required">نیاز به راه‌اندازی مجدد</string>
<string name="reboot_message">تغییرات پس از راه‌اندازی مجدد سیستم اعمال می‌شوند. آیا می‌خواهید اکنون راه‌اندازی کنید؟</string>
<string name="module_restore">بازیابی ماژول</string>
<string name="module_restore_message">بازیابی ماژول‌ها از آخرین نسخه پشتیبان.</string>
<string name="backup_restore">پشتیبان‌گیری و بازیابی</string>
<string name="module_backup">پشتیبان‌گیری از ماژول</string>
<string name="module_backup_message">پشتیبان‌گیری از ماژول‌های نصب‌شده کنونی.</string>
<string name="allowlist_restore">بازیابی لیست مجاز</string>
<string name="allowlist_restore_message">بازیابی لیست مجاز از آخرین نسخه پشتیبان.</string>
<string name="allowlist_backup">پشتیبان‌گیری از لیست مجاز</string>
<string name="allowlist_backup_message">پشتیبان‌گیری از لیست مجاز کنونی.</string>
<string name="warning">هشدار</string>
<string name="warning_message">این ویژگی هنوز در مرحله آزمایشی و در حال توسعه است. لطفاً پیش از ادامه، از ماژول‌های خود نسخه پشتیبان تهیه کنید. این ویژگی را تنها در صورتی استفاده کنید که خطرات احتمالی را درک کرده باشید. با احتیاط ادامه دهید.</string>
<string name="proceed">ادامه</string>
<string name="cancel">لغو</string>
<string name="later">بعداً</string>
<string name="home_next_kernelsu">🔥 ساخت بعدی</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">شاخه آزمایشی بعدی. آن را در گیت‌هاب بررسی کنید!</string>
<string name="home_experimental_kernelsu">⚠️ هشدار توسعه آزمایشی!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next نسخه‌ای غیررسمی است که همیشه در حال توسعه آزمایشی فعال است. این نسخه همان‌گونه که هست ارائه می‌شود، بدون تضمین پایداری، عملکرد یا قابلیت اطمینان.</string>
<string name="home_experimental_kernelsu_body_point_1"> • استفاده با مسئولیت خودتان: ممکن است با خرابی، رفتار غیرمنتظره یا مشکلات سیستمی مواجه شوید.</string>
<string name="home_experimental_kernelsu_body_point_2"> • بدون گارانتی: توسعه‌دهندگان مسئول هیچ‌گونه از دست دادن داده، آسیب به سیستم یا سایر پیامدها نیستند.</string>
<string name="home_experimental_kernelsu_body_point_3"> • فقط برای آزمایش: برای کاربرانی که خطرات را درک کرده و با عیب‌یابی راحت هستند.</string>
<string name="about_source_code"><![CDATA[مشاهده کد منبع در %1$s]]></string>
<string name="profile" translatable="false">پروفایل برنامه</string>
<string name="profile_default">پیش‌فرض</string>
<string name="profile_template">الگو</string>
<string name="profile_custom">سفارشی</string>
<string name="profile_name">نام پروفایل</string>
<string name="profile_namespace">فضای نصب</string>
<string name="profile_namespace_inherited">ارثی</string>
<string name="profile_namespace_global">جهانی</string>
<string name="profile_namespace_individual">فردی</string>
<string name="profile_groups">گروه‌ها</string>
<string name="profile_capabilities">قابلیت‌ها</string>
<string name="profile_selinux_context">زمینه SELinux</string>
<string name="profile_umount_modules">حذف ماژول‌ها</string>
<string name="failed_to_update_app_profile">به‌روزرسانی پروفایل برنامه برای %s شکست خورد</string>
<string name="require_kernel_version">نسخه کنونی KernelSU Next %1$d برای عملکرد صحیح مدیر بسیار پایین است. لطفاً به نسخه %2$d یا بالاتر ارتقا دهید!</string>
<string name="settings_umount_modules_default">حذف پیش‌فرض ماژول‌ها</string>
<string name="settings_umount_modules_default_summary">مقدار پیش‌فرض جهانی برای «حذف ماژول‌ها» در پروفایل برنامه. اگر فعال باشد، تمام تغییرات سیستمی ماژول‌ها برای برنامه‌هایی که پروفایل ندارند حذف می‌شود.</string>
<string name="settings_susfs_toggle">مخفی کردن قلاب‌های kprobe</string>
<string name="settings_susfs_toggle_summary">این گزینه قلاب‌های kprobe ایجادشده توسط ksu را غیرفعال کرده و به‌جای آن، قلاب‌های غیر kprobe داخلی را فعال می‌کند که همان عملکرد را برای هسته‌های غیر GKI که از kprobe پشتیبانی نمی‌کنند، پیاده‌سازی می‌کند.</string>
<string name="profile_umount_modules_summary">فعال کردن این گزینه به KernelSU Next اجازه می‌دهد فایل‌های تغییر یافته توسط ماژول‌ها را برای این برنامه بازیابی کند.</string>
<string name="profile_selinux_domain">دامنه</string>
<string name="profile_selinux_rules">قوانین</string>
<string name="module_update">به‌روزرسانی</string>
<string name="module_downloading">در حال دانلود ماژول: %s</string>
<string name="module_start_downloading">شروع دانلود: %s</string>
<string name="new_version_available">نسخه جدید %s در دسترس است، برای ارتقا کلیک کنید.</string>
<string name="launch_app">اجرا</string>
<string name="close">بستن</string>
<string name="force_stop_app">توقف اجباری</string>
<string name="restart_app">راه‌اندازی مجدد</string>
<string name="failed_to_update_sepolicy">به‌روزرسانی قوانین SELinux برای %s شکست خورد</string>
<string name="su_not_allowed">اعطای دسترسی ویژه برای %s مجاز نیست</string>
<string name="module_changelog">تغییرات</string>
<string name="settings_profile_template">الگوی پروفایل برنامه</string>
<string name="settings_profile_template_summary">مدیریت الگوهای محلی و آنلاین پروفایل برنامه</string>
<string name="app_profile_template_create">ایجاد الگو</string>
<string name="app_profile_template_edit">ویرایش الگو</string>
<string name="app_profile_template_id">شناسه</string>
<string name="app_profile_template_id_invalid">شناسه الگو نامعتبر است</string>
<string name="app_profile_template_name">نام</string>
<string name="app_profile_template_description">توضیحات</string>
<string name="app_profile_template_save">ذخیره</string>
<string name="app_profile_template_delete">حذف</string>
<string name="app_profile_template_view">مشاهده الگو</string>
<string name="app_profile_template_readonly">فقط خواندنی</string>
<string name="app_profile_template_id_exist">شناسه الگو قبلاً وجود دارد!</string>
<string name="app_profile_import_export">واردات/صادرات</string>
<string name="app_profile_import_from_clipboard">واردات از کلیپ‌بورد</string>
<string name="app_profile_export_to_clipboard">صادرات به کلیپ‌بورد</string>
<string name="app_profile_template_export_empty">هیچ الگوی محلی برای صادرات یافت نشد!</string>
<string name="app_profile_template_import_success">با موفقیت وارد شد</string>
<string name="app_profile_template_sync">همگام‌سازی الگوهای آنلاین</string>
<string name="app_profile_template_save_failed">ذخیره الگو شکست خورد</string>
<string name="app_profile_template_import_empty">کلیپ‌بورد خالی است!</string>
<string name="module_changelog_failed">دریافت تغییرات شکست خورد: %s</string>
<string name="settings_check_update">بررسی به‌روزرسانی</string>
<string name="settings_check_update_summary">بررسی خودکار به‌روزرسانی‌ها هنگام باز کردن برنامه.</string>
<string name="grant_root_failed">اعطای دسترسی ریشه شکست خورد!</string>
<string name="action">اقدام</string>
<string name="open">باز کردن</string>
<string name="enable_web_debugging">فعال‌سازی اشکال‌زدایی وب‌ویو</string>
<string name="enable_web_debugging_summary">می‌تواند برای اشکال‌زدایی رابط وب استفاده شود. لطفاً فقط در صورت نیاز فعال کنید.</string>
<string name="direct_install">نصب مستقیم (توصیه‌شده)</string>
<string name="select_file">انتخاب فایل</string>
<string name="install_inactive_slot">نصب در اسلات غیرفعال (پس از OTA)</string>
<string name="install_inactive_slot_warning">دستگاه شما پس از راه‌اندازی مجدد **اجباراً** به اسلات غیرفعال کنونی بوت خواهد شد!\nفقط پس از انجام OTA از این گزینه استفاده کنید.\nادامه می‌دهید؟</string>
<string name="install_next">بعدی</string>
<string name="select_file_tip">تصویر پارتیشن %1$s توصیه می‌شود</string>
<string name="select_kmi">انتخاب KMI</string>
<string name="shrink_sparse_image">کاهش اندازه تصویر پراکنده</string>
<string name="shrink_sparse_image_message">تغییر اندازه تصویر پراکنده‌ای که ماژول در آن قرار دارد به اندازه واقعی آن. توجه داشته باشید که این ممکن است باعث عملکرد غیرعادی ماژول شود، بنابراین فقط در صورت نیاز (مانند پشتیبان‌گیری) استفاده کنید.</string>
<string name="settings_uninstall">حذف نصب</string>
<string name="settings_uninstall_temporary">حذف نصب موقت</string>
<string name="settings_uninstall_permanent">حذف نصب دائمی</string>
<string name="settings_restore_stock_image">بازیابی تصویر اصلی</string>
<string name="settings_uninstall_temporary_message">حذف موقت KernelSU Next، بازگشت به حالت اولیه پس از راه‌اندازی بعدی.</string>
<string name="settings_uninstall_permanent_message">حذف کامل و دائمی KernelSU Next (ریشه و همه ماژول‌ها).</string>
<string name="settings_restore_stock_image_message">بازیابی تصویر کارخانه‌ای (در صورت وجود نسخه پشتیبان)، معمولاً قبل از OTA استفاده می‌شود؛ اگر نیاز به حذف KernelSU Next دارید، لطفاً از «حذف نصب دائمی» استفاده کنید.</string>
<string name="flashing">در حال فلش</string>
<string name="flash_success">فلش موفق</string>
<string name="flash_failed">فلش ناموفق</string>
<string name="selected_lkm">LKM انتخاب‌شده: %s</string>
<string name="save_log">ذخیره گزارش‌ها</string>
<string name="log_saved">گزارش‌ها ذخیره شدند</string>
<string name="send_log">اشتراک گزارش‌ها</string>
<string name="settings_disable_su">غیرفعال کردن سازگاری su</string>
<string name="settings_disable_su_summary">غیرفعال کردن موقت توانایی هر برنامه برای کسب دسترسی ریشه از طریق دستور su (فرآیندهای ریشه موجود تحت تأثیر قرار نمی‌گیرند).</string>
<string name="settings_language">زبان</string>
</resources>

View File

@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Problémája van?</string>
<string name="issue_report_body">Hibát észlelt, vagy visszajelzése van?</string>
<string name="issue_report_body_2">Jelentse mielőbb!</string>
<string name="issue_report_github">Report on GitHub</string>
<string name="issue_report_telegram">Kapcsolatfelvétel Telegramon keresztül</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Megerősítés</string>
<string name="app_name" translatable="false">KernelSU Next</string>
<string name="home">Kezdőlap</string>
<string name="home_not_installed">Nincs telepítve</string>
<string name="home_click_to_install">Kattintson a telepítéshez</string>
<string name="lkm_alternative_suggestion">Telepíts GKI kernelt, vagy integráld a KernelSU Next-et az eszközödbe.</string>
<string name="home_working">Működik</string>
<string name="home_working_version">Verzió: %d</string>
<string name="home_superuser_count">Superuserek: %d</string>
<string name="home_module_count">Modulok: %d</string>
<string name="home_module_update_count">Frissítések: %d</string>
<string name="home_failure">KernelSU Next v2 aláírás nem található a kernelben! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Kérje meg kernel fejlesztőjét, hogy integrálja a KernelSU Next-et!</string>
<string name="home_kernel">Kernel verzió</string>
<string name="disable">Kikapcsolva</string>
<string name="enabled">Bekapcsolva</string>
<string name="disabled">Kikapcsolva</string>
<string name="susfs_supported">Támogatott</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">SuSFS verzió</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android verzió</string>
<string name="home_manager_version">Manager verzió</string>
<string name="home_selinux_status">SELinux státusz</string>
<string name="selinux_status_disabled">Letiltva</string>
<string name="selinux_status_enforcing">Kényszerítve</string>
<string name="selinux_status_permissive">Megengedő</string>
<string name="selinux_status_unknown">Ismeretlen</string>
<string name="superuser">Superuser</string>
<string name="module_failed_to_enable">Nem sikerült bekapcsolni a(z) %s modult</string>
<string name="module_failed_to_disable">Nem sikerült kikapcsolni a(z) %s modult</string>
<string name="module_empty">Nincs telepített modul</string>
<string name="module">Modul</string>
<string name="module_install_prompt_with_name">A következő modul(ok) lesznek telepítve: %1$s</string>
<string name="module_sort_a_to_z">Rendezés (A → Z)</string>
<string name="module_sort_z_to_a">Rendezés (Z → A)</string>
<string name="module_size_high_to_low">Rendezés (Magas → Alacsony)</string>
<string name="uninstall">Eltávolítás</string>
<string name="restore">Visszaállítás</string>
<string name="module_install">Telepítés</string>
<string name="install">Telepítés</string>
<string name="reboot">Újraindítás</string>
<string name="uninstalled">Eltávolítva</string>
<string name="settings">Beállítások</string>
<string name="reboot_userspace">Lágy újraindítás</string>
<string name="reboot_recovery">Újraindítás Recovery módba</string>
<string name="reboot_bootloader">Újraindítás Bootloader módba</string>
<string name="reboot_download">Újraindítás Download módba</string>
<string name="reboot_edl">Újraindítás EDL módba</string>
<string name="about">Információ</string>
<string name="module_uninstall_confirm">Biztosan eltávolítja a(z) %s modult?</string>
<string name="module_uninstall_success">%s eltávolítva</string>
<string name="module_uninstall_failed">Nem sikerült eltávolítani az %s modult</string>
<string name="module_restore_confirm">Biztosan vissza szeretné állítan a(z) %s modult?</string>
<string name="module_restore_success">%s visszaállítva</string>
<string name="module_restore_failed">Nem sikerült visszaállítani a(z) %s modult</string>
<string name="module_version">Verzió</string>
<string name="module_author">Készítő</string>
<string name="module_id">Azonosító</string>
<string name="module_version_code">Kód</string>
<string name="module_update_json">UpdateJson</string>
<string name="module_update_json_empty">Üres</string>
<string name="enable_developer_options">Engedélyezze a fejlesztői beállításokat</string>
<string name="enable_developer_options_summary">Csak a fejlesztők számára releváns rejtett beállítások és hibakeresési információk megjelenítése.</string>
<string name="module_overlay_fs_not_available">A modulok nem érhetők el, mert az OverlayFS-t a kernel letiltotta.</string>
<string name="refresh">Frissítés</string>
<string name="show_system_apps">Rendszeralkalmazások megjelenítése</string>
<string name="hide_system_apps">Rendszeralkalmazások elrejtése</string>
<string name="export_log">Naplók exportálása</string>
<string name="safe_mode">Biztonságos mód</string>
<string name="reboot_to_apply">Indítsa újra a változtatások érvénybe lépéséhez</string>
<string name="module_magisk_conflict">A modulok a Magiskkel való konfliktus miatt nem érhetők el!</string>
<string name="home_mount_system">Csatolási rendszer</string>
<string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">Nem elérhető</string>
<string name="use_overlay_fs">Használja az OverlayFS-t</string>
<string name="use_overlay_fs_summary">Váltás az OverlayFS és a Magic Mount módszerek között a KernelSU Next csatolási rendszerében.</string>
<string name="reboot_required">Újraindítás szükséges</string>
<string name="reboot_message">A változtatások a rendszer újraindítása után lépnek életbe. Szeretné most újraindítani?</string>
<string name="module_restore">Modul visszaállítása</string>
<string name="module_restore_message">Modulok visszaállítása biztonsági mentésből</string>
<string name="backup_restore">Mentés &amp; Visszaállítás</string>
<string name="module_backup">Modul biztonsági mentése</string>
<string name="module_backup_message">Biztonsági mentés a jelenleg telepített modulokról.</string>
<string name="allowlist_restore">Engedélyezőlista visszaállítása</string>
<string name="allowlist_restore_message">Engedélyezőlista visszaállítása biztonsági mentésből.</string>
<string name="allowlist_backup">Az engedélyezési lista biztonsági mentése</string>
<string name="allowlist_backup_message">A jelenleg konfigurált engedélyezési lista biztonsági mentése.</string>
<string name="warning">Figyelem</string>
<string name="warning_message">Ez a funkció még béta állapotban van, és fejlesztés alatt áll. Kérjük, a folytatás előtt készítsen biztonsági másolatot a modulokról. Csak akkor használja ezt a funkciót, ha tisztában van a lehetséges kockázatokkal. Óvatosan járjon el.</string>
<string name="proceed">Folytatás</string>
<string name="cancel">Mégse</string>
<string name="later">Később</string>
<string name="lkm_warning_message">Az LKM patch zárt forráskódú komponenseken alapul. Folytatja?</string>
<string name="home_next_kernelsu">🔥 Next build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next kísérleti branch. Nézze meg a GitHubon!</string>
<string name="home_experimental_kernelsu">⚠️ Figyelmeztetés kísérleti fejlesztésre!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">A KernelSU Next egy nem hivatalos verzió, amely folyamatosan kísérleti fejlesztés alatt áll. Az alkalmazás \"ahogy most van\", úgy kerül biztosításra, stabilitás, teljesítmény vagy megbízhatóság tekintetében semmilyen garancia nélkül.</string>
<string name="home_experimental_kernelsu_body_point_1">• Saját felelősségre használja: összeomlások, váratlan viselkedés vagy rendszerproblémák fordulhatnak elő.</string>
<string name="home_experimental_kernelsu_body_point_2">• Nincs garancia: a fejlesztők nem vállalnak felelősséget a használatából eredő adatvesztésért, rendszerkárosodásért vagy egyéb következményekért.</string>
<string name="home_experimental_kernelsu_body_point_3">• Csak tesztelési célokra: azoknak a felhasználóknak készült, akik megértik a kockázatokat, és jártasak a hibaelhárításban.</string>
<string name="about_source_code"><![CDATA[Tekintse meg a forráskódot: %1$s]]></string>
<string name="profile" translatable="false">App Profil</string>
<string name="profile_default">Alapértelmezett</string>
<string name="profile_template">Sablon</string>
<string name="profile_custom">Egyedi</string>
<string name="profile_name">Profil neve</string>
<string name="profile_namespace">Csatolási névtér</string>
<string name="profile_namespace_inherited">Örökölt</string>
<string name="profile_namespace_global">Globális</string>
<string name="profile_namespace_individual">Egyedi</string>
<string name="profile_groups">Csoportok</string>
<string name="profile_capabilities">Adottságok</string>
<string name="profile_selinux_context">SELinux környezet</string>
<string name="profile_umount_modules">Modulok lecsatolása</string>
<string name="failed_to_update_app_profile">Nem sikerült frissíteni a(z) %s alkalmazásprofilját</string>
<string name="require_kernel_version">A jelenlegi KernelSU Next verzió (%1$d) túl alacsony ahhoz, hogy a kezelő megfelelően működjön. Kérjük, frissítsen a(z) %2$d vagy újabb verzióra!</string>
<string name="settings_umount_modules_default">Modulok lecsatolása</string>
<string name="settings_umount_modules_default_summary">A „Modulok lecsatolása” globális alapértelmezett értéke az alkalmazásprofilban. Ha engedélyezve van, eltávolítja a rendszer összes modul-módosítását az olyan alkalmazások esetében, amelyekhez nincs beállítva profil.</string>
<string name="settings_susfs_toggle">A kprobe hook-ok elrejtése</string>
<string name="settings_susfs_toggle_summary">Ez az opció letiltja a ksu által létrehozott kprobe hook-okat, és ehelyett aktiválja a beágyazott, nem kprobe hook-okat, megvalósítva ugyanazt a funkcionalitást, amelyet egy nem GKI kernel esetében alkalmaznának, amely nem támogatja a kprobe-ot.</string>
<string name="profile_umount_modules_summary">Az opció engedélyezése lehetővé teszi, hogy a KernelSU Next visszaállítsa az alkalmazás moduljai által módosított fájlokat.</string>
<string name="profile_selinux_domain">Domain</string>
<string name="profile_selinux_rules">Szabályok</string>
<string name="module_update">Frissítés</string>
<string name="module_updated">Frissítve</string>
<string name="module_downloading">%s modul letöltése</string>
<string name="module_start_downloading">Letöltés indítása: %s</string>
<string name="new_version_available">Új verzió (%s) elérhető, kattintson a frissítéshez.</string>
<string name="launch_app">Indítás</string>
<string name="close">Bezár</string>
<string name="force_stop_app">Kényszer leállítás</string>
<string name="restart_app">Újraindítás</string>
<string name="restart_app_message">A módosítás érvénybe lépéséhez újra kell indítani az alkalmazást.</string>
<string name="failed_to_update_sepolicy">Nem sikerült frissíteni a SELinux szabályait a következőhöz: %s</string>
<string name="su_not_allowed">Superuser megadása nem engedélyezett a következőhöz: %s</string>
<string name="module_changelog">Változásnapló</string>
<string name="settings_profile_template">Alkalmazásprofil sablon</string>
<string name="settings_profile_template_summary">Az alkalmazásprofil helyi és online sablonjának kezelése</string>
<string name="app_profile_template_create">Sablon létrehozása</string>
<string name="app_profile_template_edit">Sablon szerkesztése</string>
<string name="app_profile_template_id">Azonosító</string>
<string name="app_profile_template_id_invalid">Érvénytelen sablonazonosító</string>
<string name="app_profile_template_name">Név</string>
<string name="app_profile_template_description">Leírás</string>
<string name="app_profile_template_save">Mentés</string>
<string name="app_profile_template_delete">Törlés</string>
<string name="app_profile_template_view">Sablon megtekintése</string>
<string name="app_profile_template_readonly">Csak olvasható</string>
<string name="app_profile_template_id_exist">A sablonazonosító már létezik!</string>
<string name="app_profile_import_export">Importálás/Exportálás</string>
<string name="app_profile_import_from_clipboard">Importálás a vágólapról</string>
<string name="app_profile_export_to_clipboard">Exportálás vágólapra</string>
<string name="app_profile_template_export_empty">Nem található az exportálandó helyi sablon!</string>
<string name="app_profile_template_import_success">Sikeresen importálva</string>
<string name="app_profile_template_sync">Online sablonok szinkronizálása</string>
<string name="app_profile_template_save_failed">Nem sikerült menteni a sablont</string>
<string name="app_profile_template_import_empty">A vágólap üres!</string>
<string name="module_changelog_failed">A változásnapló lekérése nem sikerült: %s</string>
<string name="settings_check_update">Ellenőrizze a frissítéseket</string>
<string name="settings_check_update_summary">Az alkalmazás megnyitásakor automatikusan ellenőrizze a frissítéseket.</string>
<string name="grant_root_failed">Nem sikerült a root jog megadása!</string>
<string name="action">Tevékenység</string>
<string name="open">Megnyitás</string>
<string name="enable_web_debugging">WebView hibakeresés engedélyezése</string>
<string name="enable_web_debugging_summary">A WebUI hibakeresésére. Kérjük, csak akkor engedélyezze, ha szükséges.</string>
<string name="direct_install">Közvetlen telepítés (ajánlott)</string>
<string name="select_file">Fájl kiválasztása a patcheléshez</string>
<string name="install_inactive_slot">Telepítés inaktív slotba (OTA után)</string>
<string name="install_inactive_slot_warning">Eszköze újraindítás után **KÉNYSZERÍTVE** lesz, hogy a jelenleg inaktív slotból induljon el! Ezt az opciót csak az OTA befejezése után használja. Folytatja?</string>
<string name="install_next">Következő</string>
<string name="select_file_tip">%1$s partíciókép javasolt</string>
<string name="select_kmi">Válassza ki a megfelelő KMI-t</string>
<string name="shrink_sparse_image">Sparse image minimalizálása</string>
<string name="shrink_sparse_image_message">Méretezze át a sparse imaget, ahol a modul található, a tényleges méretre. Vegye figyelembe, hogy ez a modul rendellenes működését okozhatja, ezért kérjük, csak akkor használja, ha szükséges (például biztonsági mentéshez).</string>
<string name="settings_uninstall">Eltávolítás</string>
<string name="settings_uninstall_temporary">Ideiglenes eltávolítás</string>
<string name="settings_uninstall_permanent">Végleges eltávolítás</string>
<string name="settings_restore_stock_image">Gyári képfájl visszaállítása</string>
<string name="settings_uninstall_temporary_message">A KernelSU ideiglenes eltávolítása, a következő újraindítás után állítsa vissza az eredeti állapotot.</string>
<string name="settings_uninstall_permanent_message">A KernelSU Next (Root és az összes modul) teljes és végleges eltávolítása.</string>
<string name="settings_restore_stock_image_message">Állítsa vissza a gyári készletképet (ha létezik biztonsági másolat), amelyet általában az OTA előtt használnak; Ha el kell távolítania a KernelSU Next-t, használja a „Végleges eltávolítás” lehetőséget.</string>
<string name="flashing">Telepítés</string>
<string name="flash_success">Sikeres telepítés</string>
<string name="flash_failed">A telepítés nem sikerült</string>
<string name="selected_lkm">A kiválasztott LKM: %s</string>
<string name="save_log">Mentse a naplókat</string>
<string name="log_saved">A naplók mentve</string>
<string name="send_log">Naplók megosztása</string>
<string name="settings_disable_su">Kapcsolja ki a su kompatibilitást</string>
<string name="settings_disable_su_summary">Ideiglenesen tiltsa le bármely alkalmazás azon képességét, hogy root jogosultságokat szerezzen a su paranccsal (a már meglévő folyamatokat ez nem érinti).</string>
<string name="settings_language">Nyelv</string>
<string name="lkm_mode_deprecated">Az LKM mód elavult!</string>
<string name="hook_mode">Hook módszer</string>
<string name="enable">Bekapcsolva</string>
<string name="module_size_low_to_high">Rendezés (Alacsony → Magas)</string>
<string name="settings_amoled_mode">AMOLED mód</string>
<string name="settings_amoled_mode_summary">Engedélyezzen egy teljesen fekete témát, amely leginkább AMOLED képernyőkön hasznos. Csökkenti a szem megerőltetését és az akkumulátort is kíméli.</string>
<string name="restart_required">Újraindítás szükséges</string>
<string name="settings_legacyui">Legacy UI használata</string>
<string name="settings_legacyui_summary">Váltás az előző felhasználói felületre.</string>
<string name="settings_banner">Bannerek engedélyezése</string>
<string name="settings_banner_summary">Mutassa a modulok hátterének bannereit.</string>
<string name="use_webuix">WebUI X használata</string>
<string name="use_webuix_summary">A WebUI X több API-t támogat, mint a WebUI.</string>
<string name="use_webuix_eruda">Eruda injektálása a WebUI X-be</string>
<string name="use_webuix_eruda_summary">Hibakeresési konzol injektálása a WebUI X-be a hibakeresés megkönnyítése érdekében. Ehhez a webes hibakeresést be kell kapcsolni.</string>
<string name="customization">Testreszabás</string>
</resources>

View File

@@ -12,13 +12,19 @@
<string name="home">Home</string> <string name="home">Home</string>
<string name="home_not_installed">Non installato</string> <string name="home_not_installed">Non installato</string>
<string name="home_click_to_install">Clicca per installare</string> <string name="home_click_to_install">Clicca per installare</string>
<string name="lkm_mode_deprecated">La modalità LKM è ora obsoleta!</string>
<string name="lkm_alternative_suggestion">Installa il kernel GKI o integra KernelSU Next sul tuo dispositivo.</string>
<string name="home_working">In esecuzione</string> <string name="home_working">In esecuzione</string>
<string name="home_working_version">Versione: %d</string> <string name="home_working_version">Versione: %d</string>
<string name="home_superuser_count">Applicazioni con accesso root: %d</string> <string name="home_superuser_count">Applicazioni con accesso root: %d</string>
<string name="home_module_count">Moduli: %d</string> <string name="home_module_count">Moduli: %d</string>
<string name="home_module_update_count">Aggiornamenti: %d</string>
<string name="home_failure">Firma KernelSU Next v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">Firma KernelSU Next v2 non trovata nel kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Chiedi allo sviluppatore del kernel di integrare KernelSU Next!</string> <string name="home_failure_tip">Chiedi allo sviluppatore del kernel di integrare KernelSU Next!</string>
<string name="home_kernel">Versione Kernel</string> <string name="home_kernel">Versione Kernel</string>
<string name="hook_mode">Modalità Hook</string>
<string name="enable">Abilita</string>
<string name="disable">Disabilita</string>
<string name="enabled">Abilitato</string> <string name="enabled">Abilitato</string>
<string name="disabled">Disabilitato</string> <string name="disabled">Disabilitato</string>
<string name="susfs_supported">Supportato</string> <string name="susfs_supported">Supportato</string>
@@ -27,6 +33,7 @@
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Versione Android</string> <string name="home_android">Versione Android</string>
<string name="home_manager_version">Versione del manager</string> <string name="home_manager_version">Versione del manager</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Stato di SELinux</string> <string name="home_selinux_status">Stato di SELinux</string>
<string name="selinux_status_disabled">Disabilitato</string> <string name="selinux_status_disabled">Disabilitato</string>
<string name="selinux_status_enforcing">Enforcing</string> <string name="selinux_status_enforcing">Enforcing</string>
@@ -38,13 +45,16 @@
<string name="module_empty">Nessun modulo installato</string> <string name="module_empty">Nessun modulo installato</string>
<string name="module">Modulo</string> <string name="module">Modulo</string>
<string name="module_install_prompt_with_name">Verranno installati i seguenti moduli: %1$s</string> <string name="module_install_prompt_with_name">Verranno installati i seguenti moduli: %1$s</string>
<string name="module_sort_a_to_z">Ordinare (A-Z)</string> <string name="module_sort_a_to_z">Ordina (AZ)</string>
<string name="module_sort_z_to_a">Ordinare (Z-A)</string> <string name="module_sort_z_to_a">Ordina (ZA)</string>
<string name="module_size_low_to_high">Ordina (Basso → Alto)</string>
<string name="module_size_high_to_low">Ordina (Alto → Basso)</string>
<string name="uninstall">Disinstalla</string> <string name="uninstall">Disinstalla</string>
<string name="restore">Ripristina</string> <string name="restore">Ripristina</string>
<string name="module_install">Installa</string> <string name="module_install">Installa</string>
<string name="install">Installa</string> <string name="install">Installa</string>
<string name="reboot">Riavvia</string> <string name="reboot">Riavvia</string>
<string name="uninstalled">Disinstallato</string>
<string name="settings">Impostazioni</string> <string name="settings">Impostazioni</string>
<string name="reboot_userspace">Riavvio rapido</string> <string name="reboot_userspace">Riavvio rapido</string>
<string name="reboot_recovery">Riavvia in Recovery</string> <string name="reboot_recovery">Riavvia in Recovery</string>
@@ -96,6 +106,7 @@
<string name="proceed">Procedere</string> <string name="proceed">Procedere</string>
<string name="cancel">Cancellare</string> <string name="cancel">Cancellare</string>
<string name="later">Dopo</string> <string name="later">Dopo</string>
<string name="lkm_warning_message">La patch LKM si basa su componenti closed source. Vuoi continuare?</string>
<string name="home_next_kernelsu">🔥 Next build</string> <string name="home_next_kernelsu">🔥 Next build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Branch sperimentale di Next. Dai un\'occhiata su GitHub!</string> <string name="home_next_kernelsu_body">Branch sperimentale di Next. Dai un\'occhiata su GitHub!</string>
@@ -123,12 +134,13 @@
<string name="require_kernel_version">La versione attualmente installata di KernelSU Next %1$d è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %2$d o successiva!</string> <string name="require_kernel_version">La versione attualmente installata di KernelSU Next %1$d è troppo vecchia ed il gestore non può funzionare correttamente. Si prega di aggiornare alla versione %2$d o successiva!</string>
<string name="settings_umount_modules_default">Scollega moduli</string> <string name="settings_umount_modules_default">Scollega moduli</string>
<string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string> <string name="settings_umount_modules_default_summary">Il valore predefinito per \"Scollega moduli\" in App Profile. Se attivato, rimuoverà tutte le modifiche al sistema da parte dei moduli per le applicazioni che non hanno un profilo impostato.</string>
<string name="settings_susfs_toggle">Nascondi kprobe hooks</string> <string name="settings_susfs_toggle">Nascondi kprobes hook</string>
<string name="settings_susfs_toggle_summary">Questa opzione disabilita gli hook kprobe creati da ksu e, al loro posto, attiva gli hook non-kprobe incorporati, implementando la stessa funzionalità che verrebbe applicata a un kernel non-GKI, che non supporta kprobe.</string> <string name="settings_susfs_toggle_summary">Questa opzione disabilita gli hook kprobe creati da ksu e, al loro posto, attiva gli hook non-kprobe incorporati, implementando la stessa funzionalità che verrebbe applicata a un kernel non-GKI, che non supporta kprobe.</string>
<string name="profile_umount_modules_summary">Attivando questa opzione permetterai a KernelSU Next di ripristinare ogni file modificato dai moduli per questa app.</string> <string name="profile_umount_modules_summary">Attivando questa opzione permetterai a KernelSU Next di ripristinare ogni file modificato dai moduli per questa app.</string>
<string name="profile_selinux_domain">Dominio</string> <string name="profile_selinux_domain">Dominio</string>
<string name="profile_selinux_rules">Regole</string> <string name="profile_selinux_rules">Regole</string>
<string name="module_update">Aggiorna</string> <string name="module_update">Aggiorna</string>
<string name="module_updated">Aggiornato</string>
<string name="module_downloading">Sto scaricando il modulo: %s</string> <string name="module_downloading">Sto scaricando il modulo: %s</string>
<string name="module_start_downloading">Inizia a scaricare: %s</string> <string name="module_start_downloading">Inizia a scaricare: %s</string>
<string name="new_version_available">Nuova versione: %s disponibile, tocca per aggiornare.</string> <string name="new_version_available">Nuova versione: %s disponibile, tocca per aggiornare.</string>
@@ -136,6 +148,10 @@
<string name="close">Chiudi</string> <string name="close">Chiudi</string>
<string name="force_stop_app">Arresto forzato</string> <string name="force_stop_app">Arresto forzato</string>
<string name="restart_app">Riavvia</string> <string name="restart_app">Riavvia</string>
<string name="settings_amoled_mode">Modalità AMOLED</string>
<string name="settings_amoled_mode_summary">Abilita un tema nero puro, utile per gli schermi AMOLED, per ridurre l\'affaticamento degli occhi e risparmiare batteria.</string>
<string name="restart_required">Riavvio richiesto</string>
<string name="restart_app_message">Affinché la modifica abbia effetto, è necessario riavviare l\'app.</string>
<string name="failed_to_update_sepolicy">Aggiornamento regole SELinux per %s fallito</string> <string name="failed_to_update_sepolicy">Aggiornamento regole SELinux per %s fallito</string>
<string name="su_not_allowed">Non è consentito concedere i privilegi di superutente per: %s</string> <string name="su_not_allowed">Non è consentito concedere i privilegi di superutente per: %s</string>
<string name="module_changelog">Registro aggiornamenti</string> <string name="module_changelog">Registro aggiornamenti</string>
@@ -165,6 +181,7 @@
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti all\'apertura dell\'applicazione.</string> <string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti all\'apertura dell\'applicazione.</string>
<string name="grant_root_failed">Impossibile ottenere l\'accesso root!</string> <string name="grant_root_failed">Impossibile ottenere l\'accesso root!</string>
<string name="action">Azione</string> <string name="action">Azione</string>
<string name="webui">WebUI</string>
<string name="open">Apri</string> <string name="open">Apri</string>
<string name="enable_web_debugging">Abilita il debug di WebView</string> <string name="enable_web_debugging">Abilita il debug di WebView</string>
<string name="enable_web_debugging_summary">Può essere usato per il debug di WebUI, è consigliato attivarlo solo quando necessario.</string> <string name="enable_web_debugging_summary">Può essere usato per il debug di WebUI, è consigliato attivarlo solo quando necessario.</string>
@@ -176,7 +193,7 @@
<string name="select_file_tip">Si consiglia l\'immagine della partizione %1$s</string> <string name="select_file_tip">Si consiglia l\'immagine della partizione %1$s</string>
<string name="select_kmi">Scegli il KMI</string> <string name="select_kmi">Scegli il KMI</string>
<string name="shrink_sparse_image">Riduci al minimo l\'immagine sparse</string> <string name="shrink_sparse_image">Riduci al minimo l\'immagine sparse</string>
<string name="shrink_sparse_image_message">Ridimensiona l\'immagine sparse dei moduli alla sua reale dimensione. Nota che questo potrebbe causare malfunzionamenti dei moduli, quindi utilizzala solo quando necessario (Come per il backup)).</string> <string name="shrink_sparse_image_message">Ridimensiona l\'immagine sparse dei moduli alla sua reale dimensione. Nota che questo potrebbe causare malfunzionamenti dei moduli, quindi utilizzala solo quando necessario (Come per il backup).</string>
<string name="settings_uninstall">Disinstalla</string> <string name="settings_uninstall">Disinstalla</string>
<string name="settings_uninstall_temporary">Disinstalla temporaneamente</string> <string name="settings_uninstall_temporary">Disinstalla temporaneamente</string>
<string name="settings_uninstall_permanent">Disinstalla permanentemente</string> <string name="settings_uninstall_permanent">Disinstalla permanentemente</string>
@@ -194,4 +211,14 @@
<string name="settings_disable_su">Disabilita la compatibilità su</string> <string name="settings_disable_su">Disabilita la compatibilità su</string>
<string name="settings_disable_su_summary">Disattiva temporaneamente la possibilità per qualsiasi app di ottenere privilegi di root tramite il comando su (i processi di root esistenti non saranno interessati).</string> <string name="settings_disable_su_summary">Disattiva temporaneamente la possibilità per qualsiasi app di ottenere privilegi di root tramite il comando su (i processi di root esistenti non saranno interessati).</string>
<string name="settings_language">Lingua</string> <string name="settings_language">Lingua</string>
<string name="settings_legacyui">Usa Legacy UI</string>
<string name="settings_legacyui_summary">Passa allo stile precedente dell\'interfaccia utente.</string>
<string name="settings_banner">Abilita banner</string>
<string name="settings_banner_summary">Mostra banner di sfondo per i moduli.</string>
<string name="use_webuix">Usa WebUI X</string>
<string name="use_webuix_summary">Usa WebUI X invece di WebUI che supporta più API.</string>
<string name="use_webuix_eruda">Iniettare Eruda in WebUI X</string>
<string name="use_webuix_eruda_summary">Inietta una console di debug in WebUI X per semplificare il debug. Richiede che il debug web sia attivo.</string>
<string name="customization">Personalizzazione</string>
<string name="developer">Sviluppatore</string>
</resources> </resources>

View File

@@ -12,13 +12,19 @@
<string name="home">Strona główna</string> <string name="home">Strona główna</string>
<string name="home_not_installed">Niezainstalowany</string> <string name="home_not_installed">Niezainstalowany</string>
<string name="home_click_to_install">Kliknij, aby zainstalować</string> <string name="home_click_to_install">Kliknij, aby zainstalować</string>
<string name="lkm_mode_deprecated">Tryb LKM jest już przestarzały!</string>
<string name="lkm_alternative_suggestion">Zainstaluj jądro GKI lub zintegruj KernelSU Next ze swoim urządzeniem.</string>
<string name="home_working">Uruchomiony</string> <string name="home_working">Uruchomiony</string>
<string name="home_working_version">Wersja: %d</string> <string name="home_working_version">Wersja: %d</string>
<string name="home_superuser_count">Superuserów: %d</string> <string name="home_superuser_count">Superuserów: %d</string>
<string name="home_module_count">Modułów: %d</string> <string name="home_module_count">Modułów: %d</string>
<string name="home_module_update_count">Aktualizacji: %d</string>
<string name="home_failure">Nie znaleziono sygnatury KernelSU Next v2 w jądrze! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">Nie znaleziono sygnatury KernelSU Next v2 w jądrze! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Poproś swojego programistę jądra o integrację KernelSU Next!</string> <string name="home_failure_tip">Poproś swojego programistę jądra o integrację KernelSU Next!</string>
<string name="home_kernel">Wersja jądra</string> <string name="home_kernel">Wersja jądra</string>
<string name="hook_mode">Tryb hookowania</string>
<string name="enable">Aktywuj</string>
<string name="disable">Dezaktywuj</string>
<string name="enabled">Aktywny</string> <string name="enabled">Aktywny</string>
<string name="disabled">Nieaktywny</string> <string name="disabled">Nieaktywny</string>
<string name="susfs_supported">Obsługiwany</string> <string name="susfs_supported">Obsługiwany</string>
@@ -27,6 +33,7 @@
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Wersja Androida</string> <string name="home_android">Wersja Androida</string>
<string name="home_manager_version">Wersja managera</string> <string name="home_manager_version">Wersja managera</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Status SELinux</string> <string name="home_selinux_status">Status SELinux</string>
<string name="selinux_status_disabled">Wyłączony</string> <string name="selinux_status_disabled">Wyłączony</string>
<string name="selinux_status_enforcing">Enforcing</string> <string name="selinux_status_enforcing">Enforcing</string>
@@ -38,13 +45,16 @@
<string name="module_empty">Brak zainstalowanych modułów</string> <string name="module_empty">Brak zainstalowanych modułów</string>
<string name="module">Moduły</string> <string name="module">Moduły</string>
<string name="module_install_prompt_with_name">Następujące moduły zostaną zainstalowane: %1$s</string> <string name="module_install_prompt_with_name">Następujące moduły zostaną zainstalowane: %1$s</string>
<string name="module_sort_a_to_z">Sortuj (A-Z)</string> <string name="module_sort_a_to_z">Sortuj (AZ)</string>
<string name="module_sort_z_to_a">Sortuj (Z-A)</string> <string name="module_sort_z_to_a">Sortuj (ZA)</string>
<string name="module_size_low_to_high">Sortuj (Najmniejszy → Największy)</string>
<string name="module_size_high_to_low">Sortuj (Największy → Najmniejszy)</string>
<string name="uninstall">Odinstaluj</string> <string name="uninstall">Odinstaluj</string>
<string name="restore">Przywróć</string> <string name="restore">Przywróć</string>
<string name="module_install">Zainstaluj</string> <string name="module_install">Zainstaluj</string>
<string name="install">Zainstaluj</string> <string name="install">Zainstaluj</string>
<string name="reboot">Reboot (uruchom ponownie)</string> <string name="reboot">Reboot (uruchom ponownie)</string>
<string name="uninstalled">Odinstalowany</string>
<string name="settings">Ustawienia</string> <string name="settings">Ustawienia</string>
<string name="reboot_userspace">Miękki reboot</string> <string name="reboot_userspace">Miękki reboot</string>
<string name="reboot_recovery">Reboot do trybu Recovery</string> <string name="reboot_recovery">Reboot do trybu Recovery</string>
@@ -96,6 +106,7 @@
<string name="proceed">Dalej</string> <string name="proceed">Dalej</string>
<string name="cancel">Anuluj</string> <string name="cancel">Anuluj</string>
<string name="later">Później</string> <string name="later">Później</string>
<string name="lkm_warning_message">Łatka LKM opiera się na komponentach o zamkniętym kodzie źródłowym. Czy chcesz kontynuować?</string>
<string name="home_next_kernelsu">🔥 Kompilacja Next</string> <string name="home_next_kernelsu">🔥 Kompilacja Next</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Eksperymentalna gałąź Next. Sprawdź na GitHub!</string> <string name="home_next_kernelsu_body">Eksperymentalna gałąź Next. Sprawdź na GitHub!</string>
@@ -129,6 +140,7 @@
<string name="profile_selinux_domain">Domena</string> <string name="profile_selinux_domain">Domena</string>
<string name="profile_selinux_rules">Reguły</string> <string name="profile_selinux_rules">Reguły</string>
<string name="module_update">Zaktualizuj</string> <string name="module_update">Zaktualizuj</string>
<string name="module_updated">Zaktualizowany</string>
<string name="module_downloading">Pobieranie modułu: %s</string> <string name="module_downloading">Pobieranie modułu: %s</string>
<string name="module_start_downloading">Rozpocznij pobieranie: %s</string> <string name="module_start_downloading">Rozpocznij pobieranie: %s</string>
<string name="new_version_available">Nowa wersja %s jest dostępna, kliknij, aby zaktualizować.</string> <string name="new_version_available">Nowa wersja %s jest dostępna, kliknij, aby zaktualizować.</string>
@@ -136,6 +148,10 @@
<string name="close">Zamknij</string> <string name="close">Zamknij</string>
<string name="force_stop_app">Wymuś zatrzymanie</string> <string name="force_stop_app">Wymuś zatrzymanie</string>
<string name="restart_app">Uruchom ponownie</string> <string name="restart_app">Uruchom ponownie</string>
<string name="settings_amoled_mode">Tryb AMOLED</string>
<string name="settings_amoled_mode_summary">Włącz czysto czarny motyw, przydatny dla ekranów AMOLED, aby zmniejszyć zmęczenie oczu oraz zużycie baterii.</string>
<string name="restart_required">Wymagany restart</string>
<string name="restart_app_message">Aplikacja wymaga ponownego uruchomienia, aby zmiana została uwzględniona.</string>
<string name="failed_to_update_sepolicy">Nie udało się zaktualizować reguł SELinux dla: %s</string> <string name="failed_to_update_sepolicy">Nie udało się zaktualizować reguł SELinux dla: %s</string>
<string name="su_not_allowed">Przyznanie uprawnień superusera nie jest dozwolone dla: %s</string> <string name="su_not_allowed">Przyznanie uprawnień superusera nie jest dozwolone dla: %s</string>
<string name="module_changelog">Dziennik zmian</string> <string name="module_changelog">Dziennik zmian</string>
@@ -165,6 +181,7 @@
<string name="settings_check_update_summary">Automatycznie sprawdzaj dostępność aktualizacji przy otwieraniu aplikacji.</string> <string name="settings_check_update_summary">Automatycznie sprawdzaj dostępność aktualizacji przy otwieraniu aplikacji.</string>
<string name="grant_root_failed">Nie udało się przyznać uprawnień roota!</string> <string name="grant_root_failed">Nie udało się przyznać uprawnień roota!</string>
<string name="action">Akcja</string> <string name="action">Akcja</string>
<string name="webui">WebUI</string>
<string name="open">Otwórz</string> <string name="open">Otwórz</string>
<string name="enable_web_debugging">Włącz debugowanie WebView</string> <string name="enable_web_debugging">Włącz debugowanie WebView</string>
<string name="enable_web_debugging_summary">Możesz użyć tej opcji w celu debugowania WebUI. Włącz tylko wtedy, gdy jest to potrzebne.</string> <string name="enable_web_debugging_summary">Możesz użyć tej opcji w celu debugowania WebUI. Włącz tylko wtedy, gdy jest to potrzebne.</string>
@@ -194,4 +211,15 @@
<string name="settings_disable_su">Wyłącz funkcjonalność su</string> <string name="settings_disable_su">Wyłącz funkcjonalność su</string>
<string name="settings_disable_su_summary">Tymczasowo wyłącz możliwość uzyskania uprawnień roota przez dowolną aplikację za pomocą polecenia su (nie będzie to miało wpływu na istniejące procesy roota).</string> <string name="settings_disable_su_summary">Tymczasowo wyłącz możliwość uzyskania uprawnień roota przez dowolną aplikację za pomocą polecenia su (nie będzie to miało wpływu na istniejące procesy roota).</string>
<string name="settings_language">Język</string> <string name="settings_language">Język</string>
<string name="settings_legacyui">Używaj starszego interfejsu użytkownika</string>
<string name="settings_legacyui_summary">Przełącz na poprzedni styl interfejsu użytkownika.</string>
<string name="settings_banner">Włącz banery</string>
<string name="settings_banner_summary">Pokazuj tła-banery dla modułów.</string>
<string name="use_webuix">Używaj WebUI X</string>
<string name="use_webuix_summary">Używaj WebUI X zamiast WebUI, który obsługuje więcej interfejsów API.</string>
<string name="use_webuix_eruda">Wstrzykuj Eruda do WebUI X</string>
<string name="use_webuix_eruda_summary">Wstrzyknij konsolę debugowania do WebUI X, aby ułatwić debugowanie. Wymagane jest aktywne debugowanie WebView.</string>
<string name="customization">Personalizacja</string>
<string name="developer">Programista</string>
<string name="sucompat_disabled">SUCOMPAT NIEAKTYWNY</string>
</resources> </resources>

View File

@@ -12,13 +12,19 @@
<string name="home">Início</string> <string name="home">Início</string>
<string name="home_not_installed">Não instalado</string> <string name="home_not_installed">Não instalado</string>
<string name="home_click_to_install">Clique para instalar</string> <string name="home_click_to_install">Clique para instalar</string>
<string name="lkm_mode_deprecated">O modo LKM agora está obsoleto!</string>
<string name="lkm_alternative_suggestion">Instale o kernel GKI ou integre o KernelSU Next ao seu dispositivo.</string>
<string name="home_working">Em execução</string> <string name="home_working">Em execução</string>
<string name="home_working_version">Versão: %d</string> <string name="home_working_version">Versão: %d</string>
<string name="home_superuser_count">SuperUsuários: %d</string> <string name="home_superuser_count">SuperUsuários: %d</string>
<string name="home_module_count">Módulos: %d</string> <string name="home_module_count">Módulos: %d</string>
<string name="home_module_update_count">Atualizações: %d</string>
<string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">Assinatura KernelSU Next v2 não encontrada no kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string> <string name="home_failure_tip">Peça ao seu desenvolvedor de kernel para integrar o KernelSU Next!</string>
<string name="home_kernel">Versão do kernel</string> <string name="home_kernel">Versão do kernel</string>
<string name="hook_mode">Modo do hook</string>
<string name="enable">Ativar</string>
<string name="disable">Desativar</string>
<string name="enabled">Ativado</string> <string name="enabled">Ativado</string>
<string name="disabled">Desativado</string> <string name="disabled">Desativado</string>
<string name="susfs_supported">Suportado</string> <string name="susfs_supported">Suportado</string>
@@ -27,6 +33,7 @@
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Versão do Android</string> <string name="home_android">Versão do Android</string>
<string name="home_manager_version">Versão do gerenciador</string> <string name="home_manager_version">Versão do gerenciador</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Status do SELinux</string> <string name="home_selinux_status">Status do SELinux</string>
<string name="selinux_status_disabled">Desativado</string> <string name="selinux_status_disabled">Desativado</string>
<string name="selinux_status_enforcing">Impondo</string> <string name="selinux_status_enforcing">Impondo</string>
@@ -38,13 +45,16 @@
<string name="module_empty">Nenhum módulo instalado</string> <string name="module_empty">Nenhum módulo instalado</string>
<string name="module">Módulo</string> <string name="module">Módulo</string>
<string name="module_install_prompt_with_name">Os seguintes módulos serão instalados: %1$s</string> <string name="module_install_prompt_with_name">Os seguintes módulos serão instalados: %1$s</string>
<string name="module_sort_a_to_z">Ordenar (A-Z)</string> <string name="module_sort_a_to_z">Ordenar (AZ)</string>
<string name="module_sort_z_to_a">Ordenar (Z-A)</string> <string name="module_sort_z_to_a">Ordenar (ZA)</string>
<string name="module_size_low_to_high">Ordenar (Menor → Maior)</string>
<string name="module_size_high_to_low">Ordenar (Maior → Menor)</string>
<string name="uninstall">Desinstalar</string> <string name="uninstall">Desinstalar</string>
<string name="restore">Restaurar</string> <string name="restore">Restaurar</string>
<string name="module_install">Instalar</string> <string name="module_install">Instalar</string>
<string name="install">Instalar</string> <string name="install">Instalar</string>
<string name="reboot">Reiniciar</string> <string name="reboot">Reiniciar</string>
<string name="uninstalled">Desinstalado</string>
<string name="settings">Configurações</string> <string name="settings">Configurações</string>
<string name="reboot_userspace">Reinicialização suave</string> <string name="reboot_userspace">Reinicialização suave</string>
<string name="reboot_recovery">Reiniciar em modo Recovery</string> <string name="reboot_recovery">Reiniciar em modo Recovery</string>
@@ -96,6 +106,7 @@
<string name="proceed">Prosseguir</string> <string name="proceed">Prosseguir</string>
<string name="cancel">Cancelar</string> <string name="cancel">Cancelar</string>
<string name="later">Mais tarde</string> <string name="later">Mais tarde</string>
<string name="lkm_warning_message">O patch LKM depende de componentes de código fechado. Deseja continuar?</string>
<string name="home_next_kernelsu">🔥 Compilação next</string> <string name="home_next_kernelsu">🔥 Compilação next</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string> <string name="home_next_kernelsu_body">Branch next experimental. Confira no GitHub!</string>
@@ -123,12 +134,13 @@
<string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string> <string name="require_kernel_version">A versão atual do KernelSU Next %1$d é muito baixa para o gerenciador funcionar corretamente. Por favor, atualize para a versão %2$d ou superior!</string>
<string name="settings_umount_modules_default">Desmontar módulos</string> <string name="settings_umount_modules_default">Desmontar módulos</string>
<string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string> <string name="settings_umount_modules_default_summary">O valor padrão global para \"Desmontar módulos\" em Perfil do Aplicativo. Se ativado, ele removerá todas as modificações do módulo no sistema para apps que não possuem um perfil definido.</string>
<string name="settings_susfs_toggle">Ocultar ganchos kprobe</string> <string name="settings_susfs_toggle">Ocultar hook kprobes</string>
<string name="settings_susfs_toggle_summary">Esta opção desativa os ganchos kprobe criados pelo ksu e, em vez disso, ativa os ganchos embutidos não-kprobe, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string> <string name="settings_susfs_toggle_summary">Esta opção desativa os hook kprobes criados pelo ksu e, em vez disso, ativa os hooks embutidos não-kprobes, implementando a mesma funcionalidade que seria aplicada a um kernel não-GKI, que não oferece suporte para kprobe.</string>
<string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string> <string name="profile_umount_modules_summary">Ativar esta opção permitirá que o KernelSU Next restaure quaisquer arquivos modificados pelos módulos para este app.</string>
<string name="profile_selinux_domain">Domínio</string> <string name="profile_selinux_domain">Domínio</string>
<string name="profile_selinux_rules">Regras</string> <string name="profile_selinux_rules">Regras</string>
<string name="module_update">Atualizar</string> <string name="module_update">Atualizar</string>
<string name="module_updated">Atualizado</string>
<string name="module_downloading">Baixando módulo %s</string> <string name="module_downloading">Baixando módulo %s</string>
<string name="module_start_downloading">Começando a baixar %s</string> <string name="module_start_downloading">Começando a baixar %s</string>
<string name="new_version_available">Nova versão %s está disponível, clique para atualizar.</string> <string name="new_version_available">Nova versão %s está disponível, clique para atualizar.</string>
@@ -136,6 +148,10 @@
<string name="close">Fechar</string> <string name="close">Fechar</string>
<string name="force_stop_app">Forçar parada</string> <string name="force_stop_app">Forçar parada</string>
<string name="restart_app">Reiniciar</string> <string name="restart_app">Reiniciar</string>
<string name="settings_amoled_mode">Modo AMOLED</string>
<string name="settings_amoled_mode_summary">Ative um tema preto puro útil para telas AMOLED para reduzir o cansaço visual e economizar bateria.</string>
<string name="restart_required">Reinicialização necessária</string>
<string name="restart_app_message">O app precisa ser reiniciado para que essa alteração tenha efeito.</string>
<string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para: %s</string> <string name="failed_to_update_sepolicy">Falha ao atualizar as regras do SELinux para: %s</string>
<string name="su_not_allowed">O acesso de SuperUsuário não é permitido para: %s</string> <string name="su_not_allowed">O acesso de SuperUsuário não é permitido para: %s</string>
<string name="module_changelog">Registro de alterações</string> <string name="module_changelog">Registro de alterações</string>
@@ -165,6 +181,7 @@
<string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string> <string name="settings_check_update_summary">Verifique automaticamente se há atualizações ao abrir o app</string>
<string name="grant_root_failed">Falha ao conceder acesso root!</string> <string name="grant_root_failed">Falha ao conceder acesso root!</string>
<string name="action">Ação</string> <string name="action">Ação</string>
<string name="webui">WebUI</string>
<string name="open">Abrir</string> <string name="open">Abrir</string>
<string name="enable_web_debugging">Ativar depuração do WebView</string> <string name="enable_web_debugging">Ativar depuração do WebView</string>
<string name="enable_web_debugging_summary">Pode ser usado para depurar o WebUI. Por favor, ative somente quando necessário.</string> <string name="enable_web_debugging_summary">Pode ser usado para depurar o WebUI. Por favor, ative somente quando necessário.</string>
@@ -194,4 +211,13 @@
<string name="settings_disable_su">Desativar compatibilidade su</string> <string name="settings_disable_su">Desativar compatibilidade su</string>
<string name="settings_disable_su_summary">Desative temporariamente a capacidade de qualquer app obter privilégios root por meio do comando su (processos root existentes não serão afetados).</string> <string name="settings_disable_su_summary">Desative temporariamente a capacidade de qualquer app obter privilégios root por meio do comando su (processos root existentes não serão afetados).</string>
<string name="settings_language">Idioma</string> <string name="settings_language">Idioma</string>
<string name="settings_legacyui">Usar IU antiga</string>
<string name="settings_legacyui_summary">Mude para o estilo de interface do usuário anterior.</string>
<string name="settings_banner">Ativar banners</string>
<string name="settings_banner_summary">Mostre banners de fundo para módulos.</string>
<string name="use_webuix">Usar WebUI X</string>
<string name="use_webuix_summary">Use o WebUI X em vez do WebUI, que oferece suporte a mais APIs.</string>
<string name="use_webuix_eruda">Injetar Eruda no WebUI X</string>
<string name="use_webuix_eruda_summary">Injeta um console de depuração no WebUI X para facilitar a depuração. Requer que a depuração web esteja ativada.</string>
<string name="customization">Personalização</string>
</resources> </resources>

View File

@@ -12,39 +12,49 @@
<string name="home">Главная</string> <string name="home">Главная</string>
<string name="home_not_installed">Не установлено</string> <string name="home_not_installed">Не установлено</string>
<string name="home_click_to_install">Нажмите, чтобы установить</string> <string name="home_click_to_install">Нажмите, чтобы установить</string>
<string name="lkm_mode_deprecated">Режим LKM теперь устарел!</string>
<string name="lkm_alternative_suggestion">Установите GKI ядро или интегрируйте ядра рядом с вашим устройством.</string>
<string name="home_working">Работает</string> <string name="home_working">Работает</string>
<string name="home_working_version">Версия: %d</string> <string name="home_working_version">Версия: %d</string>
<string name="home_superuser_count">Superusers: %d</string> <string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Модули: %d</string> <string name="home_module_count">Модули: %d</string>
<string name="home_module_update_count">Обновления: %d</string>
<string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [!KSU_NEXT || != size/hash]</string> <string name="home_failure">Подпись KernelSU Next v2 не найдена в ядре! [!KSU_NEXT || != size/hash]</string>
<string name="home_failure_tip">Попросите вашего разработчика ядра интегрировать KernelSU Next!</string> <string name="home_failure_tip">Попросите вашего разработчика ядра интегрировать KernelSU Next!</string>
<string name="home_kernel">Версия ядра</string> <string name="home_kernel">Версия ядра</string>
<string name="hook_mode">Режим хуков</string>
<string name="enable">Включить</string>
<string name="disable">Отключить</string>
<string name="disabled">Отключено</string> <string name="disabled">Отключено</string>
<string name="enabled">Включено</string> <string name="enabled">Включено</string>
<string name="susfs_supported">Поддерживается</string> <string name="susfs_supported">Доступно</string>
<string name="home_susfs">SuSFS: %s</string> <string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Версия SuSFS</string> <string name="home_susfs_version">Версия SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Версия Android</string> <string name="home_android">Версия Android</string>
<string name="home_manager_version">Версия менеджера</string> <string name="home_manager_version">Версия менеджера</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Статус SELinux</string> <string name="home_selinux_status">Статус SELinux</string>
<string name="selinux_status_disabled">Отключен</string> <string name="selinux_status_disabled">Отключен</string>
<string name="selinux_status_enforcing">Принудительный</string> <string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Разрешающий</string> <string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Неизвестно</string> <string name="selinux_status_unknown">Неизвестно</string>
<string name="superuser">SuperUser</string> <string name="superuser">Superuser</string>
<string name="module_failed_to_enable">Не удалось включить модуль: %s</string> <string name="module_failed_to_enable">Не удалось включить модуль: %s</string>
<string name="module_failed_to_disable">Не удалось отключить модуль: %s</string> <string name="module_failed_to_disable">Не удалось отключить модуль: %s</string>
<string name="module_empty">Нет установленных модулей</string> <string name="module_empty">Нет установленных модулей</string>
<string name="module">Модули</string> <string name="module">Модули</string>
<string name="module_install_prompt_with_name">Следующие модуль(и) будут установлены: %1$s</string> <string name="module_install_prompt_with_name">Следующие модуль(и) будут установлены: %1$s</string>
<string name="module_sort_a_to_z">Сортировать (А-Я)</string> <string name="module_sort_a_to_z">Сортировать (АЯ)</string>
<string name="module_sort_z_to_a">Сортировать (Я-А)</string> <string name="module_sort_z_to_a">Сортировать (ЯА)</string>
<string name="module_size_low_to_high">Сортировать (Низкий → Высокий)</string>
<string name="module_size_high_to_low">Сортировать (Высокий → Низкий)</string>
<string name="uninstall">Удалить</string> <string name="uninstall">Удалить</string>
<string name="restore">Восстановить</string> <string name="restore">Восстановить</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="uninstalled">Удалено</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>
@@ -60,11 +70,11 @@
<string name="module_restore_failed">Не удалось восстановить: %s</string> <string name="module_restore_failed">Не удалось восстановить: %s</string>
<string name="module_version">Версия</string> <string name="module_version">Версия</string>
<string name="module_author">Автор</string> <string name="module_author">Автор</string>
<string name="module_id">Идентификатор</string> <string name="module_id">ID</string>
<string name="module_version_code">Код версии</string> <string name="module_version_code">Код версии</string>
<string name="module_update_json">UpdateJson</string> <string name="module_update_json">UpdateJson</string>
<string name="module_update_json_empty">Пусто</string> <string name="module_update_json_empty">Пусто</string>
<string name="enable_developer_options">Включить настройки разработчика</string> <string name="enable_developer_options">Режим разработчика</string>
<string name="enable_developer_options_summary">Показывать скрытые настройки и отладочную информацию, актуальную только для разработчиков.</string> <string name="enable_developer_options_summary">Показывать скрытые настройки и отладочную информацию, актуальную только для разработчиков.</string>
<string name="module_overlay_fs_not_available">Модули недоступны, так как OverlayFS отключен ядром.</string> <string name="module_overlay_fs_not_available">Модули недоступны, так как OverlayFS отключен ядром.</string>
<string name="refresh">Обновить</string> <string name="refresh">Обновить</string>
@@ -74,28 +84,29 @@
<string name="safe_mode">Безопасный режим</string> <string name="safe_mode">Безопасный режим</string>
<string name="reboot_to_apply">Перезагрузите для применения</string> <string name="reboot_to_apply">Перезагрузите для применения</string>
<string name="module_magisk_conflict">Модули недоступны из-за конфликта с Magisk!</string> <string name="module_magisk_conflict">Модули недоступны из-за конфликта с Magisk!</string>
<string name="home_mount_system">Система монтирования модулей</string> <string name="home_mount_system">Система монтирования</string>
<string name="home_magic_mount">Magic Mount</string> <string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string> <string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">Недоступно</string> <string name="unavailable">Недоступно</string>
<string name="use_overlay_fs">Использовать OverlayFS (Бета)</string> <string name="use_overlay_fs">Использовать OverlayFS</string>
<string name="use_overlay_fs_summary">Переключение между использованием OverlayFS и Magic Mount для системы монтирования KernelSU Next.</string> <string name="use_overlay_fs_summary">Переключение между использованием OverlayFS и Magic Mount для системы монтирования KernelSU Next.</string>
<string name="reboot_required">Требуется перезагрузка</string> <string name="reboot_required">Требуется перезагрузка</string>
<string name="reboot_message">Изменения вступят в силу после перезагрузки системы. Перезагрузить сейчас?</string> <string name="reboot_message">Изменения вступят в силу после перезагрузки системы. Перезагрузить сейчас?</string>
<string name="module_restore">Восстановить модуль</string> <string name="module_restore">Восстановить модули</string>
<string name="module_restore_message">Восстановление модулей из последней резервной копии.</string> <string name="module_restore_message">Восстановление модулей из последней резервной копии.</string>
<string name="backup_restore">Резервное копирование и восстановление</string> <string name="backup_restore">Бэкапы и восстановление</string>
<string name="module_backup">Резервное копирование модуля</string> <string name="module_backup">Бэкап модулей</string>
<string name="module_backup_message">Резервное копирование текущих установленных модулей.</string> <string name="module_backup_message">Резервное копирование текущих установленных модулей.</string>
<string name="allowlist_restore">Восстановить список разрешений</string> <string name="allowlist_restore">Восстановить список разрешений</string>
<string name="allowlist_restore_message">Восстановить список разрешений из последнего резервного копирования.</string> <string name="allowlist_restore_message">Восстановить список разрешений из последнего резервного копирования.</string>
<string name="allowlist_backup">Создать резервную копию списка разрешений</string> <string name="allowlist_backup">Бэкап списка разрешений</string>
<string name="allowlist_backup_message">Создать резервную копию текущего списка разрешений.</string> <string name="allowlist_backup_message">Резервное копирование текущего списка разрешений.</string>
<string name="warning">Предупреждение</string> <string name="warning">Предупреждение</string>
<string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string> <string name="warning_message">Эта функция всё ещё находится в стадии бета-тестирования. Пожалуйста, убедитесь, что вы создали резервные копии модулей перед использованием. Используйте это только если понимаете возможные риски. Будьте осторожны.</string>
<string name="proceed">Продолжить</string> <string name="proceed">Продолжить</string>
<string name="cancel">Отмена</string> <string name="cancel">Отмена</string>
<string name="later">Позже</string> <string name="later">Позже</string>
<string name="lkm_warning_message">Патч LKM использует компоненты с закрытым исходным кодом. Хотите продолжить?</string>
<string name="home_next_kernelsu">🔥 Следующий билд</string> <string name="home_next_kernelsu">🔥 Следующий билд</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Следующая экспериментальная ветка. Посмотрите на GitHub!</string> <string name="home_next_kernelsu_body">Следующая экспериментальная ветка. Посмотрите на GitHub!</string>
@@ -105,11 +116,11 @@
<string name="home_experimental_kernelsu_body_point_1"> • Используйте на свой страх и риск: могут возникнуть сбои, непредвиденное поведение или проблемы с системой.</string> <string name="home_experimental_kernelsu_body_point_1"> • Используйте на свой страх и риск: могут возникнуть сбои, непредвиденное поведение или проблемы с системой.</string>
<string name="home_experimental_kernelsu_body_point_2"> • Предупреждение: разработчики не несут ответственности за потерю данных, повреждение системы или другие последствия, вызванные использованием.</string> <string name="home_experimental_kernelsu_body_point_2"> • Предупреждение: разработчики не несут ответственности за потерю данных, повреждение системы или другие последствия, вызванные использованием.</string>
<string name="home_experimental_kernelsu_body_point_3"> • Только для тестирования: предназначено для пользователей, которые понимают риски и готовы решать возникающие проблемы.</string> <string name="home_experimental_kernelsu_body_point_3"> • Только для тестирования: предназначено для пользователей, которые понимают риски и готовы решать возникающие проблемы.</string>
<string name="about_source_code"><![CDATA[Посмотреть исходный код на %1$s]]></string> <string name="about_source_code"><![CDATA[Исходный код на %1$s]]></string>
<string name="profile" translatable="false">Профиль приложения</string> <string name="profile" translatable="false">Профиль Приложения</string>
<string name="profile_default">По умолчанию</string> <string name="profile_default">По умолчанию</string>
<string name="profile_template">Шаблон</string> <string name="profile_template">Шаблон</string>
<string name="profile_custom">Пользовательский</string> <string name="profile_custom">Настроить</string>
<string name="profile_name">Имя профиля</string> <string name="profile_name">Имя профиля</string>
<string name="profile_namespace">Пространство монтирования</string> <string name="profile_namespace">Пространство монтирования</string>
<string name="profile_namespace_inherited">Унаследовано</string> <string name="profile_namespace_inherited">Унаследовано</string>
@@ -119,16 +130,17 @@
<string name="profile_capabilities">Возможности</string> <string name="profile_capabilities">Возможности</string>
<string name="profile_selinux_context">Контекст SELinux</string> <string name="profile_selinux_context">Контекст SELinux</string>
<string name="profile_umount_modules">Отключить модули</string> <string name="profile_umount_modules">Отключить модули</string>
<string name="failed_to_update_app_profile">Не удалось обновить профиль приложения для %s</string> <string name="failed_to_update_app_profile">Не удалось обновить Профиль Приложения для %s</string>
<string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string> <string name="require_kernel_version">Текущая версия KernelSU Next %1$d слишком низкая для корректной работы менеджера. Пожалуйста, обновитесь до версии %2$d или выше!</string>
<string name="settings_umount_modules_default">Отмонтировать модули</string> <string name="settings_umount_modules_default">Отключить модули</string>
<string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в профиле приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string> <string name="settings_umount_modules_default_summary">Глобальное значение по умолчанию для \"Отключить модули\" в Профиле Приложения. Если включено, это удалит все модификации системы модулями для приложений без установленного профиля.</string>
<string name="settings_susfs_toggle">Скрыть хуки kprobe</string> <string name="settings_susfs_toggle">Скрыть хук kprobes</string>
<string name="settings_susfs_toggle_summary">Отключает хуки kprobe, созданные ksu, и вместо этого активирует встроенные функции, реализующие ту же функциональность для ядер, которые не поддерживают kprobe.</string> <string name="settings_susfs_toggle_summary">Эта опция отключает хук kprobes, созданный ksu, и вместо него активирует встроенный хук без использования kprobes, реализующий ту же функциональность, которая применяется к ядрам без GKI, не поддерживающим kprobe.</string>
<string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string> <string name="profile_umount_modules_summary">Включение этой опции позволит KernelSU Next восстанавливать любые изменённые модулями файлы для этого приложения.</string>
<string name="profile_selinux_domain">Домен</string> <string name="profile_selinux_domain">Домен</string>
<string name="profile_selinux_rules">Правила</string> <string name="profile_selinux_rules">Правила</string>
<string name="module_update">Обновить</string> <string name="module_update">Обновить</string>
<string name="module_updated">Обновлено</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>
@@ -136,11 +148,15 @@
<string name="close">Закрыть</string> <string name="close">Закрыть</string>
<string name="force_stop_app">Принудительно остановить</string> <string name="force_stop_app">Принудительно остановить</string>
<string name="restart_app">Перезапустить</string> <string name="restart_app">Перезапустить</string>
<string name="settings_amoled_mode">Режим AMOLED</string>
<string name="settings_amoled_mode_summary">Включить полностью тёмную тему, оптимизированную для дисплеев AMOLED, чтобы снизить зрительную нагрузку и сэкономить заряд аккумулятора.</string>
<string name="restart_required">Требуется перезапуск</string>
<string name="restart_app_message">Чтобы изменения вступили в силу, необходимо перезапустить приложение.</string>
<string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для: %s</string> <string name="failed_to_update_sepolicy">Не удалось обновить правила SELinux для: %s</string>
<string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string> <string name="su_not_allowed">Предоставление прав суперпользователя запрещено для: %s</string>
<string name="module_changelog">Журнал изменений</string> <string name="module_changelog">Журнал изменений</string>
<string name="settings_profile_template">Шаблон профиля приложений</string> <string name="settings_profile_template">Шаблон Профиля Приложений</string>
<string name="settings_profile_template_summary">Управление локальными и онлайн-шаблонами профилей приложений</string> <string name="settings_profile_template_summary">Управление локальными и онлайн шаблонами Профилей Приложений</string>
<string name="app_profile_template_create">Создать шаблон</string> <string name="app_profile_template_create">Создать шаблон</string>
<string name="app_profile_template_edit">Редактировать шаблон</string> <string name="app_profile_template_edit">Редактировать шаблон</string>
<string name="app_profile_template_id">Идентификатор</string> <string name="app_profile_template_id">Идентификатор</string>
@@ -161,16 +177,17 @@
<string name="app_profile_template_save_failed">Не удалось сохранить шаблон</string> <string name="app_profile_template_save_failed">Не удалось сохранить шаблон</string>
<string name="app_profile_template_import_empty">Буфер обмена пуст!</string> <string name="app_profile_template_import_empty">Буфер обмена пуст!</string>
<string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string> <string name="module_changelog_failed">Не удалось получить журнал изменений: %s</string>
<string name="settings_check_update">Проверить обновления</string> <string name="settings_check_update">Проверять обновления</string>
<string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string> <string name="settings_check_update_summary">Автоматически проверять обновления при открытии приложения.</string>
<string name="grant_root_failed">Не удалось предоставить root-доступ!</string> <string name="grant_root_failed">Не удалось предоставить root-доступ!</string>
<string name="action">Действие</string> <string name="action">Запустить</string>
<string name="webui">WebUI</string>
<string name="open">Открыть</string> <string name="open">Открыть</string>
<string name="enable_web_debugging">Включить отладку WebView</string> <string name="enable_web_debugging">Отладка WebView</string>
<string name="enable_web_debugging_summary">Можно использовать для отладки WebUI. Включайте только при необходимости.</string> <string name="enable_web_debugging_summary">Можно использовать для отладки WebUI. Включайте только при необходимости.</string>
<string name="direct_install">Прямая установка (Рекомендуется)</string> <string name="direct_install">Прямая установка (Рекомендуется)</string>
<string name="select_file">Выберите файл</string> <string name="select_file">Выберите файл</string>
<string name="install_inactive_slot">Установить в неактивный слот (После OTA)</string> <string name="install_inactive_slot">В неактивный слот (После OTA)</string>
<string name="install_inactive_slot_warning">Ваше устройство будет **ПРИНУДИТЕЛЬНО** загружено в текущий неактивный слот после перезагрузки!\nИспользуйте эту опцию только после завершения OTA.\nПродолжить?</string> <string name="install_inactive_slot_warning">Ваше устройство будет **ПРИНУДИТЕЛЬНО** загружено в текущий неактивный слот после перезагрузки!\nИспользуйте эту опцию только после завершения OTA.\nПродолжить?</string>
<string name="install_next">Далее</string> <string name="install_next">Далее</string>
<string name="select_file_tip">Рекомендуется образ раздела %1$s</string> <string name="select_file_tip">Рекомендуется образ раздела %1$s</string>
@@ -191,6 +208,14 @@
<string name="save_log">Сохранить логи</string> <string name="save_log">Сохранить логи</string>
<string name="log_saved">Логи сохранены</string> <string name="log_saved">Логи сохранены</string>
<string name="send_log">Поделиться логами</string> <string name="send_log">Поделиться логами</string>
<string name="settings_disable_su">Отключить совместимость с su</string> <string name="settings_disable_su">Откл. совместимость с su</string>
<string name="settings_disable_su_summary">Временно отключить возможность приложениям получать права root через команду su (существующие сеансы с правами root не будут затронуты).</string> <string name="settings_disable_su_summary">Временно отключить возможность приложениям получать права root через команду su (существующие процессы с правами root не будут затронуты).</string>
<string name="settings_language">Язык</string>
<string name="settings_legacyui">Использовать старый UI</string>
<string name="settings_legacyui_summary">Переключиться на предыдущий стиль интерфейса.</string>
<string name="use_webuix">Использовать WebUI X</string>
<string name="use_webuix_summary">Использовать WebUI X вместо WebUI, который поддерживает больше API.</string>
<string name="use_webuix_eruda">Инжект Eruda в WebUI X</string>
<string name="use_webuix_eruda_summary">Инжектить консоль отладки в WebUI X, чтобы упростить отладку. Требуется включить отладку WebView.</string>
<string name="customization">Кастомизация</string>
</resources> </resources>

View File

@@ -109,8 +109,8 @@
<string name="require_kernel_version">KernelSU Next เวอร์ชัน %1$d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถทำงานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชัน %2$d หรือสูงกว่า!</string> <string name="require_kernel_version">KernelSU Next เวอร์ชัน %1$d ต่ำเกินไป ทำให้ตัวจัดการไม่สามารถทำงานได้อย่างถูกต้อง โปรดอัปเกรดเป็นเวอร์ชัน %2$d หรือสูงกว่า!</string>
<string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string> <string name="settings_umount_modules_default">Umount โมดูลตามค่าเริ่มต้น</string>
<string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string> <string name="settings_umount_modules_default_summary">หากเปิดใช้งานค่าเริ่มต้นโดยทั่วไปสำหรับ \"Umount โมดูล\" ในโปรไฟล์แอป จะเป็นการลบการแก้ไขโมดูลทั้งหมดในระบบสำหรับแอปพลิเคชันที่ไม่มีการตั้งค่าโปรไฟล์</string>
<string name="settings_susfs_toggle">ซ่อน kprobe hooks</string> <string name="settings_susfs_toggle">ซ่อน kprobes hook</string>
<string name="settings_susfs_toggle_summary">จะปิดใช้งาน kprobe hooks ที่สร้างโดย ksu และเปิดใช้งาน non-kprobe hooks ที่ฝังไว้แทน โดยใช้ฟังก์ชันการทำงานเดียวกันกับที่ใช้กับเคอร์เนลที่ไม่ใช่ GKI ซึ่งไม่รองรับ</string> <string name="settings_susfs_toggle_summary">จะปิดใช้งาน kprobes hook ที่สร้างโดย ksu และเปิดใช้งาน non-kprobes hook ที่ฝังไว้แทน โดยใช้ฟังก์ชันการทำงานเดียวกันกับที่ใช้กับเคอร์เนลที่ไม่ใช่ GKI ซึ่งไม่รองรับ</string>
<string name="profile_umount_modules_summary">การเปิดใช้งานตัวเลือกนี้จะทำให้ KernelSU Next สามารถกู้คืนไฟล์ที่แก้ไขโดยโมดูลสำหรับแอปนี้ได้</string> <string name="profile_umount_modules_summary">การเปิดใช้งานตัวเลือกนี้จะทำให้ KernelSU Next สามารถกู้คืนไฟล์ที่แก้ไขโดยโมดูลสำหรับแอปนี้ได้</string>
<string name="profile_selinux_domain">โดเมน</string> <string name="profile_selinux_domain">โดเมน</string>
<string name="profile_selinux_rules">กฎ</string> <string name="profile_selinux_rules">กฎ</string>

View File

@@ -12,13 +12,19 @@
<string name="home">Ana Sayfa</string> <string name="home">Ana Sayfa</string>
<string name="home_not_installed">Yüklü değil</string> <string name="home_not_installed">Yüklü değil</string>
<string name="home_click_to_install">Yüklemek için tıklayın</string> <string name="home_click_to_install">Yüklemek için tıklayın</string>
<string name="lkm_mode_deprecated">LKM modu artık kullanımdan kaldırıldı!</string>
<string name="lkm_alternative_suggestion">GKI çekirdeğini kurun veya cihazınıza KernelSU Next entegre edin.</string>
<string name="home_working">Çalışıyor</string> <string name="home_working">Çalışıyor</string>
<string name="home_working_version">Sürüm: %d</string> <string name="home_working_version">Sürüm: %d</string>
<string name="home_superuser_count">Süper kullanıcılar: %d</string> <string name="home_superuser_count">Süper kullanıcılar: %d</string>
<string name="home_module_count">Modüller: %d</string> <string name="home_module_count">Modüller: %d</string>
<string name="home_module_update_count">Güncellemeler: %d</string>
<string name="home_failure">Kernel\'de KernelSU Next v2 imzası bulunamadı! [ !KSU_NEXT || != boyut/hash ]</string> <string name="home_failure">Kernel\'de KernelSU Next v2 imzası bulunamadı! [ !KSU_NEXT || != boyut/hash ]</string>
<string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmesini isteyin!</string> <string name="home_failure_tip">Kernel geliştiricinizden KernelSU Next\'i entegre etmesini isteyin!</string>
<string name="home_kernel">Kernel sürümü</string> <string name="home_kernel">Kernel sürümü</string>
<string name="hook_mode">Kanca Modu</string>
<string name="enable">Etkinleştir</string>
<string name="disable">Devre Dışı Bırak</string>
<string name="enabled">Etkin</string> <string name="enabled">Etkin</string>
<string name="disabled">Devre dışı</string> <string name="disabled">Devre dışı</string>
<string name="susfs_supported">Destekleniyor</string> <string name="susfs_supported">Destekleniyor</string>
@@ -27,6 +33,7 @@
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android sürümü</string> <string name="home_android">Android sürümü</string>
<string name="home_manager_version">Yönetici sürümü</string> <string name="home_manager_version">Yönetici sürümü</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">SELinux durumu</string> <string name="home_selinux_status">SELinux durumu</string>
<string name="selinux_status_disabled">Devre dışı</string> <string name="selinux_status_disabled">Devre dışı</string>
<string name="selinux_status_enforcing">Etkin (Enforcing)</string> <string name="selinux_status_enforcing">Etkin (Enforcing)</string>
@@ -45,6 +52,7 @@
<string name="module_install">Yükle</string> <string name="module_install">Yükle</string>
<string name="install">Yükle</string> <string name="install">Yükle</string>
<string name="reboot">Yeniden Başlat</string> <string name="reboot">Yeniden Başlat</string>
<string name="uninstalled">Kaldırıldı</string>
<string name="settings">Ayarlar</string> <string name="settings">Ayarlar</string>
<string name="reboot_userspace">Yumuşak Yeniden Başlat</string> <string name="reboot_userspace">Yumuşak Yeniden Başlat</string>
<string name="reboot_recovery">Kurtarma Moduna Yeniden Başlat</string> <string name="reboot_recovery">Kurtarma Moduna Yeniden Başlat</string>
@@ -96,6 +104,7 @@
<string name="proceed">Devam Et</string> <string name="proceed">Devam Et</string>
<string name="cancel">İptal</string> <string name="cancel">İptal</string>
<string name="later">Daha Sonra</string> <string name="later">Daha Sonra</string>
<string name="lkm_warning_message">LKM yaması, kapalı kaynak bileşenlere dayanır. Devam etmek istiyor musunuz?</string>
<string name="home_next_kernelsu">🔥 Yeni Sürüm</string> <string name="home_next_kernelsu">🔥 Yeni Sürüm</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Son deneysel dal. GitHub\'da kontrol edin!</string> <string name="home_next_kernelsu_body">Son deneysel dal. GitHub\'da kontrol edin!</string>
@@ -129,6 +138,7 @@
<string name="profile_selinux_domain">Etki Alanı</string> <string name="profile_selinux_domain">Etki Alanı</string>
<string name="profile_selinux_rules">Kurallar</string> <string name="profile_selinux_rules">Kurallar</string>
<string name="module_update">Güncelle</string> <string name="module_update">Güncelle</string>
<string name="module_updated">Güncellendi</string>
<string name="module_downloading">Modül indiriliyor: %s</string> <string name="module_downloading">Modül indiriliyor: %s</string>
<string name="module_start_downloading">İndirmeye başla: %s</string> <string name="module_start_downloading">İndirmeye başla: %s</string>
<string name="new_version_available">%s sürümü mevcut, yükseltmek için tıklayın.</string> <string name="new_version_available">%s sürümü mevcut, yükseltmek için tıklayın.</string>
@@ -136,6 +146,10 @@
<string name="close">Kapat</string> <string name="close">Kapat</string>
<string name="force_stop_app">Zorla durdur</string> <string name="force_stop_app">Zorla durdur</string>
<string name="restart_app">Yeniden Başlat</string> <string name="restart_app">Yeniden Başlat</string>
<string name="settings_amoled_mode">AMOLED modu</string>
<string name="settings_amoled_mode_summary">Göz yorgunluğunu azaltmak ve pil tasarrufu sağlamak için AMOLED ekranlara uygun saf siyah tema etkinleştirilir.</string>
<string name="restart_required">Yeniden Başlatma Gerekli</string>
<string name="restart_app_message">Bu değişikliğin etkili olması için uygulamanın yeniden başlatılması gerekiyor.</string>
<string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi.</string> <string name="failed_to_update_sepolicy">%s için SELinux kuralları güncellenemedi.</string>
<string name="su_not_allowed">SüperKullanıcı yetkisi verilemez: %s</string> <string name="su_not_allowed">SüperKullanıcı yetkisi verilemez: %s</string>
<string name="module_changelog">Değişiklik Günlüğü</string> <string name="module_changelog">Değişiklik Günlüğü</string>
@@ -165,6 +179,7 @@
<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">Eylem</string> <string name="action">Eylem</string>
<string name="webui">WebUI</string>
<string name="open"></string> <string name="open"></string>
<string name="enable_web_debugging">WebView hata ayıklamasını etkinleştir</string> <string name="enable_web_debugging">WebView hata ayıklamasını etkinleştir</string>
<string name="enable_web_debugging_summary">WebUI hata ayıklaması için kullanılabilir. Lütfen yalnızca gerekli olduğunda etkinleştirin.</string> <string name="enable_web_debugging_summary">WebUI hata ayıklaması için kullanılabilir. Lütfen yalnızca gerekli olduğunda etkinleştirin.</string>
@@ -194,4 +209,11 @@
<string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string> <string name="settings_disable_su">Su uyumluluğunu devre dışı bırak</string>
<string name="settings_disable_su_summary">Geçici olarak herhangi bir uygulamanın su komutu aracılığıyla kök ayrıcalıkları elde etme yeteneğini devre dışı bırakır (mevcut kök süreçleri etkilenmez).</string> <string name="settings_disable_su_summary">Geçici olarak herhangi bir uygulamanın su komutu aracılığıyla kök ayrıcalıkları elde etme yeteneğini devre dışı bırakır (mevcut kök süreçleri etkilenmez).</string>
<string name="settings_language">Dil</string> <string name="settings_language">Dil</string>
<string name="settings_legacyui">Eski Arayüzü Kullan</string>
<string name="settings_legacyui_summary">Önceki kullanıcı arayüzü stiline geç.</string>
<string name="use_webuix">WebUI X\'i kullanın</string>
<string name="use_webuix_summary">Daha fazla API\'yi destekleyen WebUI yerine WebUI X kullanın</string>
<string name="use_webuix_eruda">WebUI X\'e Eruda Enjekte Et</string>
<string name="use_webuix_eruda_summary">Hata ayıklamayı kolaylaştırmak için WebUI X\'e bir debug konsolu enjekte edin. Web hata ayıklamanın açık olması gerekir.</string>
<string name="customization">Özelleştirme</string>
</resources> </resources>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="issue_report_title">Виникли проблеми?</string>
<string name="issue_report_body">Виявлено помилку або є зворотній зв’язок?</string>
<string name="issue_report_body_2">Повідомте про це якнайшвидше!</string>
<string name="issue_report_github">Повідомити на GitHub</string>
<string name="issue_report_telegram">Зв’язатися через Telegram</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Підтвердити</string>
<string name="app_name" translatable="false">KernelSU Next</string>
<string name="home">Головна</string>
<string name="home_not_installed">Не встановлено</string>
<string name="home_click_to_install">Натисніть, щоб встановити</string>
<string name="lkm_mode_deprecated">Режим LKM тепер застарілий!</string>
<string name="lkm_alternative_suggestion">Встановіть ядро GKI або інтегруйте ядра поруч із вашим пристроєм.</string>
<string name="home_working">Працює</string>
<string name="home_working_version">Версія: %d</string>
<string name="home_superuser_count">SuperUsers: %d</string>
<string name="home_module_count">Модулі: %d</string>
<string name="home_module_update_count">Оновлення: %d</string>
<string name="home_failure">Підпис KernelSU Next v2 не знайдено в ядрі! [!KSU_NEXT || != size/hash]</string>
<string name="home_failure_tip">Попросіть вашого розробника ядра інтегрувати KernelSU Next!</string>
<string name="home_kernel">Версія ядра</string>
<string name="hook_mode">Режим хуків</string>
<string name="disabled">Вимкнено</string>
<string name="enabled">Увімкнено</string>
<string name="susfs_supported">Доступно</string>
<string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Версія SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Версія Android</string>
<string name="home_manager_version">Версія менеджера</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">Статус SELinux</string>
<string name="selinux_status_disabled">Вимкнено</string>
<string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Невідомо</string>
<string name="superuser">SuperUser</string>
<string name="module_failed_to_enable">Не вдалося увімкнути модуль: %s</string>
<string name="module_failed_to_disable">Не вдалося вимкнути модуль: %s</string>
<string name="module_empty">Нема встановлених модулів</string>
<string name="module">Модулі</string>
<string name="module_install_prompt_with_name">Наступні модуль(і) будуть встановлені: %1$s</string>
<string name="module_sort_a_to_z">Сортувати (А-Я)</string>
<string name="module_sort_z_to_a">Сортувати (Я-А)</string>
<string name="module_size_low_to_high">Сортувати (Низький → Великий)</string>
<string name="module_size_high_to_low">Сортувати (Великий → Низький)</string>
<string name="uninstall">Видалити</string>
<string name="restore">Відновити</string>
<string name="module_install">Встановити</string>
<string name="install">Встановити</string>
<string name="reboot">Перезавантаження</string>
<string name="uninstalled">Видалено</string>
<string name="settings">Налаштування</string>
<string name="reboot_userspace">М’яка перезавантаження</string>
<string name="reboot_recovery">Перезавантаження в Recovery</string>
<string name="reboot_bootloader">Перезавантаження в Bootloader</string>
<string name="reboot_download">Перезавантаження в Download</string>
<string name="reboot_edl">Перезавантаження в EDL</string>
<string name="about">Про програму</string>
<string name="module_uninstall_confirm">Ви впевнені, що хочете видалити модуль %s?</string>
<string name="module_uninstall_success">%s видалено</string>
<string name="module_uninstall_failed">Не вдалося видалити: %s</string>
<string name="module_restore_confirm">Ви впевнені, що хочете відновити модуль %s?</string>
<string name="module_restore_success">%s відновлено</string>
<string name="module_restore_failed">Не вдалося відновити: %s</string>
<string name="module_version">Версія</string>
<string name="module_author">Автор</string>
<string name="module_id">ID</string>
<string name="module_version_code">Код версії</string>
<string name="module_update_json">UpdateJson</string>
<string name="module_update_json_empty">Порожньо</string>
<string name="enable_developer_options">Режим розробника</string>
<string name="enable_developer_options_summary">Показувати приховані налаштування і відладкову інформацію, актуальну лише для розробників.</string>
<string name="module_overlay_fs_not_available">Модулі недоступні, оскільки OverlayFS вимкнено ядром.</string>
<string name="refresh">Оновити</string>
<string name="show_system_apps">Показати системні додатки</string>
<string name="hide_system_apps">Сховати системні додатки</string>
<string name="export_log">Експорт логів</string>
<string name="safe_mode">Безпечний режим</string>
<string name="reboot_to_apply">Перезавантажте для застосування</string>
<string name="module_magisk_conflict">Модулі недоступні через конфлікт з Magisk!</string>
<string name="home_mount_system">Система монтування</string>
<string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">Недоступно</string>
<string name="use_overlay_fs">Використовувати OverlayFS</string>
<string name="use_overlay_fs_summary">Перемикання між використанням OverlayFS и Magic Mount для системи монтування KernelSU Next.</string>
<string name="reboot_required">Потрібно перезавантаження</string>
<string name="reboot_message">Зміни вступлять в силу після перезавантаження системи. Перезавантажити зараз?</string>
<string name="module_restore">Відновити модуль</string>
<string name="module_restore_message">Відновлення модулів із останнього бекапу.</string>
<string name="backup_restore">Бекап і відновлення</string>
<string name="module_backup">Бекап модуля</string>
<string name="module_backup_message">Бекап поточних встановлених модулів.</string>
<string name="allowlist_restore">Відновити список дозволів</string>
<string name="allowlist_restore_message">Відновити список дозволів із останнього бекапу.</string>
<string name="allowlist_backup">Бекап списку дозволів</string>
<string name="allowlist_backup_message">Бекап поточного списку дозволів.</string>
<string name="warning">Попередження</string>
<string name="warning_message">Ця функція все ще перебуває у стадії бета-тестування. Будь ласка, переконайтеся, що ви створили бекап модулів перед використанням. Використовуйте це лише якщо розумієте можливі ризики. Будьте обережні.</string>
<string name="proceed">Продовжити</string>
<string name="cancel">Скасувати</string>
<string name="later">Пізніше</string>
<string name="lkm_warning_message">Патч LKM базується на компонентах із закритим кодом. Продовжити?</string>
<string name="home_next_kernelsu">🔥 Наступна збірка</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Наступна експериментальна гілка. Подивіться на GitHub!</string>
<string name="home_experimental_kernelsu">⚠️ Попередження про експериментальну розробку!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next — це неофіційна версія, яка завжди перебуває у стадії активної експериментальної розробки. Вона надається як є, без гарантій стабільності, продуктивності чи надійності.</string>
<string name="home_experimental_kernelsu_body_point_1"> • Використовуйте на свій страх і ризик: можуть виникати збої, несподівана поведінка або проблеми з системою.</string>
<string name="home_experimental_kernelsu_body_point_2"> • Попередження: розробники не несуть відповідальності за втрату даних, пошкодження системи або інші наслідки, викликані використанням.</string>
<string name="home_experimental_kernelsu_body_point_3"> • Лише для тестування: призначено для користувачів, які розуміють ризики і готові вирішувати виникаючі проблеми.</string>
<string name="about_source_code"><![CDATA[Вихідний код на %1$s]]></string>
<string name="profile" translatable="false">Профіль додатка</string>
<string name="profile_default">За замовчуванням</string>
<string name="profile_template">Шаблон</string>
<string name="profile_custom">Налаштувати</string>
<string name="profile_name">Ім’я профілю</string>
<string name="profile_namespace">Простір монтування</string>
<string name="profile_namespace_inherited">Успадковано</string>
<string name="profile_namespace_global">Глобальне</string>
<string name="profile_namespace_individual">Індивідуальне</string>
<string name="profile_groups">Групи</string>
<string name="profile_capabilities">Можливості</string>
<string name="profile_selinux_context">Контекст SELinux</string>
<string name="profile_umount_modules">Вимкнути модулі</string>
<string name="failed_to_update_app_profile">Не вдалося оновити Профіль додатка для %s</string>
<string name="require_kernel_version">Поточна версія KernelSU Next %1$d надто низька для коректної роботи менеджера. Будь ласка, оновіться до версії %2$d або вище!</string>
<string name="settings_umount_modules_default">Вимкнути модулі</string>
<string name="settings_umount_modules_default_summary">Глобальне значення за замовчуванням для \"Вимкнути модулі\" у Профілі додатка. Якщо увімкнено, це видалить усі модифікації системи модулями для додатків без встановленого профілю.</string>
<string name="settings_susfs_toggle">Сховати хуки kprobe</string>
<string name="settings_susfs_toggle_summary">Вимикає хуки kprobe, створені ksu, і замість цього активує вбудовані функції, що реалізують ту ж функціональність для ядер, які не підтримують kprobe.</string>
<string name="profile_umount_modules_summary">Увімкнення цієї опції дозволить KernelSU Next відновлювати будь-які змінені модулями файли для цього додатка.</string>
<string name="profile_selinux_domain">Домен</string>
<string name="profile_selinux_rules">Правила</string>
<string name="module_update">Оновити</string>
<string name="module_updated">Оновлено</string>
<string name="module_downloading">Завантаження модуля: %s</string>
<string name="module_start_downloading">Початок завантаження: %s</string>
<string name="new_version_available">Доступна нова версія %s, натисніть для оновлення.</string>
<string name="launch_app">Запустити</string>
<string name="close">Закрити</string>
<string name="force_stop_app">Примусово зупинити</string>
<string name="restart_app">Перезапустити</string>
<string name="settings_amoled_mode">AMOLED-режим</string>
<string name="settings_amoled_mode_summary">Увімкніть чисто чорну тему, корисну для екранів AMOLED, щоб зменшити навантаження на очі та заощадити заряд батареї.</string>
<string name="restart_required">Потрібно перезавантажити</string>
<string name="restart_app_message">Щоб ця зміна набула чинності, потрібно перезапустити програму.</string>
<string name="failed_to_update_sepolicy">Не вдалося оновити правила SELinux для: %s</string>
<string name="su_not_allowed">Надання прав суперкористувача заборонено для: %s</string>
<string name="module_changelog">Журнал змін</string>
<string name="settings_profile_template">Шаблон Профілю додатка</string>
<string name="settings_profile_template_summary">Управління локальними та онлайн шаблонами Профілів додатків</string>
<string name="app_profile_template_create">Створити шаблон</string>
<string name="app_profile_template_edit">Редагувати шаблон</string>
<string name="app_profile_template_id">Ідентифікатор</string>
<string name="app_profile_template_id_invalid">Неправильний ідентифікатор шаблону</string>
<string name="app_profile_template_name">Ім’я</string>
<string name="app_profile_template_description">Опис</string>
<string name="app_profile_template_save">Зберегти</string>
<string name="app_profile_template_delete">Видалити</string>
<string name="app_profile_template_view">Перегляд шаблону</string>
<string name="app_profile_template_readonly">Тільки для читання</string>
<string name="app_profile_template_id_exist">Ідентифікатор шаблону вже існує!</string>
<string name="app_profile_import_export">Імпорт/Експорт</string>
<string name="app_profile_import_from_clipboard">Імпорт із буфера обміну</string>
<string name="app_profile_export_to_clipboard">Експорт у буфер обміну</string>
<string name="app_profile_template_export_empty">Не вдалося знайти локальний шаблон для експорту!</string>
<string name="app_profile_template_import_success">Успішно імпортовано</string>
<string name="app_profile_template_sync">Синхронізувати онлайн-шаблони</string>
<string name="app_profile_template_save_failed">Не вдалося зберегти шаблон</string>
<string name="app_profile_template_import_empty">Буфер обміну порожній!</string>
<string name="module_changelog_failed">Не вдалося отримати журнал змін: %s</string>
<string name="settings_check_update">Перевіряти оновлення</string>
<string name="settings_check_update_summary">Автоматично перевіряти оновлення при відкритті додатка.</string>
<string name="grant_root_failed">Не вдалося надати root-доступ!</string>
<string name="action">Запустити</string>
<string name="webui">WebUI</string>
<string name="open">Відкрити</string>
<string name="enable_web_debugging">Відладка WebView</string>
<string name="enable_web_debugging_summary">Можна використовувати для відладки WebUI. Увімкніть лише при необхідності.</string>
<string name="direct_install">Пряма установка (Рекомендовано)</string>
<string name="select_file">Виберіть файл</string>
<string name="install_inactive_slot">У неактивний слот (Після OTA)</string>
<string name="install_inactive_slot_warning">Ваш пристрій буде **ПРИМУСОВО** завантажено у поточний неактивний слот після перезавантаження!\nВикористовуйте цю опцію лише після завершення OTA.\nПродовжити?</string>
<string name="install_next">Далі</string>
<string name="select_file_tip">Рекомендовано образ розділу %1$s</string>
<string name="select_kmi">Виберіть KMI</string>
<string name="shrink_sparse_image">Мінімізувати розріджене зображення</string>
<string name="shrink_sparse_image_message">Змініть розмір розрідженого зображення, де розташований модуль, до його фактичного розміру. Зверніть увагу, що це може призвести до неправильної роботи модуля, тому використовуйте його лише за необхідності (наприклад, для бекапу).</string>
<string name="settings_uninstall">Видалення</string>
<string name="settings_uninstall_temporary">Тимчасове видалення</string>
<string name="settings_uninstall_permanent">Повне видалення</string>
<string name="settings_restore_stock_image">Відновити стандартний образ</string>
<string name="settings_uninstall_temporary_message">Тимчасово видаліть KernelSU Next, відновивши початковий стан після наступного перезавантаження.</string>
<string name="settings_uninstall_permanent_message">Повне і остаточне видалення KernelSU Next (Root та всіх модулів).</string>
<string name="settings_restore_stock_image_message">Відновлення стандартного заводського образу (якщо є бекап), зазвичай використовується перед OTA; якщо потрібно видалити KernelSU Next, використовуйте "Повне видалення".</string>
<string name="flashing">Прошивка</string>
<string name="flash_success">Прошивка виконана успішно</string>
<string name="flash_failed">Помилка прошивки</string>
<string name="selected_lkm">Вибрано LKM: %s</string>
<string name="save_log">Зберегти логи</string>
<string name="log_saved">Логи збережено</string>
<string name="send_log">Поділитися логами</string>
<string name="settings_disable_su">Вимкн. сумісність із su</string>
<string name="settings_disable_su_summary">Тимчасово вимкнути можливість додаткам отримувати права root через команду su (існуючі процеси з правами root не будуть зачеплені).</string>
<string name="settings_language">Мова</string>
<string name="settings_legacyui">Використовувати застарілий UI</string>
<string name="settings_legacyui_summary">Перейти до попереднього стилю інтерфейсу користувача.</string>
<string name="settings_banner">Увімкнути банери</string>
<string name="settings_banner_summary">Показувати фонові банери для модулів.</string>
<string name="use_webuix">Використовувати WebUI X</string>
<string name="use_webuix_summary">Використовувати WebUI X замість WebUI, який підтримує більше API.</string>
<string name="use_webuix_eruda">Інжект Eruda у WebUI X</string>
<string name="use_webuix_eruda_summary">Інжектити консоль відладки у WebUI X, щоб спростити відладку. Потрібно увімкнути відладку WebView.</string>
<string name="customization">Кастомізація</string>
<string name="developer">Розробник</string>
</resources>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="issue_report_title">Đang gặp sự cố?</string> <string name="issue_report_title">Gặp sự cố?</string>
<string name="issue_report_body">Muốn báo cáo lỗi hoặc góp ý?</string> <string name="issue_report_body">Muốn báo cáo lỗi hoặc góp ý?</string>
<string name="issue_report_body_2">Báo cáo hoặc góp ý nhanh nhất có thể!</string> <string name="issue_report_body_2">Báo cáo hoặc góp ý nhanh nhất có thể!</string>
<string name="issue_report_github">Báo cáo trên GitHub</string> <string name="issue_report_github">Báo cáo trên GitHub</string>
@@ -9,29 +9,31 @@
<string name="issue_report_telegram_link">https://t.me/ksunext</string> <string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">Xác nhận</string> <string name="confirm">Xác nhận</string>
<string name="app_name" translatable="false">KernelSU Next</string> <string name="app_name" translatable="false">KernelSU Next</string>
<string name="home">Màn hình chính</string> <string name="home">Trang chủ</string>
<string name="home_not_installed">Hỗ trợ nhưng chưa cài đặt</string> <string name="home_not_installed">Hỗ trợ nhưng chưa cài đặt</string>
<string name="home_click_to_install">Bấm để cái đặt</string> <string name="home_click_to_install">Bấm để cài đặt</string>
<string name="lkm_mode_deprecated">Chế độ LKM không còn được hỗ trợ!</string>
<string name="lkm_alternative_suggestion">Cài đặt kernel GKI hoặc tự nhúng KernelSU Next vào kernel của bạn.</string>
<string name="home_working">Đã cài đặt và hoạt động</string> <string name="home_working">Đã cài đặt và hoạt động</string>
<string name="home_working_version">Phiên bản: %d</string> <string name="home_working_version">Phiên bản: %d</string>
<string name="home_superuser_count">Ứng dụng đã cấp su: %d</string> <string name="home_superuser_count">Ứng dụng đã cấp su: %d</string>
<string name="home_module_count">Modules: %d</string> <string name="home_module_count">Module: %d</string>
<string name="home_failure">Chữ kí KernelSU Next v2 Không dược tìm thấy (chưa cài đặt,nhúng sai cách hoặc nhầm trình quản lý?) [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">Không tìm thấy chữ kí KernelSU Next v2 (chưa cài đặt, nhúng sai cách hoặc nhầm trình quản lý?) [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Hỏi hoặc tự nhúng nhân KernelSU Next vào Kernel của bạn!</string> <string name="home_failure_tip">Hỏi hoặc tự nhúng KernelSU Next vào kernel của bạn!</string>
<string name="home_kernel">Phiên bản kernel</string> <string name="home_kernel">Phiên bản kernel</string>
<string name="enabled">Kích hoạt</string> <string name="enabled">Kích hoạt</string>
<string name="disabled">Vô hiệu hoá</string> <string name="disabled">Vô hiệu hoá</string>
<string name="susfs_supported">hỗ trợ</string> <string name="susfs_supported">Hỗ trợ</string>
<string name="home_susfs">SuSFS: %s</string> <string name="home_susfs">SuSFS: %s</string>
<string name="home_susfs_version">Phiên bản SuSFS</string> <string name="home_susfs_version">Phiên bản SuSFS</string>
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Phiên bản android</string> <string name="home_android">Phiên bản Android</string>
<string name="home_manager_version">Phiên bản trình quản lý</string> <string name="home_manager_version">Phiên bản trình quản lý</string>
<string name="home_selinux_status">Trạng thái SELinux</string> <string name="home_selinux_status">Trạng thái SELinux</string>
<string name="selinux_status_disabled">Vô hiệu hoá</string> <string name="selinux_status_disabled">Vô hiệu hoá</string>
<string name="selinux_status_enforcing">Enforcing</string> <string name="selinux_status_enforcing">Enforcing</string>
<string name="selinux_status_permissive">Permissive</string> <string name="selinux_status_permissive">Permissive</string>
<string name="selinux_status_unknown">Chịu</string> <string name="selinux_status_unknown">Không xác định</string>
<string name="superuser">Superuser</string> <string name="superuser">Superuser</string>
<string name="module_failed_to_enable">Không thể kích hoạt module: %s</string> <string name="module_failed_to_enable">Không thể kích hoạt module: %s</string>
<string name="module_failed_to_disable">Không thể vô hiệu hoá module: %s</string> <string name="module_failed_to_disable">Không thể vô hiệu hoá module: %s</string>
@@ -46,7 +48,7 @@
<string name="install">Cài đặt</string> <string name="install">Cài đặt</string>
<string name="reboot">Khởi động lại</string> <string name="reboot">Khởi động lại</string>
<string name="settings">Cài đặt</string> <string name="settings">Cài đặt</string>
<string name="reboot_userspace">Khởi động lại systemctrl</string> <string name="reboot_userspace">Khởi động mềm</string>
<string name="reboot_recovery">Vào Recovery</string> <string name="reboot_recovery">Vào Recovery</string>
<string name="reboot_bootloader">Vào Bootloader</string> <string name="reboot_bootloader">Vào Bootloader</string>
<string name="reboot_download">Vào Download Mode</string> <string name="reboot_download">Vào Download Mode</string>
@@ -57,7 +59,7 @@
<string name="module_uninstall_failed">Gỡ cài đặt thất bại: %s</string> <string name="module_uninstall_failed">Gỡ cài đặt thất bại: %s</string>
<string name="module_restore_confirm">Khôi phục module lại như lúc cài %s?</string> <string name="module_restore_confirm">Khôi phục module lại như lúc cài %s?</string>
<string name="module_restore_success">%s đã khôi phục</string> <string name="module_restore_success">%s đã khôi phục</string>
<string name="module_restore_failed">Khôi phục thất bại, vui lòng cài lại : %s</string> <string name="module_restore_failed">Khôi phục thất bại, vui lòng cài lại: %s</string>
<string name="module_version">Phiên bản</string> <string name="module_version">Phiên bản</string>
<string name="module_author">Người tạo ra</string> <string name="module_author">Người tạo ra</string>
<string name="module_id">ID</string> <string name="module_id">ID</string>
@@ -71,19 +73,19 @@
<string name="show_system_apps">Hiện thị ứng dụng hệ thống</string> <string name="show_system_apps">Hiện thị ứng dụng hệ thống</string>
<string name="hide_system_apps">Ẩn ứng dụng hệ thống</string> <string name="hide_system_apps">Ẩn ứng dụng hệ thống</string>
<string name="export_log">Xuất logs</string> <string name="export_log">Xuất logs</string>
<string name="safe_mode">CHẾ ĐỘ AN TOÀN!?!?</string> <string name="safe_mode">CHẾ ĐỘ AN TOÀN</string>
<string name="reboot_to_apply">Khởi động lại để có hiệu lực</string> <string name="reboot_to_apply">Khởi động lại để có hiệu lực</string>
<string name="module_magisk_conflict">Vui lòng gỡ magisk để sử dụng module</string> <string name="module_magisk_conflict">Vui lòng gỡ magisk để sử dụng module</string>
<string name="home_mount_system">Cơ chế mount</string> <string name="home_mount_system">Cơ chế mount</string>
<string name="home_magic_mount">Magic Mount</string> <string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string> <string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">Không có sẵn</string> <string name="unavailable">Không khả dụng</string>
<string name="use_overlay_fs">Sử dụng OverlayFS</string> <string name="use_overlay_fs">Sử dụng OverlayFS</string>
<string name="use_overlay_fs_summary">Gạt bật tắt chuyển giữa phương thức OverlayFS và Magic Mount cho các tập mount hệ thống.</string> <string name="use_overlay_fs_summary">Gạt bật tắt chuyển giữa phương thức OverlayFS và Magic Mount cho các tập mount hệ thống.</string>
<string name="reboot_required">Yêu cầu khởi động lại</string> <string name="reboot_required">Yêu cầu khởi động lại</string>
<string name="reboot_message">Một/Nhiều thay đổi cần được khởi động lại hệ thống, khởi động luôn?</string> <string name="reboot_message">Thay đổi sẽ có hiệu lực sau khi khởi động lại, khởi động ngay?</string>
<string name="module_restore">Khôi phục module</string> <string name="module_restore">Khôi phục module</string>
<string name="module_restore_message">Khôi phục modules từ bản sao lưu gần nhất.</string> <string name="module_restore_message">Khôi phục module từ bản sao lưu gần nhất.</string>
<string name="backup_restore">Sao lưu &amp; Khôi phục</string> <string name="backup_restore">Sao lưu &amp; Khôi phục</string>
<string name="module_backup">Sao lưu module</string> <string name="module_backup">Sao lưu module</string>
<string name="module_backup_message">Sao lưu những module đang được cài đặt.</string> <string name="module_backup_message">Sao lưu những module đang được cài đặt.</string>
@@ -102,8 +104,8 @@
<string name="home_experimental_kernelsu">⚠️ Cảnh báo nhánh thử nghiệm cho nhà phát triển!</string> <string name="home_experimental_kernelsu">⚠️ Cảnh báo nhánh thử nghiệm cho nhà phát triển!</string>
<string name="home_experimental_kernelsu_repo">127.0.0.1</string> <string name="home_experimental_kernelsu_repo">127.0.0.1</string>
<string name="home_experimental_kernelsu_body">KernelSU Next là 1 nhánh của KernelSU luôn có những nhánh thử nghiệm và cập nhật hàng ngày, nó có thể không ổn định</string> <string name="home_experimental_kernelsu_body">KernelSU Next là 1 nhánh của KernelSU luôn có những nhánh thử nghiệm và cập nhật hàng ngày, nó có thể không ổn định</string>
<string name="home_experimental_kernelsu_body_point_1"> • Tự chịu trách nghiệm: crashes, những thứ kì lạ, không vào được 1 vài ứng dụng(ngân hàng),... có thể diễn ra.</string> <string name="home_experimental_kernelsu_body_point_1"> • Tự chịu trách nghiệm: crashes, những thứ kì lạ, không vào được 1 vài ứng dụng (ngân hàng),... có thể xảy ra.</string>
<string name="home_experimental_kernelsu_body_point_2"> • Không bảo hành: Những nhà phát triển trong KernelSU (Next) và bên thứ 3 sẽ không chịu trách nghiệm khi hardbrick,bootloop,mất dữ liệu,... .</string> <string name="home_experimental_kernelsu_body_point_2"> • Không bảo hành: Các nhà phát triển KernelSU Next và bên thứ 3 sẽ không chịu trách nghiệm cho hardbrick, bootloop, mất dữ liệu,...</string>
<string name="home_experimental_kernelsu_body_point_3"> • Đùng để thử nghiệm là chính: Chỉ dành cho những người có kĩ năng, kinh nghiệm, trải nghiệm .</string> <string name="home_experimental_kernelsu_body_point_3"> • Đùng để thử nghiệm là chính: Chỉ dành cho những người có kĩ năng, kinh nghiệm, trải nghiệm .</string>
<string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s]]></string> <string name="about_source_code"><![CDATA[Xem mã nguồn tại %1$s]]></string>
<string name="profile" translatable="false">Hồ sơ ứng dụng</string> <string name="profile" translatable="false">Hồ sơ ứng dụng</string>
@@ -122,9 +124,9 @@
<string name="failed_to_update_app_profile">Cập nhật hồ sơ ứng dụng thất bại cho %s</string> <string name="failed_to_update_app_profile">Cập nhật hồ sơ ứng dụng thất bại cho %s</string>
<string name="require_kernel_version">Phiên bản KernelSU Next được nhúng trong kernel là %1$d và nó quá thấp để trình quản lý hoạt động. Vui lòng cập nhật lên phiên bản %2$d hoặc!</string> <string name="require_kernel_version">Phiên bản KernelSU Next được nhúng trong kernel là %1$d và nó quá thấp để trình quản lý hoạt động. Vui lòng cập nhật lên phiên bản %2$d hoặc!</string>
<string name="settings_umount_modules_default">Umount modules cho toàn hệ thống</string> <string name="settings_umount_modules_default">Umount modules cho toàn hệ thống</string>
<string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong hồ sơ ứng dụng. Nếu bật, tất cả nhưng module có can thiệp/thay đổi hệ thống sẽ không đi trừ khi được kích hoạt trong hồ sơ ứng dụng riêng biệt. (modder oem rom hoặc những người muốn chép file vào phân vùng hệ thống nên tắt).</string> <string name="settings_umount_modules_default_summary">Giá trị mặc định chung cho \"Umount modules\" trong Hồ sơ ứng dụng. Nếu bật, mọi thay đổi hệ thống do module gây ra sẽ bị gỡ bỏ đi với các ứng dụng chưa đặt hồ sơ riêng. (Modder OEM rom hoặc những người muốn chép file vào phân vùng hệ thống nên tắt).</string>
<string name="settings_susfs_toggle">Ẩn kprobe hooks</string> <string name="settings_susfs_toggle">Ẩn kprobes hook</string>
<string name="settings_susfs_toggle_summary">Tính năng này sẽ vô hiệu hoá những kprobe hooks đã tạo bởi kernelsu và sẽ kích hoạt và nhúng những non-kprobe hooks,đảm bảo những kernel non-GKI(EOL) hoạt động ổn định.</string> <string name="settings_susfs_toggle_summary">Tính năng này sẽ vô hiệu hoá những kprobes hook đã tạo bởi kernelsu và sẽ kích hoạt và nhúng những non-kprobes hook, đảm bảo những kernel non-GKI(EOL) hoạt động ổn định.</string>
<string name="profile_umount_modules_summary">Kích hoạt tính năng này sẽ tách các ứng dụng chưa cấp hồ sơ riêng và root.</string> <string name="profile_umount_modules_summary">Kích hoạt tính năng này sẽ tách các ứng dụng chưa cấp hồ sơ riêng và root.</string>
<string name="profile_selinux_domain">Tên miền</string> <string name="profile_selinux_domain">Tên miền</string>
<string name="profile_selinux_rules">Quyền</string> <string name="profile_selinux_rules">Quyền</string>
@@ -171,9 +173,9 @@
<string name="direct_install">Cài đặt trực tiếp (cho GKI 2.0)</string> <string name="direct_install">Cài đặt trực tiếp (cho GKI 2.0)</string>
<string name="select_file">Chọn file</string> <string name="select_file">Chọn file</string>
<string name="install_inactive_slot">Cài đặt vào phân vùng update (cho người OTA)</string> <string name="install_inactive_slot">Cài đặt vào phân vùng update (cho người OTA)</string>
<string name="install_inactive_slot_warning">Thiết bị của bạn sẽ BUỘC khởi động vào phân dùng chưa được sử dụng (có thể A hoặc B)\nSử dụng sau khi update OTA.\nTiếp?</string> <string name="install_inactive_slot_warning">Thiết bị của bạn sẽ BUỘC khởi động vào phân dùng chưa được sử dụng (A hoặc B)\nSử dụng sau khi update OTA.\nTiếp?</string>
<string name="install_next">Tiếp</string> <string name="install_next">Tiếp</string>
<string name="select_file_tip">tập tin %1$s được khuyến kích</string> <string name="select_file_tip">Tập tin %1$s được khuyến khích</string>
<string name="select_kmi">Chọn KMI</string> <string name="select_kmi">Chọn KMI</string>
<string name="shrink_sparse_image">Nén module.img</string> <string name="shrink_sparse_image">Nén module.img</string>
<string name="shrink_sparse_image_message">Nén lại module.img về kích thước thực, CHỈ SỬ DỤNG KHI CÓ HIỂU BIẾT VÀ CẦN THIẾT!?!?!?!?!.</string> <string name="shrink_sparse_image_message">Nén lại module.img về kích thước thực, CHỈ SỬ DỤNG KHI CÓ HIỂU BIẾT VÀ CẦN THIẾT!?!?!?!?!.</string>
@@ -182,7 +184,7 @@
<string name="settings_uninstall_permanent">Gỡ cài đặt sạch</string> <string name="settings_uninstall_permanent">Gỡ cài đặt sạch</string>
<string name="settings_restore_stock_image">Khôi phục phân vùng khởi động về mặc định</string> <string name="settings_restore_stock_image">Khôi phục phân vùng khởi động về mặc định</string>
<string name="settings_uninstall_temporary_message">Tạm thời gỡ KernelSU Next.</string> <string name="settings_uninstall_temporary_message">Tạm thời gỡ KernelSU Next.</string>
<string name="settings_uninstall_permanent_message">Gỡ cài đặt sạch hoàn toàn, trả về trạng thái lúc đầu .</string> <string name="settings_uninstall_permanent_message">Gỡ cài đặt sạch hoàn toàn, trả về trạng thái ban đầu.</string>
<string name="settings_restore_stock_image_message">Khôi phục lại boot lúc đầu (nếu có); nếu bạn cần gỡ hẳn KernelSU Next, sử dụng\"Gỡ cài đặt sạch\".</string> <string name="settings_restore_stock_image_message">Khôi phục lại boot lúc đầu (nếu có); nếu bạn cần gỡ hẳn KernelSU Next, sử dụng\"Gỡ cài đặt sạch\".</string>
<string name="flashing">Đang cài đặt</string> <string name="flashing">Đang cài đặt</string>
<string name="flash_success">Cài đặt thành công</string> <string name="flash_success">Cài đặt thành công</string>
@@ -194,4 +196,8 @@
<string name="settings_disable_su">Vô hiệu hoá khả năng của lệnh SU</string> <string name="settings_disable_su">Vô hiệu hoá khả năng của lệnh SU</string>
<string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (những app đã cấp trước đó không bị ảnh hưởng).</string> <string name="settings_disable_su_summary">Vô hiệu hoá khả năng thực thi lệnh SU để lấy quyền root (những app đã cấp trước đó không bị ảnh hưởng).</string>
<string name="settings_language">Ngôn ngữ</string> <string name="settings_language">Ngôn ngữ</string>
<string name="use_webuix">Dùng WebUI X</string>
<string name="use_webuix_summary">Dùng WebUI X thay vì WebUI (hỗ trợ nhiều API hơn).</string>
<string name="use_webuix_eruda">Nhúng nhân Eruda vào WebUI X</string>
<string name="use_webuix_eruda_summary">Nhúng trình gỡ lỗi vào WebUI X để việc sửa lỗi thuận tiện hơn. Yêu cầu gỡ lỗi webview được bật.</string>
</resources> </resources>

View File

@@ -4,7 +4,7 @@
<string name="issue_report_body">发现错误或者有改进建议?</string> <string name="issue_report_body">发现错误或者有改进建议?</string>
<string name="issue_report_body_2">快向我们报告吧!</string> <string name="issue_report_body_2">快向我们报告吧!</string>
<string name="issue_report_github">在 GitHub 报告</string> <string name="issue_report_github">在 GitHub 报告</string>
<string name="issue_report_telegram">在 Telegram 联系</string> <string name="issue_report_telegram">在 Telegram 获得最新消息</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string> <string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string> <string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">确认</string> <string name="confirm">确认</string>
@@ -12,42 +12,55 @@
<string name="home">主页</string> <string name="home">主页</string>
<string name="home_not_installed">未安装</string> <string name="home_not_installed">未安装</string>
<string name="home_click_to_install">点击安装</string> <string name="home_click_to_install">点击安装</string>
<string name="lkm_mode_deprecated">LKM 模式现已弃用!</string>
<string name="lkm_alternative_suggestion">请使用 GKI 内核或手动将 KernelSU Next 集成到你的设备。</string>
<string name="home_working">工作中</string> <string name="home_working">工作中</string>
<string name="home_working_version">版本:%d</string> <string name="home_working_version">版本:%d</string>
<string name="home_superuser_count">超级用户数:%d</string> <string name="home_superuser_count">超级用户数:%d</string>
<string name="home_module_count">模块数:%d</string> <string name="home_module_count">模块数:%d</string>
<string name="home_module_update_count">可更新模块: %d</string>
<string name="home_failure">内核中未找到 KernelSU Next V2 签名! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">内核中未找到 KernelSU Next V2 签名! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next</string> <string name="home_failure_tip">请让你的内核开发人员集成 KernelSU Next</string>
<string name="home_kernel">内核版本</string> <string name="home_kernel">内核版本</string>
<string name="hook_mode">Hook 模式</string>
<string name="enable">启用</string>
<string name="disable">禁用</string>
<string name="enabled">已启用</string>
<string name="disabled">已禁用</string>
<string name="susfs_supported">支持</string>
<string name="home_susfs">SuSFS%s</string> <string name="home_susfs">SuSFS%s</string>
<string name="home_susfs_version">SuSFS 版本</string> <string name="home_susfs_version">SuSFS 版本</string>
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">安卓版本</string> <string name="home_android">Android 版本</string>
<string name="home_manager_version">管理器版本</string> <string name="home_manager_version">管理器版本</string>
<string name="home_abi">接口</string>
<string name="home_selinux_status">SELinux 状态</string> <string name="home_selinux_status">SELinux 状态</string>
<string name="selinux_status_disabled">禁用</string> <string name="selinux_status_disabled">禁用</string>
<string name="selinux_status_enforcing">强制执行</string> <string name="selinux_status_enforcing">严格模式</string>
<string name="selinux_status_permissive">宽容模式</string> <string name="selinux_status_permissive">宽容模式</string>
<string name="selinux_status_unknown">未知</string> <string name="selinux_status_unknown">未知</string>
<string name="superuser">超级用户</string> <string name="superuser">超级用户</string>
<string name="module_failed_to_enable">无法启用模块:%s</string> <string name="module_failed_to_enable">启用模块失败数%s</string>
<string name="module_failed_to_disable">无法禁用模块:%s</string> <string name="module_failed_to_disable">禁用模块失败数%s</string>
<string name="module_empty">没有安装模块</string> <string name="module_empty">什么都没有呢</string>
<string name="module">模块</string> <string name="module">模块</string>
<string name="module_install_prompt_with_name">是否要继续安装模块 %1$s </string> <string name="module_install_prompt_with_name">是否要继续安装模块 %1$s </string>
<string name="module_sort_a_to_z">按 AZ 排序</string> <string name="module_sort_a_to_z">按 A - Z 排序</string>
<string name="module_sort_z_to_a">按 ZA 排序</string> <string name="module_sort_z_to_a">按 Z - A 排序</string>
<string name="module_size_low_to_high">按模块大小正序排序</string>
<string name="module_size_high_to_low">按模块大小倒序排序</string>
<string name="uninstall">卸载</string> <string name="uninstall">卸载</string>
<string name="restore">恢复</string> <string name="restore">恢复</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="uninstalled">已卸载</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>
@@ -62,20 +75,20 @@
<string name="module_update_json">更新配置</string> <string name="module_update_json">更新配置</string>
<string name="module_update_json_empty">无更新配置</string> <string name="module_update_json_empty">无更新配置</string>
<string name="enable_developer_options">启用开发者模式</string> <string name="enable_developer_options">启用开发者模式</string>
<string name="enable_developer_options_summary">显示隐藏的开发者专用设置和调试信息</string> <string name="enable_developer_options_summary">显示隐藏的开发者专用设置和调试信息</string>
<string name="module_overlay_fs_not_available">OverlayFS 被内核禁用,模块不可用。</string> <string name="module_overlay_fs_not_available">OverlayFS 被内核禁用,模块系统不可用。</string>
<string name="refresh">刷新</string> <string name="refresh">刷新</string>
<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="export_log">导出日志</string> <string name="export_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_mount_system">模块系统</string> <string name="home_mount_system">模块系统</string>
<string name="home_magic_mount">Magic Mount</string> <string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string> <string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">不可用</string> <string name="unavailable">不可用</string>
<string name="use_overlay_fs">使用 OverlayFS(实验性)</string> <string name="use_overlay_fs">使用 OverlayFS</string>
<string name="use_overlay_fs_summary">在 OverlayFS 和 Magic Mount 两种挂载系统之间进行切换。</string> <string name="use_overlay_fs_summary">在 OverlayFS 和 Magic Mount 两种挂载系统之间进行切换。</string>
<string name="reboot_required">需要重启</string> <string name="reboot_required">需要重启</string>
<string name="reboot_message">更改将在重启系统后生效。您想现在重启吗?</string> <string name="reboot_message">更改将在重启系统后生效。您想现在重启吗?</string>
@@ -93,6 +106,7 @@
<string name="proceed">继续</string> <string name="proceed">继续</string>
<string name="cancel">取消</string> <string name="cancel">取消</string>
<string name="later">稍后</string> <string name="later">稍后</string>
<string name="lkm_warning_message">此 LKM 补丁依赖于闭源组件,你确定要继续吗?</string>
<string name="home_next_kernelsu">🔥 Next 构建</string> <string name="home_next_kernelsu">🔥 Next 构建</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next 实验性分支。在 GitHub 上查看!</string> <string name="home_next_kernelsu_body">Next 实验性分支。在 GitHub 上查看!</string>
@@ -102,7 +116,7 @@
<string name="home_experimental_kernelsu_body_point_1"> • 风险自担:可能会发生崩溃、意外行为或导致系统故障。</string> <string name="home_experimental_kernelsu_body_point_1"> • 风险自担:可能会发生崩溃、意外行为或导致系统故障。</string>
<string name="home_experimental_kernelsu_body_point_2"> • 不做保证:开发者不对数据丢失、系统损坏等问题负责。</string> <string name="home_experimental_kernelsu_body_point_2"> • 不做保证:开发者不对数据丢失、系统损坏等问题负责。</string>
<string name="home_experimental_kernelsu_body_point_3"> • 仅供测试:此版适合了解风险并能轻松解决问题的用户。</string> <string name="home_experimental_kernelsu_body_point_3"> • 仅供测试:此版适合了解风险并能轻松解决问题的用户。</string>
<string name="about_source_code"><![CDATA[在 %1$s 查看源码]]></string> <string name="about_source_code"><![CDATA[在 %1$s 查看源码]]></string>
<string name="profile" translatable="false">App Profile</string> <string name="profile" translatable="false">App Profile</string>
<string name="profile_default">默认</string> <string name="profile_default">默认</string>
<string name="profile_template">模板</string> <string name="profile_template">模板</string>
@@ -126,6 +140,7 @@
<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_updated">已更新</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>
@@ -133,15 +148,19 @@
<string name="close">关闭</string> <string name="close">关闭</string>
<string name="force_stop_app">强制停止</string> <string name="force_stop_app">强制停止</string>
<string name="restart_app">重新启动</string> <string name="restart_app">重新启动</string>
<string name="settings_amoled_mode">AMOLED 模式</string>
<string name="settings_amoled_mode_summary">启用适用于 AMOLED 屏幕的纯黑主题,可减少视觉疲劳并节省电量。</string>
<string name="restart_required">需要重启</string>
<string name="restart_app_message">请重启 APP 以确保更改生效。</string>
<string name="failed_to_update_sepolicy">为 %s 更新 SELinux 规则失败</string> <string name="failed_to_update_sepolicy">为 %s 更新 SELinux 规则失败</string>
<string name="su_not_allowed">拒绝授予%s超级用户权限</string> <string name="su_not_allowed">拒绝授予%s超级用户权限</string>
<string name="module_changelog">更新日志</string> <string name="module_changelog">更新日志</string>
<string name="settings_profile_template">App Profile 模板</string> <string name="settings_profile_template">App Profile 模板</string>
<string name="settings_profile_template_summary">管理本地和在线的 App Profile 模版</string> <string name="settings_profile_template_summary">管理本地和在线的 App Profile 模版</string>
<string name="app_profile_template_create">创建模版</string> <string name="app_profile_template_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">模板 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>
<string name="app_profile_template_save">保存</string> <string name="app_profile_template_save">保存</string>
@@ -159,9 +178,10 @@
<string name="app_profile_template_import_empty">剪贴板为空!</string> <string name="app_profile_template_import_empty">剪贴板为空!</string>
<string name="module_changelog_failed">获取更新日志失败: %s</string> <string name="module_changelog_failed">获取更新日志失败: %s</string>
<string name="settings_check_update">检查更新</string> <string name="settings_check_update">检查更新</string>
<string name="settings_check_update_summary">在应用启动后自动检查是否有最新版</string> <string name="settings_check_update_summary">在应用启动后自动检查是否有更新</string>
<string name="grant_root_failed">获取 root 失败!</string> <string name="grant_root_failed">获取 root 失败!</string>
<string name="action">执行</string> <string name="action">动作</string>
<string name="webui">WebUI</string>
<string name="open">打开</string> <string name="open">打开</string>
<string name="enable_web_debugging">启用 WebView 调试</string> <string name="enable_web_debugging">启用 WebView 调试</string>
<string name="enable_web_debugging_summary">可用于调试 WebUI请仅在需要时启用。</string> <string name="enable_web_debugging_summary">可用于调试 WebUI请仅在需要时启用。</string>
@@ -173,7 +193,7 @@
<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_kmi">选择 KMI</string>
<string name="shrink_sparse_image">最小化稀疏文件</string> <string name="shrink_sparse_image">最小化稀疏文件</string>
<string name="shrink_sparse_image_message">将模块所在的稀疏文件镜像调整为其实际大小,注意这可能导致模块工作异常,请仅在必要时(如备份)使用</string> <string name="shrink_sparse_image_message">将模块所在的稀疏文件镜像调整为其实际大小,注意这可能导致模块工作异常,请仅在必要时(如备份)使用</string>
<string name="settings_uninstall">卸载</string> <string name="settings_uninstall">卸载</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>
@@ -189,6 +209,15 @@
<string name="log_saved">日志已保存</string> <string name="log_saved">日志已保存</string>
<string name="send_log">分享日志</string> <string name="send_log">分享日志</string>
<string name="settings_disable_su">禁用超级用户指令</string> <string name="settings_disable_su">禁用超级用户指令</string>
<string name="settings_disable_su_summary">临时禁止任何应用通过 su 命令获取 root 权限(运行的 root 进程不受影响)</string> <string name="settings_disable_su_summary">临时禁止任何应用通过 su 命令获取 root 权限(正在运行的 root 进程不受影响)</string>
<string name="settings_language">语言</string> <string name="settings_language">语言</string>
<string name="settings_legacyui">切换到传统 UI</string>
<string name="settings_legacyui_summary">使用早期的用户界面风格。</string>
<string name="settings_banner">启用横幅</string>
<string name="settings_banner_summary">针对模块启用背景横幅。</string>
<string name="use_webuix">使用 WebUI X</string>
<string name="use_webuix_summary">使用更完善的 WebUI X 取代旧有 WebUI请注意模块开发者可在模块信息中单独覆盖此项设置。</string>
<string name="use_webuix_eruda">对 WebUI X 注入 Eruda</string>
<string name="use_webuix_eruda_summary">使用 WebUI X 时注入控制台以便于调试,需要启用 WebView 调试功能。</string>
<string name="customization">自定义</string>
</resources> </resources>

View File

@@ -3,8 +3,8 @@
<string name="issue_report_title">有任何問題?</string> <string name="issue_report_title">有任何問題?</string>
<string name="issue_report_body">遇到錯誤或者需要反饋?</string> <string name="issue_report_body">遇到錯誤或者需要反饋?</string>
<string name="issue_report_body_2">請儘快告知我們!</string> <string name="issue_report_body_2">請儘快告知我們!</string>
<string name="issue_report_github"> GitHub 回報</string> <string name="issue_report_github"> GitHub 回報</string>
<string name="issue_report_telegram">透過 Telegram 聯繫</string> <string name="issue_report_telegram">透過 Telegram 取得最新情報</string>
<string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string> <string name="issue_report_github_link">https://github.com/KernelSU-Next/KernelSU-Next/issues</string>
<string name="issue_report_telegram_link">https://t.me/ksunext</string> <string name="issue_report_telegram_link">https://t.me/ksunext</string>
<string name="confirm">確認</string> <string name="confirm">確認</string>
@@ -12,18 +12,28 @@
<string name="home">主頁</string> <string name="home">主頁</string>
<string name="home_not_installed">未安裝</string> <string name="home_not_installed">未安裝</string>
<string name="home_click_to_install">點擊安裝</string> <string name="home_click_to_install">點擊安裝</string>
<string name="lkm_mode_deprecated">LKM 模式現已棄用!</string>
<string name="lkm_alternative_suggestion">請使用 GKI 內核或手動將 KernelSU Next 整合到你的裝置。</string>
<string name="home_working">工作中</string> <string name="home_working">工作中</string>
<string name="home_working_version">版本: %d</string> <string name="home_working_version">版本: %d</string>
<string name="home_superuser_count">超級使用者數: %d</string> <string name="home_superuser_count">超級使用者數: %d</string>
<string name="home_module_count">模組數: %d</string> <string name="home_module_count">模組數: %d</string>
<string name="home_module_update_count">可升級模組: %d</string>
<string name="home_failure">內核中未找到 KernelSU Next v2 簽名! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">內核中未找到 KernelSU Next v2 簽名! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">請讓你的內核開發人員整合 KernelSU Next</string> <string name="home_failure_tip">請讓你的內核開發人員整合 KernelSU Next</string>
<string name="home_kernel">內核版本</string> <string name="home_kernel">內核版本</string>
<string name="hook_mode">Hook 方法</string>
<string name="enable">啓用</string>
<string name="disable">禁用</string>
<string name="enabled">已經啓用</string>
<string name="disabled">已經禁用</string>
<string name="susfs_supported">支援</string>
<string name="home_susfs">SuSFS%s</string> <string name="home_susfs">SuSFS%s</string>
<string name="home_susfs_version">SuSFS 版本</string> <string name="home_susfs_version">SuSFS 版本</string>
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android 版本</string> <string name="home_android">Android 版本</string>
<string name="home_manager_version">管理版本</string> <string name="home_manager_version">管理版本</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">SELinux 狀態</string> <string name="home_selinux_status">SELinux 狀態</string>
<string name="selinux_status_disabled">被禁用</string> <string name="selinux_status_disabled">被禁用</string>
<string name="selinux_status_enforcing">強制執行</string> <string name="selinux_status_enforcing">強制執行</string>
@@ -37,11 +47,14 @@
<string name="module_install_prompt_with_name">是否要繼續安裝模組 %1$s </string> <string name="module_install_prompt_with_name">是否要繼續安裝模組 %1$s </string>
<string name="module_sort_a_to_z">按 A - Z 排序</string> <string name="module_sort_a_to_z">按 A - Z 排序</string>
<string name="module_sort_z_to_a">按 Z - A 排序</string> <string name="module_sort_z_to_a">按 Z - A 排序</string>
<string name="module_size_low_to_high">按模組大小正序排序</string>
<string name="module_size_high_to_low">按模組大小倒序排序</string>
<string name="uninstall">卸載</string> <string name="uninstall">卸載</string>
<string name="restore">恢復</string> <string name="restore">恢復</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="uninstalled">已經卸載</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>
@@ -63,7 +76,7 @@
<string name="module_update_json_empty">無更新配置</string> <string name="module_update_json_empty">無更新配置</string>
<string name="enable_developer_options">啟用開發人員模式</string> <string name="enable_developer_options">啟用開發人員模式</string>
<string name="enable_developer_options_summary">顯示隱藏的開發人員專用設置和調試信息</string> <string name="enable_developer_options_summary">顯示隱藏的開發人員專用設置和調試信息</string>
<string name="module_overlay_fs_not_available">OverlayFS 被內核禁用,模組不可用。</string> <string name="module_overlay_fs_not_available">OverlayFS 被內核禁用,所有模組不可用。</string>
<string name="refresh">刷新</string> <string name="refresh">刷新</string>
<string name="show_system_apps">顯示系統應用</string> <string name="show_system_apps">顯示系統應用</string>
<string name="hide_system_apps">隱藏系統應用</string> <string name="hide_system_apps">隱藏系統應用</string>
@@ -75,7 +88,7 @@
<string name="home_magic_mount">Magic Mount</string> <string name="home_magic_mount">Magic Mount</string>
<string name="home_overlayfs_mount">OverlayFS</string> <string name="home_overlayfs_mount">OverlayFS</string>
<string name="unavailable">不可用</string> <string name="unavailable">不可用</string>
<string name="use_overlay_fs">使用 OverlayFS (實驗性功能)</string> <string name="use_overlay_fs">使用 OverlayFS</string>
<string name="use_overlay_fs_summary">對於 KernelSU Next 的掛載系統,在使用 OverlayFS 和 Magic Mount 之間進行切換。</string> <string name="use_overlay_fs_summary">對於 KernelSU Next 的掛載系統,在使用 OverlayFS 和 Magic Mount 之間進行切換。</string>
<string name="reboot_required">需要重啟</string> <string name="reboot_required">需要重啟</string>
<string name="reboot_message">更改將在重啟系統後生效。您想現在重啟嗎?</string> <string name="reboot_message">更改將在重啟系統後生效。您想現在重啟嗎?</string>
@@ -93,6 +106,7 @@
<string name="proceed">繼續</string> <string name="proceed">繼續</string>
<string name="cancel">取消</string> <string name="cancel">取消</string>
<string name="later">稍後</string> <string name="later">稍後</string>
<string name="lkm_warning_message">該 LKM 補丁依賴閉源元件,確定繼續嗎?</string>
<string name="home_next_kernelsu">🔥 Next 構建</string> <string name="home_next_kernelsu">🔥 Next 構建</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next 實驗性分支。在 GitHub 上查看!</string> <string name="home_next_kernelsu_body">Next 實驗性分支。在 GitHub 上查看!</string>
@@ -126,6 +140,7 @@
<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_updated">已經更新</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>
@@ -133,22 +148,26 @@
<string name="close">關閉</string> <string name="close">關閉</string>
<string name="force_stop_app">強制停止</string> <string name="force_stop_app">強制停止</string>
<string name="restart_app">重新啟動</string> <string name="restart_app">重新啟動</string>
<string name="settings_amoled_mode">AMOLED 模式</string>
<string name="settings_amoled_mode_summary">啓用 AMOLED 屏幕專用的純黑主題,減少視覺疲勞的同時節約電池使用。</string>
<string name="restart_required">需要重啓</string>
<string name="restart_app_message">請重啓程式確保改動生效。</string>
<string name="failed_to_update_sepolicy">為:%s 更新 SELinux 規則失敗</string> <string name="failed_to_update_sepolicy">為:%s 更新 SELinux 規則失敗</string>
<string name="su_not_allowed">拒絕授予%s超級使用者權限</string> <string name="su_not_allowed">拒絕授予%s超級使用者權限</string>
<string name="module_changelog">更新日誌</string> <string name="module_changelog">更新日誌</string>
<string name="settings_profile_template">App Profile 模板</string> <string name="settings_profile_template">App Profile 模板</string>
<string name="settings_profile_template_summary">管理本地和線上的 App Profile 模板</string> <string name="settings_profile_template_summary">管理本地和線上的 App Profile 模板</string>
<string name="app_profile_template_create">創建模板</string> <string name="app_profile_template_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">模板 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>
<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">模板 id 已存在!</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>
@@ -161,10 +180,11 @@
<string name="settings_check_update">檢查更新</string> <string name="settings_check_update">檢查更新</string>
<string name="settings_check_update_summary">在應用啟動後自動檢查是否有最新版。</string> <string name="settings_check_update_summary">在應用啟動後自動檢查是否有最新版。</string>
<string name="grant_root_failed">獲取 root 失敗!</string> <string name="grant_root_failed">獲取 root 失敗!</string>
<string name="action">執行</string> <string name="action">Action</string>
<string name="webui">WebUI</string>
<string name="open">打開</string> <string name="open">打開</string>
<string name="enable_web_debugging">啟用 WebView 偵錯</string> <string name="enable_web_debugging">啟用 WebView 偵錯</string>
<string name="enable_web_debugging_summary">可用於偵錯 WebUI 僅在需要時啟用。</string> <string name="enable_web_debugging_summary">可用於偵錯 WebUI ,僅在需要時啟用。</string>
<string name="direct_install">直接安裝(推薦)</string> <string name="direct_install">直接安裝(推薦)</string>
<string name="select_file">選擇一個檔案</string> <string name="select_file">選擇一個檔案</string>
<string name="install_inactive_slot">安裝到未使用的槽位OTA 後)</string> <string name="install_inactive_slot">安裝到未使用的槽位OTA 後)</string>
@@ -173,7 +193,7 @@
<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_kmi">選擇 KMI</string>
<string name="shrink_sparse_image">最小化稀疏檔案</string> <string name="shrink_sparse_image">最小化稀疏檔案</string>
<string name="shrink_sparse_image_message">將模組所在的稀疏檔案映像調整為其實際大小,注意這可能導致模組工作異常,請僅在必要時(如備份)使用</string> <string name="shrink_sparse_image_message">將模組所在的稀疏檔案映像調整為其實際大小,注意這可能導致模組工作異常,請僅在必要時(如備份)使用</string>
<string name="settings_uninstall">卸載</string> <string name="settings_uninstall">卸載</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>
@@ -189,6 +209,15 @@
<string name="log_saved">日誌已保存</string> <string name="log_saved">日誌已保存</string>
<string name="send_log">發送日誌</string> <string name="send_log">發送日誌</string>
<string name="settings_disable_su">關閉 SU 相容</string> <string name="settings_disable_su">關閉 SU 相容</string>
<string name="settings_disable_su_summary">暫時禁止任何應用通過 su 命令獲取 root 權限(已運行的 root 進程不受影響)</string> <string name="settings_disable_su_summary">暫時禁止任何應用通過 su 命令獲取 root 權限(已運行的 root 進程不受影響)</string>
<string name="settings_language">語言</string> <string name="settings_language">語言</string>
<string name="settings_legacyui">換回傳統 UI</string>
<string name="settings_legacyui_summary">使用早期版本 UI 風格。</string>
<string name="settings_banner">啓用橫幅</string>
<string name="settings_banner_summary">對模組啓用背景橫幅。</string>
<string name="use_webuix">使用 WebUI X</string>
<string name="use_webuix_summary">使用更爲完善的 WebUI X 而不是 WebUI請注意模組開發人員能在模組信息中覆寫這個設置。</string>
<string name="use_webuix_eruda">將 Eruda 注入 WebUI X</string>
<string name="use_webuix_eruda_summary">在使用 WebUI X 時注入控制台以便於偵錯,需要啟用 WebView 偵錯功能。</string>
<string name="customization">客制化</string>
</resources> </resources>

View File

@@ -12,13 +12,19 @@
<string name="home">Home</string> <string name="home">Home</string>
<string name="home_not_installed">Not installed</string> <string name="home_not_installed">Not installed</string>
<string name="home_click_to_install">Click to install</string> <string name="home_click_to_install">Click to install</string>
<string name="lkm_mode_deprecated">LKM mode is now deprecated!</string>
<string name="lkm_alternative_suggestion">Install GKI kernel or integrate KernelSU Next to your device.</string>
<string name="home_working">Working</string> <string name="home_working">Working</string>
<string name="home_working_version">Version: %d</string> <string name="home_working_version">Version: %d</string>
<string name="home_superuser_count">Superusers: %d</string> <string name="home_superuser_count">Superusers: %d</string>
<string name="home_module_count">Modules: %d</string> <string name="home_module_count">Modules: %d</string>
<string name="home_module_update_count">Updates: %d</string>
<string name="home_failure">KernelSU Next v2 signature not found in kernel! [ !KSU_NEXT || != size/hash ]</string> <string name="home_failure">KernelSU Next v2 signature not found in kernel! [ !KSU_NEXT || != size/hash ]</string>
<string name="home_failure_tip">Ask your kernel developer to integrate KernelSU Next!</string> <string name="home_failure_tip">Ask your kernel developer to integrate KernelSU Next!</string>
<string name="home_kernel">Kernel version</string> <string name="home_kernel">Kernel version</string>
<string name="hook_mode">Hook mode</string>
<string name="enable">Enable</string>
<string name="disable">Disable</string>
<string name="enabled">Enabled</string> <string name="enabled">Enabled</string>
<string name="disabled">Disabled</string> <string name="disabled">Disabled</string>
<string name="susfs_supported">Supported</string> <string name="susfs_supported">Supported</string>
@@ -27,6 +33,7 @@
<string name="home_susfs_sus_su">SuS SU</string> <string name="home_susfs_sus_su">SuS SU</string>
<string name="home_android">Android version</string> <string name="home_android">Android version</string>
<string name="home_manager_version">Manager version</string> <string name="home_manager_version">Manager version</string>
<string name="home_abi">ABI</string>
<string name="home_selinux_status">SELinux status</string> <string name="home_selinux_status">SELinux status</string>
<string name="selinux_status_disabled">Disabled</string> <string name="selinux_status_disabled">Disabled</string>
<string name="selinux_status_enforcing">Enforcing</string> <string name="selinux_status_enforcing">Enforcing</string>
@@ -38,13 +45,16 @@
<string name="module_empty">No module installed</string> <string name="module_empty">No module installed</string>
<string name="module">Module</string> <string name="module">Module</string>
<string name="module_install_prompt_with_name">The following module(s) will be installed: %1$s</string> <string name="module_install_prompt_with_name">The following module(s) will be installed: %1$s</string>
<string name="module_sort_a_to_z">Sort (A-Z)</string> <string name="module_sort_a_to_z">Sort (AZ)</string>
<string name="module_sort_z_to_a">Sort (Z-A)</string> <string name="module_sort_z_to_a">Sort (ZA)</string>
<string name="module_size_low_to_high">Sort (Low → High)</string>
<string name="module_size_high_to_low">Sort (High → Low)</string>
<string name="uninstall">Uninstall</string> <string name="uninstall">Uninstall</string>
<string name="restore">Restore</string> <string name="restore">Restore</string>
<string name="module_install">Install</string> <string name="module_install">Install</string>
<string name="install">Install</string> <string name="install">Install</string>
<string name="reboot">Reboot</string> <string name="reboot">Reboot</string>
<string name="uninstalled">Uninstalled</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="reboot_userspace">Soft Reboot</string> <string name="reboot_userspace">Soft Reboot</string>
<string name="reboot_recovery">Reboot to Recovery</string> <string name="reboot_recovery">Reboot to Recovery</string>
@@ -96,6 +106,7 @@
<string name="proceed">Proceed</string> <string name="proceed">Proceed</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
<string name="later">Later</string> <string name="later">Later</string>
<string name="lkm_warning_message">The LKM patch relies on closed source components. Do you want to continue?</string>
<string name="home_next_kernelsu">🔥 Next build</string> <string name="home_next_kernelsu">🔥 Next build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string> <string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string> <string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>
@@ -123,12 +134,13 @@
<string name="require_kernel_version">The current KernelSU Next version %1$d is too low for the manager to work properly. Please upgrade to version %2$d or higher!</string> <string name="require_kernel_version">The current KernelSU Next version %1$d is too low for the manager to work properly. Please upgrade to version %2$d or higher!</string>
<string name="settings_umount_modules_default">Umount modules</string> <string name="settings_umount_modules_default">Umount modules</string>
<string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string> <string name="settings_umount_modules_default_summary">The global default value for \"Umount modules\" in App Profile. If enabled, it will remove all module modifications to the system for apps that don\'t have a profile set.</string>
<string name="settings_susfs_toggle">Hide kprobe hooks</string> <string name="settings_susfs_toggle">Hide kprobes hook</string>
<string name="settings_susfs_toggle_summary">This option disables the kprobe hooks created by ksu and, instead, activates the embedded non-kprobe hooks, implementing the same functionality that would be applied to a non-GKI kernel, which doesn\'t support kprobe.</string> <string name="settings_susfs_toggle_summary">This option disables the kprobes hook created by ksu and, instead, activates the embedded non-kprobes hook, implementing the same functionality that would be applied to a non-GKI kernel, which doesn\'t support kprobe.</string>
<string name="profile_umount_modules_summary">Enabling this option will allow KernelSU Next to restore any modified files by the modules for this app.</string> <string name="profile_umount_modules_summary">Enabling this option will allow KernelSU Next to restore any modified files by the modules for this app.</string>
<string name="profile_selinux_domain">Domain</string> <string name="profile_selinux_domain">Domain</string>
<string name="profile_selinux_rules">Rules</string> <string name="profile_selinux_rules">Rules</string>
<string name="module_update">Update</string> <string name="module_update">Update</string>
<string name="module_updated">Updated</string>
<string name="module_downloading">Downloading module: %s</string> <string name="module_downloading">Downloading module: %s</string>
<string name="module_start_downloading">Start downloading: %s</string> <string name="module_start_downloading">Start downloading: %s</string>
<string name="new_version_available">New version %s is available, click to upgrade.</string> <string name="new_version_available">New version %s is available, click to upgrade.</string>
@@ -136,6 +148,10 @@
<string name="close">Close</string> <string name="close">Close</string>
<string name="force_stop_app">Force stop</string> <string name="force_stop_app">Force stop</string>
<string name="restart_app">Restart</string> <string name="restart_app">Restart</string>
<string name="settings_amoled_mode">AMOLED mode</string>
<string name="settings_amoled_mode_summary">Enable a pure black theme useful for AMOLED screens to reduce eye strain and save battery.</string>
<string name="restart_required">Restart required</string>
<string name="restart_app_message">The app needs to restart for this change to take effect.</string>
<string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string> <string name="failed_to_update_sepolicy">Failed to update SELinux rules for: %s</string>
<string name="su_not_allowed">Granting superuser isn\'t allowed for: %s</string> <string name="su_not_allowed">Granting superuser isn\'t allowed for: %s</string>
<string name="module_changelog">Changelog</string> <string name="module_changelog">Changelog</string>
@@ -165,6 +181,7 @@
<string name="settings_check_update_summary">Automatically check for updates when opening the app.</string> <string name="settings_check_update_summary">Automatically check for updates when opening the app.</string>
<string name="grant_root_failed">Failed to grant root!</string> <string name="grant_root_failed">Failed to grant root!</string>
<string name="action">Action</string> <string name="action">Action</string>
<string name="webui">WebUI</string>
<string name="open">Open</string> <string name="open">Open</string>
<string name="enable_web_debugging">Enable WebView debugging</string> <string name="enable_web_debugging">Enable WebView debugging</string>
<string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string> <string name="enable_web_debugging_summary">Can be used to debug WebUI. Please enable only when needed.</string>
@@ -194,4 +211,15 @@
<string name="settings_disable_su">Disable su compatibility</string> <string name="settings_disable_su">Disable su compatibility</string>
<string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (existing root processes won\'t be affected).</string> <string name="settings_disable_su_summary">Temporarily disable the ability of any app to gain root privileges via the su command (existing root processes won\'t be affected).</string>
<string name="settings_language">Language</string> <string name="settings_language">Language</string>
<string name="settings_legacyui">Use Legacy UI</string>
<string name="settings_legacyui_summary">Switch to the previous user interface style.</string>
<string name="settings_banner">Enable banners</string>
<string name="settings_banner_summary">Show background banners for modules.</string>
<string name="use_webuix">Use WebUI X</string>
<string name="use_webuix_summary">Use WebUI X instead of WebUI, which supports more APIs.</string>
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
<string name="customization">Customization</string>
<string name="developer">Developer</string>
<string name="sucompat_disabled">SUCOMPAT DISABLED</string>
</resources> </resources>

View File

@@ -18,7 +18,7 @@ cmaker {
"-DANDROID_STL=none", "-DANDROID_STL=none",
) )
) )
abiFilters("arm64-v8a") abiFilters("arm64-v8a", "armeabi-v7a", "x86_64")
} }
buildTypes { buildTypes {
if (it.name == "release") { if (it.name == "release") {
@@ -28,9 +28,9 @@ cmaker {
} }
val androidMinSdkVersion = 26 val androidMinSdkVersion = 26
val androidTargetSdkVersion = 35 val androidTargetSdkVersion = 36
val androidCompileSdkVersion = 35 val androidCompileSdkVersion = 36
val androidCompileNdkVersion = "28.0.13004108" val androidCompileNdkVersion = "28.1.13356709"
val androidSourceCompatibility = JavaVersion.VERSION_21 val androidSourceCompatibility = JavaVersion.VERSION_21
val androidTargetCompatibility = JavaVersion.VERSION_21 val androidTargetCompatibility = JavaVersion.VERSION_21
val managerVersionCode by extra(getVersionCode()) val managerVersionCode by extra(getVersionCode())
@@ -78,7 +78,7 @@ subprojects {
versionName = managerVersionName versionName = managerVersionName
} }
ndk { ndk {
abiFilters += listOf("arm64-v8a") abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64")
} }
} }

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