diff --git a/.cargo/config.toml b/.cargo/config.toml index 115192e..ac2b23f 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,2 @@ [target.x86_64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] - -[target.x86_64-unknown-linux-gnu] -linker = "clang" -rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/.github/ISSUE_TEMPLATE/3-add-new-packages.yml b/.github/ISSUE_TEMPLATE/3-add-new-packages.yml index c9dc35f..b44df06 100644 --- a/.github/ISSUE_TEMPLATE/3-add-new-packages.yml +++ b/.github/ISSUE_TEMPLATE/3-add-new-packages.yml @@ -6,16 +6,17 @@ body: - type: markdown attributes: value: | + ## Consider submitting a Pull Request + + We receive many package-related issues and it's hard to keep up. **Consider submitting a Pull Request yourself**—it helps us process changes much faster! See our [guide on how to contribute](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute) for instructions. + + --- + ## Document each package the best you can **List**: `Google`|`Misc`|`OEM` (manufacturer) |`AOSP`|`Pending`|`Carrier` (ISP). - **Removal**: - - - Recommended: Pointless or outright negative packages, and/or apps available through Google Play. - - Advanced: Breaks obscure or minor parts of functionality, or apps that aren't easily enabled/installed through Settings/Google Play. This category is also used for apps that are useful (default keyboard/gallery/launcher/music app.) but that can easily be replaced by a better alternative. - - Expert: Breaks widespread and/or important functionality, but nothing important to the basic operation of the operating system. Removing an Expert package should not bootloop the device (unless mentioned in the description) but we can't guarantee it 100%. - - Unsafe: Can break vital parts of the operating system. Removing an Unsafe package have an extremely high risk of bootlooping your device. + **Removal**: `Recommended`|`Advanced`|`Expert`|`Unsafe`. See the [Removal Definitions](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Debloat-Lists#removal-definitions) on the wiki for details. **Please ensure you follow these definitions when proposing changes.** - type: textarea id: package-listing @@ -30,6 +31,15 @@ body: validations: required: true +- type: checkboxes + id: removal-definitions + attributes: + label: Removal Definitions + description: Please ensure you follow the removal definitions when proposing changes. + options: + - label: I've read the [Removal Definitions](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Debloat-Lists#removal-definitions) + required: true + - type: checkboxes id: acknowledgements attributes: @@ -37,6 +47,7 @@ body: description: Your bug report will be closed if you don't follow the checklist below. options: - label: I removed all those packages on my phone. If not, why? Explain in the issue. + - label: I'm willing to submit a Pull Request for this change. - label: This issue is not a duplicate of an existing one. required: true - label: I have chosen an appropriate title. diff --git a/.github/ISSUE_TEMPLATE/4-debloat-issue-report.yml b/.github/ISSUE_TEMPLATE/4-debloat-issue-report.yml index 4900d9e..8cba412 100644 --- a/.github/ISSUE_TEMPLATE/4-debloat-issue-report.yml +++ b/.github/ISSUE_TEMPLATE/4-debloat-issue-report.yml @@ -3,6 +3,13 @@ description: Your phone has unexpected issues after debloating title: "pkg(scope): " labels: ["package::breakage"] body: +- type: markdown + attributes: + value: | + ## Consider submitting a Pull Request + + If you know which package caused the issue and how the documentation should be updated, **consider submitting a Pull Request yourself**—it helps us process changes much faster! See our [guide on how to contribute](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute) for instructions. + - type: textarea id: what-happened attributes: @@ -31,6 +38,7 @@ body: label: Acknowledgements description: Your bug report will be closed if you don't follow the checklist below. options: + - label: I'm willing to submit a Pull Request to fix the package documentation. - label: This issue is not a duplicate of an existing one. required: true - label: I have chosen an appropriate title. diff --git a/.github/ISSUE_TEMPLATE/5-update-apps-description-or-recommendation.yml b/.github/ISSUE_TEMPLATE/5-update-apps-description-or-recommendation.yml index 6027118..945e302 100644 --- a/.github/ISSUE_TEMPLATE/5-update-apps-description-or-recommendation.yml +++ b/.github/ISSUE_TEMPLATE/5-update-apps-description-or-recommendation.yml @@ -6,16 +6,17 @@ body: - type: markdown attributes: value: | + ## Consider submitting a Pull Request + + We receive many package documentation updates and it's hard to keep up. **Consider submitting a Pull Request yourself**—it helps us process changes much faster! See our [guide on how to contribute](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute) for instructions. + + --- + ## Document each package the best you can **List**: `Google`|`Misc`|`OEM` (manufacturer) |`AOSP`|`Pending`|`Carrier` (ISP). - **Removal**: - - - Recommended: Pointless or outright negative packages, and/or apps available through Google Play. - - Advanced: Breaks obscure or minor parts of functionality, or apps that aren't easily enabled/installed through Settings/Google Play. This category is also used for apps that are useful (default keyboard/gallery/launcher/music app.) but that can easily be replaced by a better alternative. - - Expert: Breaks widespread and/or important functionality, but nothing important to the basic operation of the operating system. Removing an Expert package should not bootloop the device (unless mentioned in the description) but we can't guarantee it 100%. - - Unsafe: Can break vital parts of the operating system. Removing an Unsafe package have an extremely high risk of bootlooping your device. + **Removal**: `Recommended`|`Advanced`|`Expert`|`Unsafe`. See the [Removal Definitions](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Debloat-Lists#removal-definitions) on the wiki for details. **Please ensure you follow these definitions when proposing changes.** - type: textarea id: package-listing @@ -33,12 +34,22 @@ body: validations: required: true +- type: checkboxes + id: removal-definitions + attributes: + label: Removal Definitions + description: Please ensure you follow the removal definitions when proposing changes. + options: + - label: I've read the [Removal Definitions](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Debloat-Lists#removal-definitions) + required: true + - type: checkboxes id: acknowledgements attributes: label: Acknowledgements description: Your bug report will be closed if you don't follow the checklist below. options: + - label: I'm willing to submit a Pull Request for this change. - label: This issue is not a duplicate of an existing one. required: true - label: I have chosen an appropriate title. diff --git a/.github/PULL_REQUEST_TEMPLATE/app.md b/.github/PULL_REQUEST_TEMPLATE/app.md new file mode 100644 index 0000000..41e92ae --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/app.md @@ -0,0 +1,31 @@ +## Description + + + +### Related issues + + + + +## How has this been tested? + + + +- [ ] Unit tests added/updated +- [ ] Manual testing performed +- [ ] Tested on the following environment(s): + - OS: + - Desktop Environment: + - Window System/Manager: + - ADB version: + - Rust version: + +## Checklist + +- [ ] I have read the [CONTRIBUTING guidelines](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/CONTRIBUTING.md) +- [ ] My code follows the project's code style +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] My changes generate no new warnings +- [ ] I have tested the application with these changes +- [ ] The CI/CD pipeline passes diff --git a/.github/PULL_REQUEST_TEMPLATE/documentation.md b/.github/PULL_REQUEST_TEMPLATE/documentation.md new file mode 100644 index 0000000..530277e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/documentation.md @@ -0,0 +1,18 @@ +## Description + + + + + +## Documentation Changes + + + +## Checklist + +- [ ] I have read the [CONTRIBUTING guidelines](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/CONTRIBUTING.md) +- [ ] My changes are clear and easy to understand +- [ ] I have checked for grammar and spelling errors +- [ ] I have verified all links are correct +- [ ] I have tested any code examples provided +- [ ] The documentation is properly formatted with markdown diff --git a/.github/PULL_REQUEST_TEMPLATE/packages.md b/.github/PULL_REQUEST_TEMPLATE/packages.md new file mode 100644 index 0000000..38cc9b2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/packages.md @@ -0,0 +1,21 @@ +## Description + + + + + +## Testing + +- [ ] I have tested these packages on a real device or emulator +- [ ] Package names follow correct naming conventions (e.g., `com.example.app`) +- [ ] Package names have been verified against device/ADB output +- [ ] Descriptions are accurate and helpful +- [ ] No duplicate packages added + +## Acknowledgements + +- [ ] I have read the [CONTRIBUTING guidelines](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/CONTRIBUTING.md) +- [ ] I have followed the package addition guidelines +- [ ] I have reviewed the [Removal Definitions](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Debloat-Lists#removal-definitions) in the wiki +- [ ] All package information is accurate and tested +- [ ] I understand my PR may be modified before merging diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..523bbb6 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ +## Description + + + +## Related issues + + + + +## Checklist + +- [ ] I have read the [CONTRIBUTING guidelines](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/CONTRIBUTING.md) +- [ ] I have performed a self-review of my changes +- [ ] My changes generate no new warnings +- [ ] The CI/CD pipeline passes (or is expected to pass) + + diff --git a/.github/release.yml b/.github/release.yml index fd89e5b..b34ac36 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -9,11 +9,6 @@ changelog: - title: Refactors labels: - refactor - - title: Packages/apps - labels: - - package::documentation - - package::addition - - package::breakage - title: Development labels: - ci @@ -21,3 +16,8 @@ changelog: - title: Documentation labels: - documentation + - title: Packages/apps + labels: + - package::documentation + - package::addition + - package::breakage diff --git a/.github/workflows/build_artifacts.yml b/.github/workflows/build_artifacts.yml index bb167e3..63e6542 100644 --- a/.github/workflows/build_artifacts.yml +++ b/.github/workflows/build_artifacts.yml @@ -18,9 +18,9 @@ jobs: - build_target: linux os: ubuntu-22.04 - build_target: macos - os: macos-14 + os: macos-15 - build_target: macos-intel - os: macos-13 + os: macos-15-intel - build_target: windows os: windows-2022 - update_feature: self-update @@ -30,7 +30,6 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - uses: rui314/setup-mold@v1 # faster linker - uses: actions/cache@v4 with: path: | @@ -43,7 +42,7 @@ jobs: restore-keys: ${{ runner.OS }}-release- if: matrix.os == 'ubuntu-22.04' - name: Building - run: cargo build --release --no-default-features --features wgpu,${{ matrix.update_feature }} + run: cargo build --release -p uad-gui --no-default-features --features wgpu,${{ matrix.update_feature }},img - name: Renaming binaries [Windows] if: matrix.os == 'windows-2022' run: mv target/release/uad-ng.exe uad-ng-${{ matrix.build_target }}.exe @@ -69,3 +68,59 @@ jobs: with: name: uad-ng${{ matrix.update_name }}-${{ matrix.build_target }} path: uad-ng-* + + build-cli: + name: Building CLI ${{ matrix.build_target }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - build_target: linux + os: ubuntu-22.04 + - build_target: macos + os: macos-15 + - build_target: macos-intel + os: macos-15-intel + - build_target: windows + os: windows-2022 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target + key: ${{ runner.os }}-release-cli-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.OS }}-release-cli- + if: matrix.os == 'ubuntu-22.04' + - name: Building + run: cargo build --release -p uad-cli + - name: Renaming binaries [Windows] + if: matrix.os == 'windows-2022' + run: mv target/release/uad.exe uad-cli-${{ matrix.build_target }}.exe + - name: Renaming binaries [Others] + if: matrix.os != 'windows-2022' + run: mv target/release/uad uad-cli-${{ matrix.build_target }} + - name: Tarball Linux/MacOS binary + if: matrix.os != 'windows-2022' + run: tar -czf uad-cli-${{ matrix.build_target }}{.tar.gz,} + - name: Install coreutils for macOS + if: startsWith(matrix.os, 'macos') + run: brew install coreutils + - name: Create checksums for binaries and archives [Windows] + if: matrix.os == 'windows-2022' + run: sha256sum uad-cli-${{ matrix.build_target }}.exe | tee uad-cli-${{ matrix.build_target }}.exe-checksum.txt + - name: Create checksums for binaries and archives [Others] + if: matrix.os != 'windows-2022' + run: | + sha256sum uad-cli-${{ matrix.build_target }} | tee uad-cli-${{ matrix.build_target }}-checksum + sha256sum uad-cli-${{ matrix.build_target }}.tar.gz | tee uad-cli-${{ matrix.build_target }}.tar.gz-checksum + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: uad-cli-${{ matrix.build_target }} + path: uad-cli-* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 755976d..da742c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,29 +21,29 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-22.04, windows-2022, macOS-14] + os: [ubuntu-22.04, windows-2022, macos-15] lint: [check, test, clippy, fmt] exclude: # https://github.com/community/community/discussions/7835 - os: windows-2022 lint: clippy - os: windows-2022 lint: fmt - - os: macOS-14 + - os: macos-15 lint: clippy - - os: macOS-14 + - os: macos-15 lint: fmt include: - lint: check args: " --all-features" + env-flag: "-D warnings" - lint: test args: "" - lint: clippy - args: " --all --all-features" + args: " --all-features -- -D clippy::all -W clippy::style" - lint: fmt - args: " --all -- --check" + args: " -- --check" steps: - uses: actions/checkout@v4 - - uses: rui314/setup-mold@v1 # faster linker - uses: actions/cache@v4 with: path: | @@ -57,7 +57,8 @@ jobs: - uses: dtolnay/rust-toolchain@stable with: components: clippy,rustfmt - - run: cargo ${{ matrix.lint }}${{ matrix.args }} + - shell: bash + run: RUSTFLAGS='${{ matrix.env-flag }}' cargo ${{ matrix.lint }}${{ matrix.args }} coverage: name: coverage diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3baf45d..66ef045 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,5 +25,10 @@ jobs: - name: Create release uses: softprops/action-gh-release@v2 with: - files: uad-ng-*/* + files: | + uad-ng-*/* + uad-cli-*/* generate_release_notes: true + body: | + > [!NOTE] + > 📦 **Package list updates don't require a new app version**—UAD-ng automatically fetches the latest package definitions on launch (requires internet connection). diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..39a8e77 --- /dev/null +++ b/.mailmap @@ -0,0 +1,11 @@ +Rudxain +Rudxain <76864299+Rudxain@users.noreply.github.com> Ricardo Fernández Serrata <76864299+Rudxain@users.noreply.github.com> +Anonymoussaurus <50231698+AnonymousWP@users.noreply.github.com> AnonymousWP <50231698+AnonymousWP@users.noreply.github.com> +Anonymoussaurus +# w1nst0n +# 0x192 +# “Frigyes06” +# Frigyes +# Frigyes06 +# Frigyes Erdosi-Szucs +# Frigyes Erdosi Szucs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3fd6a78..1df3b89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,12 +2,42 @@ ## For who is this guide? -This guide is meant for users who want to contribute to the codebase of Universal Android Debloater Next Generation, whether that is the application code or the JSON-file for adding packages. To keep all processes streamlined and consistent, we're asking you to stick to this guide whenever contributing. +This guide is meant for users who want to contribute to the codebase of Universal Android Debloater Next Generation, whether that is the application code or [the "database"-file for adding packages](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute). To keep all processes streamlined and consistent, we're asking you to stick to this guide whenever contributing. Even though the guide is made for contributors, it's also strongly recommended that the UAD-ng team sticks to these guidelines. After all, we're a prime example. ## What are the guidelines? +### Mass edits + +If you've performed massive edits via automation, you must specify what automation you used. For example, if you ran the command: + +```sh +sed -i 's/a/b/' resources/assets/uad_lists.json +``` + +You should copy-paste that cmd to the pull-request description. This rule applies even if you use "proper" cmds such as `jq`, which safely edit structured data. And it also applies to AI, *especially* LLMs. + +This is required so that we can review your big patch without reading it. This improves [transparency](https://en.wikipedia.org/wiki/Transparency_(behavior)), which makes you more trust-worthy! Bonus points if you can provide a sequence of cmds that proves your patch contains exactly what you said it does. For the simple `sed` case, something like: + +```sh +# alt: `gh pr checkout 0000 && git checkout main` +git remote add fork https://github.com/user/uadng +git fetch fork +# example commit hash from upstream (not fork); +# more reproducible than branch-name +git checkout beefcafe +sed -i 's/a/b/' resources/assets/uad_lists.json +# compare unstaged change with commit from fork +git diff cafebeef +``` + +Should be enough. + +You should be careful with mass-editing anyways. Even if the verification is successful, the effects [might not be what you expect](https://en.wikipedia.org/wiki/Scunthorpe_problem). + +Since AI is non-deterministic, the version number is optional, but it's helpful to know how "intelligent" it is. AI edits are non-reproducible, so "verification scripts" are useless. + ### Branching strategy As for our branching strategy, we're using [Trunk-Based Development](https://trunkbaseddevelopment.com/#one-line-summary). @@ -33,3 +63,30 @@ If you want to [back-port](https://en.wikipedia.org/wiki/Backporting) (GitHub's ### Commit messages As for commits, we prefer using [Conventional Commit Messages](https://gist.github.com/qoomon/5dfcdf8eec66a051ecd85625518cfd13). When working in any of the branches listed above (if there's an existing issue for it), close it using a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword). For more information regarding Conventional Commit Messages, see as well. + +### Issue labels + +When creating issues, they are automatically labeled based on the [issue template](.github/ISSUE_TEMPLATE/) you choose. These labels help categorize work and generate release notes. + +| Label | Purpose | Issue template | +| ----- | ------- | -------------- | +| `bug` | Software bugs in UAD-ng | Bug Report | +| `enhancement` | New feature requests | Feature Request | +| `package::addition` | Adding new packages to the debloat list | Add new package(s) | +| `package::breakage` | Issues caused by debloating | Debloat issue report | +| `package::documentation` | Updating package descriptions or recommendations | Update apps description or recommendation | +| `documentation` | Improvements to docs/wiki | UAD-ng documentation | +| `ci` | CI/CD related issues | CI/CD | +| `refactor` | Code refactoring | — (maintainer-assigned) | +| `dependencies` | Dependency updates | — (maintainer-assigned) | + +Labels are also used to automatically generate categorized [release notes](.github/release.yml). Each label maps to a changelog section: + +| Label(s) | Changelog category | +| -------- | ------------------ | +| `enhancement` | Features | +| `bug` | Fixed | +| `refactor` | Refactors | +| `package::addition`, `package::breakage`, `package::documentation` | Packages/apps | +| `ci`, `dependencies` | Development | +| `documentation` | Documentation | diff --git a/Cargo.lock b/Cargo.lock index 8250903..e40c813 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.28" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,52 +14,55 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", ] [[package]] -name = "aho-corasick" -version = "1.1.3" +name = "aligned" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" dependencies = [ - "memchr", + "as-slice", ] [[package]] -name = "allocator-api2" -version = "0.2.18" +name = "aligned-vec" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] [[package]] name = "android-activity" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.6.0", + "bitflags 2.10.0", "cc", "cesu8", "jni", @@ -70,7 +73,16 @@ dependencies = [ "ndk-context", "ndk-sys", "num_enum", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "android-build" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cac4c64175d504608cf239756339c07f6384a476f97f20a7043f92920b0b8fd" +dependencies = [ + "windows-sys 0.52.0", ] [[package]] @@ -79,12 +91,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -95,25 +101,89 @@ dependencies = [ ] [[package]] -name = "approx" -version = "0.5.1" +name = "anstream" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ - "num-traits", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "as-raw-xcb-connection" @@ -121,58 +191,49 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "ash" -version = "0.37.3+1.3.251" +version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.7.4", + "libloading", ] [[package]] name = "ashpd" -version = "0.8.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +checksum = "de3d60bee1a1d38c2077030f4788e1b4e31058d2e79a8cfc8f2b440bd44db290" dependencies = [ "async-fs", "async-net", "enumflags2", "futures-channel", "futures-util", - "rand", + "rand 0.8.6", "serde", "serde_repr", "url", - "zbus 4.3.1", -] - -[[package]] -name = "ashpd" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" -dependencies = [ - "async-fs", - "async-net", - "enumflags2", - "futures-channel", - "futures-util", - "rand", - "serde", - "serde_repr", - "url", - "zbus 5.2.0", + "zbus", ] [[package]] name = "async-broadcast" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -191,9 +252,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -203,22 +264,23 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", + "pin-project-lite", "slab", ] [[package]] name = "async-fs" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ "async-lock", "blocking", @@ -231,7 +293,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-executor", "async-io", "async-lock", @@ -242,30 +304,29 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", "futures-lite", "parking", "polling", - "rustix", + "rustix 1.1.3", "slab", - "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -283,22 +344,20 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener 5.3.1", + "event-listener 5.4.1", "futures-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", + "rustix 1.1.3", ] [[package]] @@ -309,14 +368,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -324,17 +383,17 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix", + "rustix 1.1.3", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "async-std" -version = "1.13.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" dependencies = [ "async-channel 1.9.0", "async-global-executor", @@ -364,13 +423,13 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] @@ -381,9 +440,52 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" +dependencies = [ + "arrayvec", +] [[package]] name = "base64" @@ -393,24 +495,24 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bit_field" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -420,9 +522,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitstream-io" +version = "4.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +dependencies = [ + "core2", +] [[package]] name = "block" @@ -430,34 +541,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" -dependencies = [ - "block-sys", - "objc2 0.4.1", -] - [[package]] name = "block2" version = "0.5.1" @@ -468,12 +551,21 @@ dependencies = [ ] [[package]] -name = "blocking" -version = "1.6.1" +name = "block2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "async-channel 2.3.1", + "objc2 0.6.3", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel 2.5.0", "async-task", "futures-io", "futures-lite", @@ -481,81 +573,107 @@ dependencies = [ ] [[package]] -name = "bumpalo" -version = "3.16.0" +name = "built" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" [[package]] -name = "by_address" -version = "1.2.1" +name = "bumpalo" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.6.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "calloop" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "log", "polling", - "rustix", + "rustix 0.38.44", "slab", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +dependencies = [ + "bitflags 2.10.0", + "polling", + "rustix 1.1.3", + "slab", + "tracing", ] [[package]] name = "calloop-wayland-source" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop", - "rustix", + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.3", + "rustix 1.1.3", "wayland-backend", "wayland-client", ] [[package]] name = "cc" -version = "1.2.16" +version = "1.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -569,9 +687,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -587,34 +705,82 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.52.6", + "windows-link", ] [[package]] -name = "clipboard-win" -version = "5.4.0" +name = "clap" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_complete" +version = "4.5.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c757a3b7e39161a4e56f9365141ada2a6c915a8622c408ab6bb4b5d047371031" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" dependencies = [ "error-code", ] [[package]] name = "clipboard_macos" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" +checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f" dependencies = [ - "objc", - "objc-foundation", - "objc_id", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -628,22 +794,23 @@ dependencies = [ [[package]] name = "clipboard_x11" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c" +checksum = "bd63e33452ffdafd39924c4f05a5dd1e94db646c779c6bd59148a3d95fff5ad4" dependencies = [ - "thiserror", + "thiserror 2.0.18", "x11rb", ] [[package]] name = "codespan-reporting" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ + "serde", "termcolor", - "unicode-width", + "unicode-width 0.2.2", ] [[package]] @@ -652,46 +819,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "colored" -version = "1.9.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ - "is-terminal", "lazy_static", - "winapi", -] - -[[package]] -name = "com" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" -dependencies = [ - "com_macros", -] - -[[package]] -name = "com_macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" -dependencies = [ - "com_macros_support", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "com_macros_support" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "windows-sys 0.59.0", ] [[package]] @@ -713,6 +854,35 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie_store" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc4bff745c9b4c7fb1e97b25d13153da2bc7796260141df62378998d070207f" +dependencies = [ + "cookie", + "document-features", + "idna", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -724,10 +894,20 @@ dependencies = [ ] [[package]] -name = "core-foundation-sys" -version = "0.8.6" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -736,8 +916,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "foreign-types", "libc", ] @@ -749,23 +929,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] [[package]] -name = "cosmic-text" -version = "0.10.0" +name = "core-graphics-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75acbfb314aeb4f5210d379af45ed1ec2c98c7f1790bf57b8a4c562ac0c51b71" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" dependencies = [ - "fontdb", "libm", +] + +[[package]] +name = "cosmic-text" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173852283a9a57a3cbe365d86e74dc428a09c50421477d5ad6fe9d9509e37737" +dependencies = [ + "bitflags 2.10.0", + "fontdb", + "harfrust", + "linebender_resource_handle", "log", "rangemap", - "rustc-hash", - "rustybuzz", + "rustc-hash 1.1.0", "self_cell", + "skrifa", + "smol_str", "swash", "sys-locale", "unicode-bidi", @@ -774,29 +986,20 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -813,69 +1016,61 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "crypto-common" -version = "0.1.6" +name = "cryoglyph" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "08bc795bdbccdbd461736fb163930a009da6597b226d6f6fce33e7a8eb6ec519" dependencies = [ - "generic-array", - "typenum", + "cosmic-text", + "etagere", + "lru", + "rustc-hash 2.1.1", + "wgpu", ] [[package]] name = "csv" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] [[package]] name = "ctor-lite" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" +checksum = "b29fccfdaeb0f9bd90da5759b1d0eaa2f6cfcfe90960124cfc83141ed4e111fd" [[package]] name = "cursor-icon" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" - -[[package]] -name = "d3d12" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307" -dependencies = [ - "bitflags 2.6.0", - "libloading 0.8.4", - "winapi", -] +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] name = "dark-light" @@ -883,43 +1078,42 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18e1a09f280e29a8b00bc7e81eca5ac87dca0575639c9422a5fa25a07bb884b8" dependencies = [ - "ashpd 0.10.2", + "ashpd", "async-std", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", "web-sys", - "winreg", + "winreg 0.52.0", ] [[package]] -name = "digest" -version = "0.10.7" +name = "deranged" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ - "block-buffer", - "crypto-common", + "powerfmt", ] [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -928,13 +1122,45 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "libc", + "objc2 0.6.3", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dlib" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.4", + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", ] [[package]] @@ -944,75 +1170,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "drm" -version = "0.12.0" +name = "dpi" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" -dependencies = [ - "bitflags 2.6.0", - "bytemuck", - "drm-ffi", - "drm-fourcc", - "rustix", -] - -[[package]] -name = "drm-ffi" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" -dependencies = [ - "drm-sys", - "rustix", -] - -[[package]] -name = "drm-fourcc" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" - -[[package]] -name = "drm-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986" -dependencies = [ - "libc", - "linux-raw-sys 0.6.4", -] +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "embed-resource" -version = "2.4.2" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" +checksum = "55a075fc573c64510038d7ee9abc7990635863992f83ebc52c8b433b8411a02e" dependencies = [ "cc", "memchr", "rustc_version", "toml", "vswhom", - "winreg", + "winreg 0.55.0", ] [[package]] name = "endi" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enumflags2" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ "enumflags2_derive", "serde", @@ -1020,42 +1219,62 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "etagere" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e2f1e3be19fb10f549be8c1bf013e8675b4066c445e36eb76d2ebb2f54ee495" +checksum = "fc89bf99e5dc15954a60f707c1e09d7540e5cd9af85fa75caa0b510bc08c5342" dependencies = [ "euclid", "svg_fmt", @@ -1063,9 +1282,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.10" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f0eb73b934648cd7a4a61f1b15391cd95dab0b4da6e2e66c2a072c144b4a20" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" dependencies = [ "num-traits", ] @@ -1078,9 +1297,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.3.1" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -1089,22 +1308,21 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "pin-project-lite", ] [[package]] name = "exr" -version = "1.72.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", - "flume", "half", "lebe", "miniz_oxide", @@ -1114,31 +1332,56 @@ dependencies = [ ] [[package]] -name = "fast-srgb8" -version = "1.0.0" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "fastrand" -version = "2.1.0" +name = "fax" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix 1.1.3", + "windows-sys 0.59.0", +] [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "fern" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" dependencies = [ "colored", "log", @@ -1146,65 +1389,73 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", ] [[package]] -name = "flate2" -version = "1.0.30" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "flume" -version = "0.11.0" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "font-types" -version = "0.5.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34fd7136aca682873d859ef34494ab1a7d3f57ecd485ed40eb6437ee8c85aa29" +checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" dependencies = [ "bytemuck", ] [[package]] name = "fontconfig-parser" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" dependencies = [ "roxmltree", ] [[package]] name = "fontdb" -version = "0.15.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" dependencies = [ "fontconfig-parser", "log", - "memmap2 0.8.0", + "memmap2", "slotmap", "tinyvec", - "ttf-parser 0.19.2", + "ttf-parser", ] [[package]] @@ -1225,7 +1476,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] @@ -1236,18 +1487,18 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1260,9 +1511,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1270,15 +1521,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1288,15 +1539,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ "fastrand", "futures-core", @@ -1307,32 +1558,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1346,31 +1597,21 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "gethostname" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "libc", - "windows-targets 0.48.5", + "rustix 1.1.3", + "windows-link", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -1378,10 +1619,35 @@ dependencies = [ ] [[package]] -name = "gif" -version = "0.13.1" +name = "getrandom" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "gif" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" dependencies = [ "color_quant", "weezl", @@ -1418,9 +1684,9 @@ dependencies = [ [[package]] name = "glow" -version = "0.13.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" dependencies = [ "js-sys", "slotmap", @@ -1430,32 +1696,20 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" dependencies = [ "gl_generator", ] -[[package]] -name = "glyphon" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a62d0338e4056db6a73221c2fb2e30619452f6ea9651bac4110f51b0f7a7581" -dependencies = [ - "cosmic-text", - "etagere", - "lru", - "wgpu", -] - [[package]] name = "gpu-alloc" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "gpu-alloc-types", ] @@ -1465,40 +1719,39 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", ] [[package]] name = "gpu-allocator" -version = "0.25.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" dependencies = [ "log", "presser", - "thiserror", - "winapi", - "windows", + "thiserror 1.0.69", + "windows 0.58.0", ] [[package]] name = "gpu-descriptor" -version = "0.2.4" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "gpu-descriptor-types", - "hashbrown 0.14.5", + "hashbrown 0.15.5", ] [[package]] name = "gpu-descriptor-types" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", ] [[package]] @@ -1513,56 +1766,58 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "harfrust" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c020db12c71d8a12a3fe7607873cade3a01a6287e29d540c8723276221b9d8" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "core_maths", + "read-fonts", + "smallvec", ] [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "ahash", - "allocator-api2", + "foldhash 0.1.5", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "hassle-rs" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "bitflags 2.6.0", - "com", - "libc", - "libloading 0.8.4", - "thiserror", - "widestring", - "winapi", + "foldhash 0.2.0", ] [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1577,17 +1832,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] -name = "iana-time-zone" -version = "0.1.60" +name = "home" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -1601,57 +1882,71 @@ dependencies = [ [[package]] name = "iced" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4eb0fbbefb8c428b70680e77ed9013887b17c1d6be366b40f264f956d1a096" +checksum = "000e01026c93ba643f8357a3db3ada0e6555265a377f6f9291c472f6dd701fb3" dependencies = [ "iced_core", + "iced_debug", "iced_futures", "iced_renderer", + "iced_runtime", "iced_widget", "iced_winit", "image", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "iced_core" -version = "0.12.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7e6bbd197f311ed3d8b71651876b0ce01318fde52cda862a9a7a4373c9b930" +checksum = "91ab1937d699403e7e69252ae743a902bcee9f4ab2052cc4c9a46fcf34729d85" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", + "bytes", "glam", + "lilt", "log", "num-traits", - "palette", - "raw-window-handle", + "rustc-hash 2.1.1", "smol_str", - "thiserror", + "thiserror 2.0.18", "web-time", - "xxhash-rust", +] + +[[package]] +name = "iced_debug" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25035ab0215a620e53f4103e36fc4e59a1fb2817e4bfc38a30ad27b4202ea0be" +dependencies = [ + "iced_core", + "iced_futures", + "log", ] [[package]] name = "iced_futures" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370bad88fb3832cbeeb3fa6c486b4701fb7e8da32a753b3101d4ce81fc1d9497" +checksum = "8c0c85ccad42dfbec7293c36c018af0ea0dbcc52d137a4a9a0b0f6822a3fdf0a" dependencies = [ "futures", "iced_core", "log", + "rustc-hash 2.1.1", "wasm-bindgen-futures", - "wasm-timer", + "wasmtimer", ] [[package]] name = "iced_graphics" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a044c193ef0840eacabfa05424717331d1fc5b3ecb9a89316200c75da2ba9a4" +checksum = "234ca1c2cec4155055f68fa5fad1b5242c496ac8238d80a259bca382fb44a102" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "bytemuck", "cosmic-text", "half", @@ -1660,191 +1955,309 @@ dependencies = [ "image", "kamadak-exif", "log", - "once_cell", "raw-window-handle", - "rustc-hash", - "thiserror", + "rustc-hash 2.1.1", + "thiserror 2.0.18", "unicode-segmentation", - "xxhash-rust", +] + +[[package]] +name = "iced_program" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dfafec2947cda688d8eb00dac337ba11aa60f9ef6335aed343e189d26e4a673" +dependencies = [ + "iced_graphics", + "iced_runtime", ] [[package]] name = "iced_renderer" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c281e03001d566058f53dec9325bbe61c62da715341206d2627f57a3ecc7f69" +checksum = "250cc0802408e8c077986ec56c7d07c65f423ee658a4b9fd795a1f2aae5dac05" dependencies = [ "iced_graphics", "iced_tiny_skia", "iced_wgpu", "log", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "iced_runtime" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a79f852c01cc6d61663c94379cb3974ac3ad315a28c504e847d573e094f46822" +checksum = "d1889b819ce4c06674183242e336c8d49465665441396914dc07cc86f44fa8d4" dependencies = [ + "bytes", "iced_core", "iced_futures", "raw-window-handle", - "thiserror", -] - -[[package]] -name = "iced_style" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ea42a740915d2a5a9ff9c3aa0bca28b16e9fb660bc8f675eed71d186cadb579" -dependencies = [ - "iced_core", - "once_cell", - "palette", + "thiserror 2.0.18", ] [[package]] name = "iced_tiny_skia" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2228781f4d381a1cbbd7905a9f077351aa8d37269094021d5d9e779f130aff" +checksum = "fe0acf8b75a3bc914aff5f2329fdffc1b36eeaea29dda0e4bd232f1c62e9cc3d" dependencies = [ "bytemuck", "cosmic-text", + "iced_debug", "iced_graphics", "kurbo", "log", - "rustc-hash", + "rustc-hash 2.1.1", "softbuffer", "tiny-skia", - "xxhash-rust", ] [[package]] name = "iced_wgpu" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c243b6700452886aac1ee1987e84d9fb43b56b53fea9a1eb67713fd0fde244" +checksum = "ff144a999b0ca0f8a10257934500060240825c42e950ec0ebee9c8ae30561c13" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "bytemuck", + "cryoglyph", "futures", "glam", - "glyphon", "guillotiere", + "iced_debug", "iced_graphics", "log", - "once_cell", + "rustc-hash 2.1.1", + "thiserror 2.0.18", "wgpu", ] [[package]] name = "iced_widget" -version = "0.12.3" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01b2212adecf1cb80e2267f302c0e0c263e55f97812056949199ccf9f0b908" +checksum = "b1596afa0d3109c2618e8bc12bae6c11d3064df8f95c42dfce570397dbe957ab" dependencies = [ "iced_renderer", - "iced_runtime", - "iced_style", + "log", "num-traits", - "thiserror", + "rustc-hash 2.1.1", + "thiserror 2.0.18", "unicode-segmentation", ] [[package]] name = "iced_winit" -version = "0.12.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f66831d0e399b93f631739121a6171780d344b275d56808b9504d8ca75c7d2" +checksum = "8b7dbedc47562d1de3b9707d939f678b88c382004b7ab5a18f7a7dd723162d75" dependencies = [ - "iced_graphics", - "iced_runtime", - "iced_style", + "iced_debug", + "iced_program", "log", - "thiserror", + "mundy", + "rustc-hash 2.1.1", + "thiserror 2.0.18", "tracing", + "wasm-bindgen-futures", "web-sys", - "winapi", "window_clipboard", "winit", ] [[package]] -name = "icrate" -version = "0.0.4" +name = "icu_collections" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ - "block2 0.3.0", - "dispatch", - "objc2 0.4.1", + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "idna" -version = "0.5.0" +name = "icu_locale_core" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "image" -version = "0.24.9" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", "color_quant", "exr", "gif", - "jpeg-decoder", + "image-webp", + "moxcms", "num-traits", "png", "qoi", + "ravif", + "rayon", + "rgb", "tiff", + "zune-core 0.5.1", + "zune-jpeg 0.5.12", ] +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + [[package]] name = "indexmap" -version = "2.7.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] -name = "instant" -version = "0.1.13" +name = "interpolate_name" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "is-terminal" -version = "0.4.12" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.52.0", + "either", ] [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jni" @@ -1857,7 +2270,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -1870,36 +2283,29 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] - [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "kamadak-exif" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077" +checksum = "1130d80c7374efad55a117d715a3af9368f0fa7a2c54573afc15a188cd984837" dependencies = [ "mutate_once", ] @@ -1911,7 +2317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.4", + "libloading", "pkg-config", ] @@ -1947,104 +2353,132 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "lebe" -version = "0.5.2" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] -name = "libloading" -version = "0.7.4" +name = "libfuzzer-sys" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" dependencies = [ - "cfg-if", - "winapi", + "arbitrary", + "cc", ] [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-link", ] [[package]] name = "libm" -version = "0.2.8" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.0.2" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.7.1", ] [[package]] -name = "libredox" -version = "0.1.3" +name = "lilt" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "f67562e5eff6b20553fa9be1c503356768420994e28f67e3eafe6f41910e57ad" dependencies = [ - "bitflags 2.6.0", - "libc", + "web-time", ] [[package]] -name = "linux-raw-sys" -version = "0.4.14" +name = "linebender_resource_handle" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" [[package]] name = "linux-raw-sys" -version = "0.6.4" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b5399f6804fbab912acbd8878ed3532d506b7c951b8f9f164ef90fef39e3f4" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.22" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" dependencies = [ "value-bag", ] [[package]] -name = "lru" -version = "0.12.3" +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "hashbrown 0.14.5", + "imgref", ] +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2055,25 +2489,26 @@ dependencies = [ ] [[package]] -name = "memchr" -version = "2.7.4" +name = "maybe-rayon" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memmap2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ - "libc", + "cfg-if", + "rayon", ] [[package]] -name = "memmap2" -version = "0.9.4" +name = "memchr" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", ] @@ -2089,13 +2524,13 @@ dependencies = [ [[package]] name = "metal" -version = "0.27.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block", - "core-graphics-types", + "core-graphics-types 0.2.0", "foreign-types", "log", "objc", @@ -2104,53 +2539,105 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", "simd-adler32", ] [[package]] -name = "mutate_once" -version = "0.1.1" +name = "mio" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moxcms" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "mundy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523813c9e194ec43693805214eb112551f99382115b67f38600d724a692e7e8b" +dependencies = [ + "android-build", + "async-io", + "cfg-if", + "dispatch", + "futures-channel", + "futures-lite", + "jni", + "ndk-context", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", + "pin-project-lite", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.62.2", + "zbus", +] + +[[package]] +name = "mutate_once" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d2233c9842d08cfe13f9eac96e207ca6a2ea10b80259ebe8ad0268be27d2af" [[package]] name = "naga" -version = "0.19.2" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ + "arrayvec", "bit-set", - "bitflags 2.6.0", + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases 0.2.1", "codespan-reporting", + "half", + "hashbrown 0.16.1", "hexf-parse", "indexmap", + "libm", "log", "num-traits", - "rustc-hash", + "once_cell", + "rustc-hash 1.1.0", "spirv", - "termcolor", - "thiserror", - "unicode-xid", + "thiserror 2.0.18", + "unicode-ident", ] [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "jni-sys", "log", "ndk-sys", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2161,24 +2648,100 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.5.0+25.2.9519653" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ "jni-sys", ] [[package]] -name = "nix" -version = "0.29.0" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ - "bitflags 2.6.0", + "smallvec", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.10.0", "cfg-if", - "cfg_aliases 0.2.1", + "cfg_aliases 0.1.1", "libc", - "memoffset", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", ] [[package]] @@ -2188,37 +2751,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] @@ -2228,18 +2793,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", ] [[package]] @@ -2248,16 +2801,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" -[[package]] -name = "objc2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" -dependencies = [ - "objc-sys", - "objc2-encode 3.0.0", -] - [[package]] name = "objc2" version = "0.5.2" @@ -2265,7 +2808,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", - "objc2-encode 4.0.3", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", ] [[package]] @@ -2274,14 +2826,70 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block2 0.5.1", "libc", "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-cloud-kit 0.3.2", + "objc2-core-data 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -2290,10 +2898,45 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -2304,21 +2947,62 @@ checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-metal", ] [[package]] -name = "objc2-encode" -version = "3.0.0" +name = "objc2-core-image" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", +] [[package]] name = "objc2-encode" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" @@ -2326,23 +3010,59 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block2 0.5.1", "dispatch", "libc", "objc2 0.5.2", ] +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + [[package]] name = "objc2-metal" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -2351,36 +3071,91 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "block2 0.5.1", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-metal", ] [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-quartz-core" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "cc", + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-symbols" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "objc", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "option-ext" @@ -2390,11 +3165,21 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orbclient" -version = "0.3.47" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" +checksum = "52ad2c6bae700b7aa5d1cc30c59bdd3a1c180b09dbaea51e2ae2b8e1cf211fdd" dependencies = [ - "libredox 0.0.2", + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" +dependencies = [ + "num-traits", ] [[package]] @@ -2409,89 +3194,40 @@ dependencies = [ [[package]] name = "owned_ttf_parser" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" dependencies = [ - "ttf-parser 0.24.0", -] - -[[package]] -name = "palette" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" -dependencies = [ - "approx", - "fast-srgb8", - "palette_derive", - "phf", -] - -[[package]] -name = "palette_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" -dependencies = [ - "by_address", - "proc-macro2", - "quote", - "syn 2.0.70", + "ttf-parser", ] [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2500,59 +3236,43 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] -name = "phf" -version = "0.11.2" +name = "pin-project" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ - "phf_macros", - "phf_shared", + "pin-project-internal", ] [[package]] -name = "phf_generator" -version = "0.11.2" +name = "pin-project-internal" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", "proc-macro2", "quote", - "syn 2.0.70", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2562,9 +3282,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -2573,17 +3293,17 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "png" -version = "0.17.13" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.10.0", "crc32fast", "fdeflate", "flate2", @@ -2592,30 +3312,62 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi", "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", + "rustix 1.1.3", + "windows-sys 0.61.2", ] [[package]] name = "pollster" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "presser" @@ -2624,38 +3376,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "proc-macro2", + "syn", ] [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.22.22", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7186d3822593aa4393561d186d1393b3923e9d6163d3fbfd6e825e3e6cf3e6a8" +dependencies = [ + "num-traits", +] [[package]] name = "qoi" @@ -2667,32 +3441,64 @@ dependencies = [ ] [[package]] -name = "quick-xml" -version = "0.34.0" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.8.5" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -2702,7 +3508,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -2711,20 +3527,79 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] name = "range-alloc" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" +checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" [[package]] name = "rangemap" -version = "1.5.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.2", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] [[package]] name = "raw-window-handle" @@ -2734,9 +3609,9 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -2744,9 +3619,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2754,32 +3629,15 @@ dependencies = [ [[package]] name = "read-fonts" -version = "0.19.3" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b8af39d1f23869711ad4cea5e7835a20daa987f80232f7f2a2374d648ca64d" +checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" dependencies = [ "bytemuck", + "core_maths", "font-types", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2791,53 +3649,33 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +dependencies = [ + "bitflags 2.10.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom", - "libredox 0.1.3", - "thiserror", + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", ] -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - [[package]] name = "renderdoc-sys" version = "1.1.0" @@ -2846,45 +3684,55 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "retry" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9166d72162de3575f950507683fac47e30f6f2c3836b71b7fbc61aa517c9c5f4" +checksum = "1cab9bd343c737660e523ee69f788018f3db686d537d2fd0f99c9f747c1bda4f" dependencies = [ - "rand", + "rand 0.9.2", ] [[package]] name = "rfd" -version = "0.14.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220" dependencies = [ - "ashpd 0.8.1", - "block", - "dispatch", + "block2 0.6.2", + "dispatch2", "js-sys", + "libc", "log", - "objc", - "objc-foundation", - "objc_id", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "percent-encoding", "pollster", "raw-window-handle", - "urlencoding", "wasm-bindgen", "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", "web-sys", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] -name = "ring" -version = "0.17.13" +name = "rgb" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -2892,9 +3740,9 @@ dependencies = [ [[package]] name = "roxmltree" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] name = "rustc-hash" @@ -2903,32 +3751,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustc_version" -version = "0.4.0" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", @@ -2941,15 +3808,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -2957,27 +3827,38 @@ dependencies = [ ] [[package]] -name = "rustybuzz" -version = "0.11.0" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rustyline" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63" dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "libm", - "smallvec", - "ttf-parser 0.20.0", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", + "bitflags 2.10.0", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "unicode-segmentation", + "unicode-width 0.1.14", + "utf8parse", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -3002,89 +3883,90 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "ab_glyph", "log", - "memmap2 0.9.4", - "smithay-client-toolkit", + "memmap2", + "smithay-client-toolkit 0.19.2", "tiny-skia", ] [[package]] name = "self_cell" -version = "1.0.4" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", - "ryu", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_repr" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", + "serde_core", ] [[package]] @@ -3095,30 +3977,34 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] -name = "siphasher" -version = "0.3.11" +name = "simd_helpers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] [[package]] name = "skrifa" -version = "0.19.3" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab45fb68b53576a43d4fc0e9ec8ea64e29a4d2cc7f44506964cb75f288222e9" +checksum = "8c31071dedf532758ecf3fed987cdb4bd9509f900e026ab684b4ecb81ea49841" dependencies = [ "bytemuck", "read-fonts", @@ -3126,43 +4012,40 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smithay-client-toolkit" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.6.0", - "calloop", - "calloop-wayland-source", + "bitflags 2.10.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", "cursor-icon", "libc", "log", - "memmap2 0.9.4", - "rustix", - "thiserror", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -3174,13 +4057,40 @@ dependencies = [ ] [[package]] -name = "smithay-clipboard" -version = "0.7.1" +name = "smithay-client-toolkit" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.10.0", + "calloop 0.14.3", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.3", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" dependencies = [ "libc", - "smithay-client-toolkit", + "smithay-client-toolkit 0.20.0", "wayland-backend", ] @@ -3194,56 +4104,61 @@ dependencies = [ ] [[package]] -name = "softbuffer" -version = "0.4.5" +name = "socket2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d623bff5d06f60d738990980d782c8c866997d9194cfe79ecad00aa2f76826dd" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "softbuffer" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" dependencies = [ "as-raw-xcb-connection", "bytemuck", - "cfg_aliases 0.2.1", - "core-graphics", - "drm", "fastrand", - "foreign-types", "js-sys", - "log", - "memmap2 0.9.4", - "objc2 0.5.2", - "objc2-app-kit", - "objc2-foundation", - "objc2-quartz-core", + "memmap2", + "ndk", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", "raw-window-handle", - "redox_syscall 0.5.2", - "rustix", + "redox_syscall 0.5.18", + "rustix 1.1.3", "tiny-xlib", + "tracing", "wasm-bindgen", "wayland-backend", "wayland-client", "wayland-sys", "web-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", "x11rb", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3256,6 +4171,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -3264,15 +4185,15 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svg_fmt" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" [[package]] name = "swash" -version = "0.1.17" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d7773d67fe3373048cf840bfcc54ec3207cfc1e95c526b287ef2eb5eff9faf6" +checksum = "47846491253e976bdd07d0f9cc24b7daf24720d11309302ccbbc6e6b6e53550a" dependencies = [ "skrifa", "yazi", @@ -3281,9 +4202,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.109" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3291,30 +4212,30 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.70" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn", ] [[package]] name = "sys-locale" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" dependencies = [ "libc", ] [[package]] name = "tar" -version = "0.4.41" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -3323,14 +4244,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ - "cfg-if", "fastrand", - "rustix", - "windows-sys 0.52.0", + "getrandom 0.4.1", + "once_cell", + "rustix 1.1.3", + "windows-sys 0.61.2", ] [[package]] @@ -3344,33 +4266,87 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "tiff" -version = "0.9.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" dependencies = [ + "fax", "flate2", - "jpeg-decoder", + "half", + "quick-error", "weezl", + "zune-jpeg 0.4.21", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", ] [[package]] @@ -3384,7 +4360,6 @@ dependencies = [ "bytemuck", "cfg-if", "log", - "png", "tiny-skia-path", ] @@ -3401,22 +4376,32 @@ dependencies = [ [[package]] name = "tiny-xlib" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d52f22673960ad13af14ff4025997312def1223bfa7c8e4949d099e6b3d5d1c" +checksum = "0324504befd01cab6e0c994f34b2ffa257849ee019d3fb3b64fb2c858887d89e" dependencies = [ "as-raw-xcb-connection", "ctor-lite", - "libloading 0.8.4", + "libloading", "pkg-config", "tracing", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -3428,56 +4413,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "toml" -version = "0.8.14" +name = "tokio" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "serde", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_parser", + "toml_writer", + "winnow", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap", "toml_datetime", - "winnow 0.5.40", + "toml_parser", + "winnow", ] [[package]] -name = "toml_edit" -version = "0.22.22" +name = "toml_parser" +version = "1.0.7+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "247eaa3197818b831697600aadf81514e577e0cba5eab10f7e064e78ae154df1" dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.22", + "winnow", ] +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3485,69 +4505,87 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] [[package]] name = "ttf-parser" -version = "0.19.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] [[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +name = "uad-cli" +version = "1.2.0" +dependencies = [ + "chrono", + "clap", + "clap_complete", + "csv", + "dirs", + "log", + "retry", + "rustyline", + "serde", + "serde_json", + "tokio", + "toml", + "uad-core", + "ureq", +] [[package]] -name = "ttf-parser" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uad-ng" -version = "1.1.2" +name = "uad-core" +version = "1.2.0" dependencies = [ "chrono", "csv", + "dirs", + "flate2", + "log", + "retry", + "serde", + "serde_json", + "tar", + "toml", + "ureq", + "win32console", +] + +[[package]] +name = "uad-gui" +version = "1.2.0" +dependencies = [ + "chrono", "dark-light", "dirs", "embed-resource", "fern", "flate2", "iced", + "image", "log", - "regex", - "retry", "rfd", - "serde", - "serde_json", "tar", - "toml", - "ureq", + "uad-core", "win32console", ] @@ -3564,27 +4602,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-bidi-mirroring" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" - -[[package]] -name = "unicode-ccc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-linebreak" @@ -3592,44 +4618,35 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" - [[package]] name = "unicode-script" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -3639,51 +4656,100 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" dependencies = [ "base64", + "cookie_store", "flate2", "log", - "once_cell", + "percent-encoding", "rustls", "rustls-pki-types", "serde", "serde_json", - "url", + "ureq-proto", + "utf-8", "webpki-roots", ] [[package]] -name = "url" -version = "2.5.2" +name = "ureq-proto" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] -name = "urlencoding" -version = "2.1.3" +name = "utf-8" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] [[package]] name = "value-bag" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vswhom" @@ -3697,9 +4763,9 @@ dependencies = [ [[package]] name = "vswhom-sys" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" dependencies = [ "cc", "libc", @@ -3717,52 +4783,60 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasm-bindgen" -version = "0.2.92" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "cfg-if", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "bumpalo", - "log", + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.70", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3770,47 +4844,83 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.70", - "wasm-bindgen-backend", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] [[package]] -name = "wasm-timer" -version = "0.2.5" +name = "wasm-encoder" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" dependencies = [ "futures", "js-sys", - "parking_lot 0.11.2", + "parking_lot", "pin-utils", + "slab", "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", ] [[package]] name = "wayland-backend" -version = "0.3.5" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269c04f203640d0da2092d1b8d89a2d081714ae3ac2f1b53e99f205740517198" +checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 1.1.3", "scoped-tls", "smallvec", "wayland-sys", @@ -3818,12 +4928,12 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.4" +version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bd0f46c069d3382a36c8666c1b9ccef32b8b04f41667ca1fef06a1adcc2982" +checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" dependencies = [ - "bitflags 2.6.0", - "rustix", + "bitflags 2.10.0", + "rustix 1.1.3", "wayland-backend", "wayland-scanner", ] @@ -3834,41 +4944,67 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.4" +version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09414bcf0fd8d9577d73e9ac4659ebc45bcc9cff1980a350543ad8e50ee263b2" +checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" dependencies = [ - "rustix", + "rustix 1.1.3", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-scanner", ] [[package]] -name = "wayland-protocols-plasma" -version = "0.2.0" +name = "wayland-protocols-experimental" +version = "20250721.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791c58fdeec5406aa37169dd815327d1e47f334219b523444bc26d70ceb4c34e" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +dependencies = [ + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -3877,11 +5013,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -3890,9 +5026,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.3" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", "quick-xml", @@ -3901,9 +5037,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.3" +version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6754825230fa5b27bafaa28c30b3c9e72c55530581220cef401fa422c0fae7" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" dependencies = [ "dlib", "log", @@ -3913,9 +5049,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -3923,9 +5059,9 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -3933,32 +5069,36 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wgpu" -version = "0.19.4" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd7311dbd2abcfebaabf1841a2824ed7c8be443a0f29166e5d3c6a53a762c01" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", + "bitflags 2.10.0", "cfg-if", - "cfg_aliases 0.1.1", + "cfg_aliases 0.2.1", + "document-features", + "hashbrown 0.16.1", "js-sys", "log", "naga", - "parking_lot 0.12.3", + "parking_lot", + "portable-atomic", "profiling", "raw-window-handle", "smallvec", @@ -3973,92 +5113,126 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.19.4" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" dependencies = [ "arrayvec", + "bit-set", "bit-vec", - "bitflags 2.6.0", - "cfg_aliases 0.1.1", - "codespan-reporting", + "bitflags 2.10.0", + "bytemuck", + "cfg_aliases 0.2.1", + "document-features", + "hashbrown 0.16.1", "indexmap", "log", "naga", "once_cell", - "parking_lot 0.12.3", + "parking_lot", + "portable-atomic", "profiling", "raw-window-handle", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", - "thiserror", - "web-sys", + "thiserror 2.0.18", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-types", ] [[package]] -name = "wgpu-hal" -version = "0.19.4" +name = "wgpu-core-deps-apple" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1a4924366df7ab41a5d8546d6534f1f33231aa5b3f72b9930e300f254e39c3" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "27.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" dependencies = [ "android_system_properties", "arrayvec", "ash", "bit-set", - "bitflags 2.6.0", + "bitflags 2.10.0", "block", - "cfg_aliases 0.1.1", - "core-graphics-types", - "d3d12", + "bytemuck", + "cfg-if", + "cfg_aliases 0.2.1", + "core-graphics-types 0.2.0", "glow", "glutin_wgl_sys", "gpu-alloc", "gpu-allocator", "gpu-descriptor", - "hassle-rs", + "hashbrown 0.16.1", "js-sys", "khronos-egl", "libc", - "libloading 0.8.4", + "libloading", "log", "metal", "naga", "ndk-sys", "objc", "once_cell", - "parking_lot 0.12.3", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", "profiling", "range-alloc", "raw-window-handle", "renderdoc-sys", - "rustc-hash", "smallvec", - "thiserror", + "thiserror 2.0.18", "wasm-bindgen", "web-sys", "wgpu-types", - "winapi", + "windows 0.58.0", + "windows-core 0.58.0", ] [[package]] name = "wgpu-types" -version = "0.19.2" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", + "bytemuck", "js-sys", + "log", + "thiserror 2.0.18", "web-sys", ] -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - [[package]] name = "win32console" version = "0.1.5" @@ -4086,11 +5260,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4101,37 +5275,183 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window_clipboard" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d692d46038c433f9daee7ad8757e002a4248c20b0a3fbc991d99521d3bcb6d" +checksum = "d5654226305eaf2dde8853fb482861d28e5dcecbbd40cb88e8393d94bb80d733" dependencies = [ "clipboard-win", "clipboard_macos", "clipboard_wayland", "clipboard_x11", "raw-window-handle", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "windows" -version = "0.52.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core", + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] [[package]] name = "windows-core" -version = "0.52.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -4168,6 +5488,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4214,6 +5543,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -4348,37 +5686,41 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.29.15" +version = "0.30.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.6.0", + "bitflags 2.10.0", + "block2 0.5.1", "bytemuck", - "calloop", - "cfg_aliases 0.1.1", - "core-foundation", + "calloop 0.13.0", + "cfg_aliases 0.2.1", + "concurrent-queue", + "core-foundation 0.9.4", "core-graphics", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", - "memmap2 0.9.4", + "memmap2", "ndk", - "ndk-sys", - "objc2 0.4.1", - "once_cell", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", "orbclient", "percent-encoding", + "pin-project", "raw-window-handle", - "redox_syscall 0.3.5", - "rustix", + "redox_syscall 0.4.1", + "rustix 0.38.44", "sctk-adwaita", - "smithay-client-toolkit", + "smithay-client-toolkit 0.19.2", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -4388,7 +5730,7 @@ dependencies = [ "wayland-protocols-plasma", "web-sys", "web-time", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", @@ -4396,18 +5738,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.40" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] @@ -4422,6 +5755,110 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.10.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + [[package]] name = "x11-dl" version = "2.21.0" @@ -4435,51 +5872,40 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.4", + "libloading", "once_cell", - "rustix", + "rustix 1.1.3", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xattr" -version = "1.3.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "linux-raw-sys 0.4.14", - "rustix", + "rustix 1.1.3", ] [[package]] name = "xcursor" -version = "0.3.5" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" - -[[package]] -name = "xdg-home" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" [[package]] name = "xkbcommon-dl" @@ -4487,7 +5913,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "dlib", "log", "once_cell", @@ -4502,31 +5928,53 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.20" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] -name = "xxhash-rust" -version = "0.8.11" +name = "y4m" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63658493314859b4dfdf3fb8c1defd61587839def09582db50b8a4e93afca6bb" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" [[package]] name = "yazi" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[package]] name = "zbus" -version = "4.3.1" +version = "5.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "851238c133804e0aa888edf4a0229481c753544ca12a60fd1c3230c8a500fe40" +checksum = "1bfeff997a0aaa3eb20c4652baf788d2dfa6d2839a0ead0b3ff69ce2f9c4bdd1" dependencies = [ "async-broadcast", "async-executor", - "async-fs", "async-io", "async-lock", "async-process", @@ -4535,145 +5983,154 @@ dependencies = [ "async-trait", "blocking", "enumflags2", - "event-listener 5.3.1", + "event-listener 5.4.1", "futures-core", - "futures-sink", - "futures-util", + "futures-lite", "hex", - "nix", + "libc", "ordered-stream", - "rand", + "rustix 1.1.3", "serde", "serde_repr", - "sha1", - "static_assertions", "tracing", "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros 4.3.1", - "zbus_names 3.0.0", - "zvariant 4.1.2", -] - -[[package]] -name = "zbus" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb67eadba43784b6fb14857eba0d8fc518686d3ee537066eb6086dc318e2c8a1" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener 5.3.1", - "futures-core", - "futures-util", - "hex", - "nix", - "ordered-stream", - "serde", - "serde_repr", - "static_assertions", - "tracing", - "uds_windows", - "windows-sys 0.59.0", - "winnow 0.6.22", - "xdg-home", - "zbus_macros 5.2.0", - "zbus_names 4.1.0", - "zvariant 5.1.0", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", ] [[package]] name = "zbus_macros" +version = "5.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bbd5a90dbe8feee5b13def448427ae314ccd26a49cac47905cafefb9ff846f1" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5a3f12c20bd473be3194af6b49d50d7bb804ef3192dc70eddedb26b85d9da7" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.70", - "zvariant_utils 2.0.0", -] - -[[package]] -name = "zbus_macros" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d49ebc960ceb660f2abe40a5904da975de6986f2af0d7884b39eec6528c57" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.70", - "zbus_names 4.1.0", - "zvariant 5.1.0", - "zvariant_utils 3.0.2", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", - "static_assertions", - "zvariant 4.1.2", -] - -[[package]] -name = "zbus_names" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" -dependencies = [ - "serde", - "static_assertions", - "winnow 0.6.22", - "zvariant 5.1.0", + "winnow", + "zvariant", ] [[package]] name = "zeno" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-inflate" @@ -4685,82 +6142,60 @@ dependencies = [ ] [[package]] -name = "zvariant" -version = "4.1.2" +name = "zune-jpeg" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1724a2b330760dc7d2a8402d841119dc869ef120b139d29862d6980e9c75bfc9" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "zvariant_derive 4.1.2", + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410e9ecef634c709e3831c2cfdb8d9c32164fae1c67496d5b68fff728eec37fe" +dependencies = [ + "zune-core 0.5.1", ] [[package]] name = "zvariant" -version = "5.1.0" +version = "5.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" +checksum = "68b64ef4f40c7951337ddc7023dd03528a57a3ce3408ee9da5e948bd29b232c4" dependencies = [ "endi", "enumflags2", "serde", - "static_assertions", "url", - "winnow 0.6.22", - "zvariant_derive 5.1.0", - "zvariant_utils 3.0.2", + "winnow", + "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.1.2" +version = "5.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55025a7a518ad14518fb243559c058a2e5b848b015e31f1d90414f36e3317859" +checksum = "484d5d975eb7afb52cc6b929c13d3719a20ad650fea4120e6310de3fc55e415c" dependencies = [ - "proc-macro-crate 3.2.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.70", - "zvariant_utils 2.0.0", -] - -[[package]] -name = "zvariant_derive" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.70", - "zvariant_utils 3.0.2", + "syn", + "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "2.0.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.70", -] - -[[package]] -name = "zvariant_utils" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" dependencies = [ "proc-macro2", "quote", "serde", - "static_assertions", - "syn 2.0.70", - "winnow 0.6.22", + "syn", + "winnow", ] diff --git a/Cargo.toml b/Cargo.toml index 82d3b67..0464938 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,13 @@ -[package] -name = "uad-ng" -description = "A cross-platform GUI debloater for android devices" -version = "1.1.2" +[workspace] +members = [ + "crates/uad-core", + "crates/uad-gui", + "crates/uad-cli" +] +resolver = "2" + +[workspace.package] +version = "1.2.0" authors = ["Universal-Debloater-Alliance"] license = "GPL-3.0" homepage = "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation" @@ -11,66 +17,47 @@ keywords = ["debloater", "android", "adb", "privacy", "bloatware"] categories = ["gui"] edition = "2024" -[features] -default = ["wgpu", "self-update"] -wgpu = [] # Iced/wgpu is default -self-update = ["flate2", "tar"] -no-self-update = [] - -[dependencies] -dark-light = "2" +[workspace.dependencies] +# Core dependencies serde = { version = "^1.0", features = ["derive"] } serde_json = "^1.0" -fern = { version = "^0", features = ["colored"] } -chrono = { version = "^0.4", default-features = false, features = [ - "std", - "clock", -] } log = "^0.4" -regex = "^1.10.2" +chrono = { version = "^0.4", default-features = false, features = ["std", "clock"] } toml = "^0" -dirs = "^5.0.0" -ureq = { version = "*", features = ["json"] } +dirs = "^6" +ureq = { version = "3", features = ["json"] } retry = "^2.0.0" -iced = { version = "^0.12.0", features = ["advanced", "image"] } -rfd = "^0.14" csv = "^1.3" -[target.'cfg(not(target_os = "windows"))'.dependencies] -flate2 = { version = "^1", optional = true } -tar = { version = "^0.4", optional = true } +# GUI dependencies +iced = { version = "=0.14.0", features = ["advanced"] } +image = "0.25" +rfd = "^0.17.1" +dark-light = "2" +fern = { version = "^0", features = ["colored"] } -[target.'cfg(target_os = "windows")'.dependencies] +# CLI dependencies +clap = { version = "4.6.1", features = ["derive"] } +tokio = { version = "1.52.3", features = ["full"] } + +# Platform-specific dependencies +flate2 = "^1" +tar = "^0.4" win32console = "^0.1.5" -[profile.release] -opt-level = "s" -codegen-units = 1 -lto = true -strip = true -panic = "abort" - -[build-dependencies] -embed-resource = "2.4.2" - -[lints.rust] +[workspace.lints.rust] deprecated_safe = "warn" -[lints.clippy] +[workspace.lints.clippy] undocumented_unsafe_blocks = "forbid" -exit = "deny" panic_in_result_fn = "warn" infinite_loop = "warn" -mem_forget = "warn" -string_to_string = "warn" format_push_string = "warn" large_include_file = "warn" shadow_unrelated = "warn" struct_field_names = "allow" # annoying -module_name_repetitions = "allow" # annoying disallowed_types = "deny" disallowed_methods = "deny" -allow_attributes_without_reason = "warn" -pedantic = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } \ No newline at end of file diff --git a/README.md b/README.md index 5fc614f..6e0f111 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,53 @@ # Universal Android Debloater Next Generation > [!warning] -> **DISCLAIMER**: Use at your own risk. We're not responsible for anything that -could happen to your devices. +> **DISCLAIMER**: Use at your own risk. We're not responsible for anything that could happen to your devices. -uad_screenshot +
+screenshot of apps view +
-**Check out the issues, and [feel free to contribute!](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute)**. We're in **HIGH NEED** of [Rust](https://www.rust-lang.org) developers for fixing critical issues, see [this announcement](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/discussions/731) for more information. - -**For real-time communication, consider joining our Discord server:** - - - Icon - - -**In case you prefer using Matrix (using a Matrix bridge to Discord):** - -[](https://matrix.to/#/#uad-ng:matrix.org) - -## Summary - -This is a detached fork of the [UAD project](https://github.com/0x192/universal-android-debloater), which aims to improve privacy and battery performance by removing unnecessary and obscure system apps. -This can also contribute to improving security by reducing (but not eliminating) [the attack surface](https://en.wikipedia.org/wiki/Attack_surface). Read the [wiki](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki) for more details on getting started. Whilst UAD-ng can remove system apps, it cannot detect or remove potentially malicious system services or drivers baked into the firmware of your device by various vendors; some vendor-specific apps are only UI front-ends to vendor-provided system services, and as such disabling/uninstalling those apps will not stop a service from running. Additional information can be found in package descriptions inside the Universal Android Debloater Next Generation application. +This is a detached fork of the [UAD project](https://github.com/0x192/universal-android-debloater). This aims to improve privacy and efficiency (energy, speed, memory) by removing unnecessary and obscure system apps. +This can also improve security by reducing the [attack surface](https://en.wikipedia.org/wiki/Attack_surface). Read [the wiki](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki) for more details. ## Documentation -For documentation regarding how to use UAD-ng, the FAQ, building from source and how to decompile/extract APKs, see [our Wiki](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki). +Everything about UAD-ng (and related stuff) can be found on the Wiki, such as: + +- [Getting started](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Getting-started) +- Features of this app +- [Usage guide](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Usage) +- Suggested Android app replacements +- How to get the cutting-edge version by [building the source-code](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Building-from-source) +- Weird things OEMs do +- [Suggested apps for analyzing APKs](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/How-to-contribute#useful-apps) + +## Privacy + +UAD-ng does not collect or transmit any user data. The only external connections are `GET` requests to GitHub for fetching the [package list](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/resources/assets/uad_lists.json) ([src/core/uad_lists.rs](src/core/uad_lists.rs)) and checking for updates ([src/core/update.rs](src/core/update.rs)). + +## Contact + +**For real-time communication and support, consider joining our Discord guild:** + +[Discord symbol](https://discord.gg/CzwbMCPEZa) + +**If you prefer using Matrix, we have a bridge to Discord:** + +[](https://matrix.to/#/#uad-ng:matrix.org) + +## Friends + +Several projects integrate with or depend on UAD-ng's data and tools: + +- **[Canta](https://github.com/samolego/Canta)** — A mobile Android debloater that uses Shizuku for rootless privilege escalation. It integrates with UAD-ng's Universal Debloat List to provide safe package recommendations without requiring a PC. + +- **Projects by [Muntashir Akon](https://github.com/MuntashirAkon):** + - **[AppManager](https://github.com/MuntashirAkon/AppManager)** — An advanced Android app manager with powerful debloating features. + - **[android-debloat-list](https://github.com/MuntashirAkon/android-debloat-list)** — A comprehensive, community-driven list of Android packages to debloat, based on UAD-ng's list. ## Special thanks - [@0x192](https://github.com/0x192) who created the original UAD project. -- [@mawilms](https://github.com/mawilms) for his LotRO plugin manager ([Lembas](https://github.com/mawilms/lembas)) which helped a lot to understand how to use the [Iced](https://github.com/hecrj/iced) GUI library. +- [@mawilms](https://github.com/mawilms) for his LotRO plugin manager ([Lembas](https://github.com/mawilms/lembas)) which helped a lot to understand how to use the [Iced](https://github.com/iced-rs/iced) GUI library. - [@casperstorm](https://github.com/casperstorm) for the UI/UX inspiration. diff --git a/build.rs b/build.rs index cc564fe..e2bbb62 100644 --- a/build.rs +++ b/build.rs @@ -1,9 +1,11 @@ -use std::{env, error::Error}; +const META: &str = "resources/assets/manifest.rc"; -fn main() -> Result<(), Box> { - if env::var("CARGO_CFG_TARGET_FAMILY")? == "windows" { - embed_resource::compile("resources/assets/manifest.rc", embed_resource::NONE); +fn main() -> Result<(), Box> { + println!("cargo::rerun-if-changed={META}"); + if std::env::var("CARGO_CFG_TARGET_FAMILY")? == "windows" { + embed_resource::compile(META, embed_resource::NONE) + .manifest_optional() + .unwrap(); } - Ok(()) } diff --git a/crates/uad-cli/Cargo.toml b/crates/uad-cli/Cargo.toml new file mode 100644 index 0000000..6045f95 --- /dev/null +++ b/crates/uad-cli/Cargo.toml @@ -0,0 +1,52 @@ +[package] +name = "uad-cli" +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +keywords.workspace = true +categories = ["command-line-utilities"] +edition.workspace = true + +[[bin]] +name = "uad" +path = "src/main.rs" + +[dependencies] +uad-core = { path = "../uad-core" } +clap.workspace = true +clap_complete = "4.4" +tokio.workspace = true +serde.workspace = true +serde_json.workspace = true +log.workspace = true +chrono.workspace = true +toml.workspace = true +dirs.workspace = true +ureq.workspace = true +retry.workspace = true +csv.workspace = true +rustyline = "14.0" + +[lints.rust] +deprecated_safe = "warn" + +[lints.clippy] +undocumented_unsafe_blocks = "deny" +exit = "deny" +panic_in_result_fn = "warn" +infinite_loop = "warn" +mem_forget = "warn" +implicit_clone = "warn" +format_push_string = "warn" +large_include_file = "warn" +shadow_unrelated = "warn" +struct_field_names = "allow" # annoying + +disallowed_types = "deny" +disallowed_methods = "deny" + +allow_attributes_without_reason = "warn" +pedantic = { level = "warn", priority = -1 } diff --git a/crates/uad-cli/examples/usage.sh b/crates/uad-cli/examples/usage.sh new file mode 100755 index 0000000..ab3192e --- /dev/null +++ b/crates/uad-cli/examples/usage.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Example usage script for UAD CLI + +# Check if uad-cli is available +if ! command -v uad &> /dev/null; then + echo "uad command not found. Please build and install uad-cli first." + exit 1 +fi + +echo "=== UAD CLI Usage Examples ===" +echo + +echo "1. List connected devices:" +uad devices +echo + +echo "2. List all enabled packages:" +uad list --state enabled | head -20 +echo "... (showing first 20)" +echo + +echo "3. Search for Google packages:" +uad list --search google | head -10 +echo "... (showing first 10)" +echo + +echo "4. Show info about a package (example):" +echo "uad info com.google.android.gms" +echo + +echo "5. Dry-run uninstall (safe to test):" +echo "uad uninstall com.example.package --dry-run" +echo + +echo "6. Start interactive mode:" +echo "uad repl" +echo + +echo "=== Generate shell completions ===" +echo "For bash: uad completions bash > ~/.local/share/bash-completion/completions/uad" +echo "For zsh: uad completions zsh > ~/.local/share/zsh/site-functions/_uad" +echo "For fish: uad completions fish > ~/.config/fish/completions/uad.fish" + diff --git a/crates/uad-cli/src/commands.rs b/crates/uad-cli/src/commands.rs new file mode 100644 index 0000000..62286bd --- /dev/null +++ b/crates/uad-cli/src/commands.rs @@ -0,0 +1,470 @@ +use clap::CommandFactory; +use clap_complete::{Shell, generate}; +use std::collections::{HashMap, HashSet}; +use std::io::Write; +use uad_core::adb::{ACommand, PmListPacksFlag}; +use uad_core::sync::{ + CorePackage, Phone, User, apply_pkg_state_commands, get_devices_list, get_package_state, + run_adb_shell_action, +}; +use uad_core::uad_lists::{Package, PackageState, Removal, UadList, load_debloat_lists}; +use uad_core::utils::{matches_search, truncate_description}; + +use crate::device::{NO_DEVICES_FOUND, get_target_device, get_user}; +use crate::filters::{ListFilter, RemovalFilter, StateFilter}; +use crate::{Cli, print_or_exit, println_or_exit}; + +/// List all connected Android devices +pub fn list_devices() -> Result<(), Box> { + println_or_exit!("Scanning for connected devices..."); + let devices = get_devices_list(); + + if devices.is_empty() { + return Err(NO_DEVICES_FOUND.into()); + } + + println_or_exit!("\nFound {} device(s):\n", devices.len()); + for device in &devices { + println_or_exit!(" Model: {}", device.model); + println_or_exit!(" Serial: {}", device.adb_id); + println_or_exit!(" Android SDK: {}", device.android_sdk); + + if !device.user_list.is_empty() { + println_or_exit!(" Users: {} user(s)", device.user_list.len()); + for user in &device.user_list { + let protected = if user.protected { " (protected)" } else { "" }; + println_or_exit!(" - User ID: {}{}", user.id, protected); + } + } + println_or_exit!(); + } + + Ok(()) +} + +/// Context for package filtering and display +pub struct PackageListContext { + pub state_filter: Option, + pub removal_filter: Option, + pub list_filter: Option, + pub search: Option, +} + +impl PackageListContext { + /// Check if package passes all filters + pub fn filter_package( + &self, + pkg_name: &str, + pkg_info: Option<&Package>, + pkg_state: PackageState, + ) -> bool { + // Removal filter + if let Some(removal) = self.removal_filter { + if !removal.matches(pkg_info) { + return false; + } + } + + // State filter + if let Some(state) = self.state_filter { + if !state.matches(pkg_state) { + return false; + } + } + + // List filter + if let Some(list) = self.list_filter { + if !list.matches(pkg_info) { + return false; + } + } + + // Search filter + if let Some(ref search_term) = self.search { + let description = pkg_info.map(|p| p.description.as_str()); + if !matches_search(pkg_name, search_term, description) { + return false; + } + } + + true + } + + /// Determine what information to show based on active filters + pub fn display_config(&self) -> DisplayConfig { + DisplayConfig { + show_state: self.state_filter.is_none_or(|f| !f.is_specific()), + show_removal: self.removal_filter.is_none_or(|f| !f.is_specific()), + } + } +} + +pub struct DisplayConfig { + pub show_state: bool, + pub show_removal: bool, +} + +/// List packages on a device with filtering +pub fn list_packages( + device: Option, + state_filter: Option, + removal_filter: Option, + list_filter: Option, + search: Option, + user_id: Option, +) -> Result<(), Box> { + let target_device = get_target_device(device)?; + let uad_lists = load_debloat_lists(false).unwrap_or_else(|lists| lists); + + println_or_exit!( + "Listing packages on: {} ({})\n", + target_device.model, + target_device.adb_id + ); + + let context = PackageListContext { + state_filter, + removal_filter, + list_filter, + search, + }; + + let pm_flag = state_filter.and_then(StateFilter::to_pm_flag); + let system_packages = ACommand::new() + .shell(&target_device.adb_id) + .pm() + .list_packages_sys(pm_flag, user_id)?; + + let displayed_count = display_package_list( + &system_packages, + &uad_lists, + &target_device.adb_id, + user_id, + &context, + )?; + + if displayed_count == 0 { + println_or_exit!(" No packages found matching the specified filters."); + } else { + println_or_exit!("\nTotal: {} package(s)", displayed_count); + } + + Ok(()) +} + +/// Display a list of packages with their info +pub fn display_package_list( + packages: &[String], + uad_lists: &HashMap, + device_serial: &str, + user_id: Option, + context: &PackageListContext, +) -> Result> { + let config = context.display_config(); + let mut displayed_count = 0; + + let enabled_packages: HashSet = ACommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(Some(PmListPacksFlag::OnlyEnabled), user_id) + .unwrap_or_default() + .into_iter() + .collect(); + let disabled_packages: HashSet = ACommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(Some(PmListPacksFlag::OnlyDisabled), user_id) + .unwrap_or_default() + .into_iter() + .collect(); + + for pkg_name in packages { + let pkg_info = uad_lists.get(pkg_name); + + let pkg_state = if enabled_packages.contains(pkg_name) { + PackageState::Enabled + } else if disabled_packages.contains(pkg_name) { + PackageState::Disabled + } else { + PackageState::Uninstalled + }; + + if !context.filter_package(pkg_name, pkg_info, pkg_state) { + continue; + } + + display_package_entry(pkg_name, pkg_info, pkg_state, &config); + displayed_count += 1; + } + + Ok(displayed_count) +} + +/// Display a single package entry +pub fn display_package_entry( + pkg_name: &str, + pkg_info: Option<&Package>, + pkg_state: PackageState, + config: &DisplayConfig, +) { + print_or_exit!("["); + + if let Some(info) = pkg_info { + if config.show_removal { + print_or_exit!("{}", info.removal); + if config.show_state { + print_or_exit!(" - "); + } + } + if config.show_state { + print_or_exit!("{}", pkg_state); + } + print_or_exit!("] {}", pkg_name); + if !info.description.is_empty() { + print_or_exit!(" - {}", truncate_description(&info.description, 80)); + } + } else { + if config.show_removal { + print_or_exit!("Unlisted"); + if config.show_state { + print_or_exit!(" - "); + } + } + if config.show_state { + print_or_exit!("{}", pkg_state); + } + print_or_exit!("] {}", pkg_name); + } + + println_or_exit!(); +} + +/// Change the state of one or more packages +pub fn change_package_state( + packages: &[String], + device: Option, + user_id: Option, + dry_run: bool, + target_state: PackageState, + action_name: &str, +) -> Result<(), Box> { + if packages.is_empty() { + return Err("No packages specified".into()); + } + + let target_device = get_target_device(device)?; + let user = get_user(&target_device, user_id)?; + let uad_lists = load_debloat_lists(false).unwrap_or_else(|lists| lists); + + println!( + "{} {} package(s) on: {} ({})\n", + action_name, + packages.len(), + target_device.model, + target_device.adb_id + ); + + if dry_run { + println!("DRY RUN - No changes will be made\n"); + } + + for pkg_name in packages { + process_package_state_change( + pkg_name, + &target_device, + user, + target_state, + dry_run, + &uad_lists, + )?; + println!(); + } + + if dry_run { + println!("Dry run completed. No changes were made."); + } else { + println!("Operation completed successfully."); + } + + Ok(()) +} + +/// Process state change for a single package +fn process_package_state_change( + pkg_name: &str, + device: &Phone, + user: User, + target_state: PackageState, + dry_run: bool, + uad_lists: &HashMap, +) -> Result<(), Box> { + let current_state = get_package_state(&device.adb_id, pkg_name, Some(user.id)) + .ok_or("Package not found on device")?; + + println!(" {} ({})", pkg_name, current_state); + + if current_state == target_state { + println!(" → Already in target state, skipping"); + return Ok(()); + } + + let pkg_info = uad_lists.get(pkg_name); + if let Some(info) = pkg_info { + if info.removal == Removal::Unsafe { + println!(" ⚠ WARNING: This package is marked as UNSAFE to remove!"); + } + } + + let core_pkg = CorePackage { + name: pkg_name.to_string(), + description: pkg_info.map(|p| p.description.clone()).unwrap_or_default(), + removal: pkg_info.map(|p| p.removal).unwrap_or(Removal::Unlisted), + state: current_state, + list: pkg_info.map(|p| p.list).unwrap_or(UadList::Unlisted), + }; + + let commands = apply_pkg_state_commands(&core_pkg, target_state, user, device); + + if dry_run { + for cmd in &commands { + println!(" Would run: {}", cmd); + } + } else { + execute_with_fallback( + pkg_name, + target_state, + &core_pkg, + user, + device, + &commands, + " ", + )?; + } + + Ok(()) +} + +/// Execute commands and verify package state with fallback +pub fn execute_with_fallback( + package: &str, + target_state: PackageState, + core_pkg: &CorePackage, + user: User, + device: &Phone, + commands: &[String], + indent: &str, +) -> Result<(), Box> { + // Capture the before-state of packages on other users for cross-user detection + let before_cross_user_states = + uad_core::sync::capture_cross_user_states(package, &device.adb_id, user.id, device); + + // Execute commands + for cmd in commands { + match run_adb_shell_action(&device.adb_id, cmd.as_str()) { + Ok(_) => println!("{}✓ {}", indent, cmd), + Err(e) => { + return Err(format!("{indent}✗ Failed to execute `{cmd}`: {e:?}").into()); + } + } + } + + // Verify package state and attempt fallback if needed + let actual_state = match get_package_state(&device.adb_id, package, Some(user.id)) { + Some(state) => state, + None if target_state == PackageState::Uninstalled => PackageState::Uninstalled, + None => { + return Err(format!( + "Package '{package}' was not found on device for user {}", + user.id + ) + .into()); + } + }; + + if actual_state != target_state { + println!( + "{}⚠ Package state verification failed: expected {:?}, got {:?}", + indent, target_state, actual_state + ); + + // Attempt fallback + if let Ok(fallback_action) = + uad_core::sync::attempt_fallback(core_pkg, target_state, actual_state, user, device) + { + println!("{}↻ Fallback: {}", indent, fallback_action); + } else { + println!("{}✗ No fallback available", indent); + } + } + + // Check for cross-user behavior if operation succeeded + if actual_state == target_state { + if let Some(notification) = uad_core::sync::detect_cross_user_behavior( + package, + device.adb_id.as_str(), + user.id, + target_state, + actual_state, + device, + &before_cross_user_states, + ) { + println!("{}ℹ {}", indent, notification); + } + } + + Ok(()) +} + +/// Show detailed information about a package +pub fn show_package_info( + package: &str, + device: Option, + user_id: Option, +) -> Result<(), Box> { + println!("Package: {}\n", package); + + let uad_lists = load_debloat_lists(false).unwrap_or_else(|lists| lists); + + if let Some(pkg_info) = uad_lists.get(package) { + println!("UAD Information:"); + println!(" List: {}", pkg_info.list); + println!(" Removal: {}", pkg_info.removal); + println!(" Description: {}", pkg_info.description); + println!(); + } else { + println!(" Not found in UAD lists (unlisted package)\n"); + } + + if let Some(device_id) = device { + let target_device = get_target_device(Some(device_id))?; + let user = get_user(&target_device, user_id)?; + println!("Device: {} ({})", target_device.model, target_device.adb_id); + println!("User: {}", user.id); + + let state = get_package_state(&target_device.adb_id, package, Some(user.id)) + .ok_or("Package not found on device")?; + println!(" State: {}", state); + } + + Ok(()) +} + +/// Update UAD package lists from remote repository +pub fn update_lists() -> Result<(), Box> { + println!("Updating UAD package lists from remote repository..."); + + match load_debloat_lists(true) { + Ok(_lists) => { + println!("✓ Successfully updated package lists"); + Ok(()) + } + Err(_lists) => Err("Failed to update lists from remote, using cached version".into()), + } +} + +/// Generate shell completion script +pub fn generate_completions(shell: Shell) { + let mut cmd = Cli::command(); + let name = cmd.get_name().to_string(); + generate(shell, &mut cmd, name, &mut std::io::stdout()); +} diff --git a/crates/uad-cli/src/device.rs b/crates/uad-cli/src/device.rs new file mode 100644 index 0000000..54fee8c --- /dev/null +++ b/crates/uad-cli/src/device.rs @@ -0,0 +1,47 @@ +use uad_core::sync::{Phone, User, get_devices_list}; + +pub const NO_DEVICES_FOUND: &str = + "No devices found. Make sure ADB is installed and devices are connected."; + +/// Get target device, either by serial or first available +pub fn get_target_device(device: Option) -> Result> { + let devices = get_devices_list(); + + if devices.is_empty() { + return Err(NO_DEVICES_FOUND.into()); + } + + let target_device = if let Some(device_id) = device { + devices + .iter() + .find(|d| d.adb_id == device_id) + .ok_or("Device not found")? + .clone() + } else { + if devices.len() > 1 { + eprintln!( + "Warning: Multiple devices found, using first one: {}", + devices[0].adb_id + ); + } + devices[0].clone() + }; + + Ok(target_device) +} + +/// Get user from device, creating a basic one if not found +pub fn get_user(device: &Phone, user_id: Option) -> Result> { + let uid = user_id.unwrap_or(0); + + if let Some(user) = device.user_list.iter().find(|u| u.id == uid) { + Ok(*user) + } else { + // Create a basic user if not found in list + Ok(User { + id: uid, + index: 0, + protected: false, + }) + } +} diff --git a/crates/uad-cli/src/filters.rs b/crates/uad-cli/src/filters.rs new file mode 100644 index 0000000..5ae156f --- /dev/null +++ b/crates/uad-cli/src/filters.rs @@ -0,0 +1,98 @@ +use clap::ValueEnum; +use uad_core::adb::PmListPacksFlag; +use uad_core::uad_lists::{Package, PackageState, Removal, UadList}; + +#[derive(Debug, Clone, Copy, ValueEnum)] +pub enum StateFilter { + /// Show all packages regardless of state + All, + /// Show only enabled packages + Enabled, + /// Show only disabled packages + Disabled, + /// Show only uninstalled packages + Uninstalled, +} + +#[derive(Debug, Clone, Copy, ValueEnum)] +pub enum RemovalFilter { + All, + Recommended, + Advanced, + Expert, + Unsafe, + Unlisted, +} + +#[derive(Debug, Clone, Copy, ValueEnum)] +pub enum ListFilter { + All, + Aosp, + Carrier, + Google, + Misc, + Oem, + Pending, + Unlisted, +} + +impl StateFilter { + pub fn to_pm_flag(self) -> Option { + match self { + Self::Enabled => Some(PmListPacksFlag::OnlyEnabled), + Self::Disabled => Some(PmListPacksFlag::OnlyDisabled), + Self::Uninstalled | Self::All => Some(PmListPacksFlag::IncludeUninstalled), + } + } + + pub fn matches(self, pkg_state: PackageState) -> bool { + match self { + Self::All => true, + Self::Enabled => pkg_state == PackageState::Enabled, + Self::Disabled => pkg_state == PackageState::Disabled, + Self::Uninstalled => pkg_state == PackageState::Uninstalled, + } + } + + pub fn is_specific(self) -> bool { + matches!(self, Self::Enabled | Self::Disabled | Self::Uninstalled) + } +} + +impl RemovalFilter { + pub fn matches(self, pkg_info: Option<&Package>) -> bool { + match pkg_info { + Some(info) => match self { + Self::All => true, + Self::Recommended => info.removal == Removal::Recommended, + Self::Advanced => info.removal == Removal::Advanced, + Self::Expert => info.removal == Removal::Expert, + Self::Unsafe => info.removal == Removal::Unsafe, + Self::Unlisted => info.removal == Removal::Unlisted, + }, + None => matches!(self, Self::All | Self::Unlisted), + } + } + + pub fn is_specific(self) -> bool { + !matches!(self, Self::All) + } +} + +impl ListFilter { + pub fn matches(self, pkg_info: Option<&Package>) -> bool { + match pkg_info { + Some(info) => match self { + Self::All => true, + Self::Aosp => info.list == UadList::Aosp, + Self::Carrier => info.list == UadList::Carrier, + Self::Google => info.list == UadList::Google, + Self::Misc => info.list == UadList::Misc, + Self::Oem => info.list == UadList::Oem, + Self::Pending => info.list == UadList::Pending, + Self::Unlisted => info.list == UadList::Unlisted, + }, + None => matches!(self, Self::All | Self::Unlisted), + } + } +} diff --git a/crates/uad-cli/src/main.rs b/crates/uad-cli/src/main.rs new file mode 100644 index 0000000..f473e28 --- /dev/null +++ b/crates/uad-cli/src/main.rs @@ -0,0 +1,251 @@ +#![allow( + clippy::needless_continue, + clippy::collapsible_if, + clippy::uninlined_format_args, + clippy::map_unwrap_or, + clippy::unnecessary_wraps, + reason = "Suppress non-critical pedantic/style lints to keep build green" +)] + +use clap::{Parser, Subcommand}; +use clap_complete::Shell; +use std::process::ExitCode; +use uad_core::uad_lists::PackageState; + +mod commands; +mod device; +mod filters; +mod output; +mod repl; + +use filters::{ListFilter, RemovalFilter, StateFilter}; + +#[derive(Parser)] +#[command(name = "uad")] +#[command(about = "Universal Android Debloater - Command Line Interface", long_about = None)] +#[command(version)] +#[command(propagate_version = true)] +pub struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// List connected Android devices + Devices, + + /// List packages on a device + #[command(name = "list", visible_alias = "ls")] + List { + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// Filter by package state + #[arg(short, long, value_enum)] + state: Option, + + /// Filter by removal category + #[arg(short, long, value_enum)] + removal: Option, + + /// Filter by UAD list + #[arg(short, long, value_enum)] + list: Option, + + /// Search pattern (matches package name or description) + #[arg(short = 'q', long)] + search: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + }, + + /// Uninstall packages (default removal action) + #[command(visible_alias = "rm")] + Uninstall { + /// Package names to uninstall + packages: Vec, + + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + + /// Dry run - show what would be done without actually doing it + #[arg(long)] + dry_run: bool, + }, + + /// Restore (reinstall) packages + #[command(visible_alias = "restore")] + Enable { + /// Package names to restore/enable + packages: Vec, + + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + + /// Dry run - show what would be done without actually doing it + #[arg(long)] + dry_run: bool, + }, + + /// Disable packages (keeps data but prevents execution) + Disable { + /// Package names to disable + packages: Vec, + + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + + /// Dry run - show what would be done without actually doing it + #[arg(long)] + dry_run: bool, + }, + + /// Show detailed information about a package + Info { + /// Package name + package: String, + + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + }, + + /// Update UAD package lists from remote repository + Update, + + /// Generate shell completion script + Completions { + /// Shell to generate completions for + #[arg(value_enum)] + shell: Shell, + }, + + /// Start interactive REPL mode + #[command(visible_alias = "shell")] + Repl { + /// Device serial number (optional, uses first device if not specified) + #[arg(short, long)] + device: Option, + + /// User ID (defaults to 0) + #[arg(short, long)] + user: Option, + }, +} + +#[tokio::main] +async fn main() -> ExitCode { + match run() { + Ok(()) => ExitCode::SUCCESS, + Err(err) => { + eprintln!("Error: {err}"); + ExitCode::FAILURE + } + } +} + +fn run() -> Result<(), Box> { + let cli = Cli::parse(); + + match cli.command { + Commands::Devices => { + commands::list_devices()?; + } + Commands::List { + device, + state, + removal, + list, + search, + user, + } => { + commands::list_packages(device, state, removal, list, search, user)?; + } + Commands::Uninstall { + packages, + device, + user, + dry_run, + } => { + commands::change_package_state( + &packages, + device, + user, + dry_run, + PackageState::Uninstalled, + "Uninstalling", + )?; + } + Commands::Enable { + packages, + device, + user, + dry_run, + } => { + commands::change_package_state( + &packages, + device, + user, + dry_run, + PackageState::Enabled, + "Enabling", + )?; + } + Commands::Disable { + packages, + device, + user, + dry_run, + } => { + commands::change_package_state( + &packages, + device, + user, + dry_run, + PackageState::Disabled, + "Disabling", + )?; + } + Commands::Info { + package, + device, + user, + } => { + commands::show_package_info(&package, device, user)?; + } + Commands::Update => { + commands::update_lists()?; + } + Commands::Completions { shell } => { + commands::generate_completions(shell); + } + Commands::Repl { device, user } => { + repl::repl_mode(device, user)?; + } + } + + Ok(()) +} diff --git a/crates/uad-cli/src/output.rs b/crates/uad-cli/src/output.rs new file mode 100644 index 0000000..cff4724 --- /dev/null +++ b/crates/uad-cli/src/output.rs @@ -0,0 +1,18 @@ +/// Helper macro to handle broken pipe errors gracefully +/// When piping to commands like `head`, we want to exit cleanly when the pipe closes +#[macro_export] +macro_rules! println_or_exit { + () => { + let _ = writeln!(std::io::stdout()); + }; + ($($arg:tt)*) => { + let _ = writeln!(std::io::stdout(), $($arg)*); + }; +} + +#[macro_export] +macro_rules! print_or_exit { + ($($arg:tt)*) => { + let _ = write!(std::io::stdout(), $($arg)*); + }; +} diff --git a/crates/uad-cli/src/repl.rs b/crates/uad-cli/src/repl.rs new file mode 100644 index 0000000..eeee0c6 --- /dev/null +++ b/crates/uad-cli/src/repl.rs @@ -0,0 +1,374 @@ +use rustyline::DefaultEditor; +use rustyline::error::ReadlineError; +use std::collections::HashMap; +use std::io::Write; +use uad_core::adb::ACommand; +use uad_core::sync::{CorePackage, Phone, User, apply_pkg_state_commands, get_package_state}; +use uad_core::uad_lists::{Package, PackageState, Removal, UadList, load_debloat_lists}; + +use crate::commands::{PackageListContext, display_package_list, execute_with_fallback}; +use crate::device::{get_target_device, get_user}; +use crate::filters::StateFilter; +use crate::println_or_exit; + +enum ReplAction { + Continue, + Exit, +} + +/// Start interactive REPL mode +pub fn repl_mode( + device: Option, + user_id: Option, +) -> Result<(), Box> { + println!("Universal Android Debloater - Interactive Mode"); + println!("Type 'help' for available commands, 'exit' or 'quit' to leave\n"); + + let target_device = get_target_device(device)?; + let user = get_user(&target_device, user_id)?; + + println!( + "Connected to: {} ({})", + target_device.model, target_device.adb_id + ); + println!("User: {}\n", user.id); + + let uad_lists = load_debloat_lists(false).unwrap_or_else(|lists| lists); + let mut rl = DefaultEditor::new()?; + + // Try to load history + let history_file = dirs::cache_dir().map(|d| d.join("uad").join("cli_history.txt")); + if let Some(ref path) = history_file { + let _ = rl.load_history(path); + } + + loop { + let readline = rl.readline("uad> "); + match readline { + Ok(line) => { + match handle_repl_line(&line, &mut rl, &target_device, user, user_id, &uad_lists) { + Ok(ReplAction::Continue) => {} + Ok(ReplAction::Exit) => break, + Err(e) => { + eprintln!("Error: {}", e); + } + } + } + Err(ReadlineError::Interrupted) => { + println!("Interrupted (Ctrl-C). Type 'exit' to quit."); + continue; + } + Err(ReadlineError::Eof) => { + println!("Goodbye!"); + break; + } + Err(err) => { + eprintln!("Error: {:?}", err); + break; + } + } + } + + // Save history + if let Some(ref path) = history_file { + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + let _ = rl.save_history(path); + } + + Ok(()) +} + +/// Handle a single line of REPL input +fn handle_repl_line( + line: &str, + rl: &mut DefaultEditor, + device: &Phone, + user: User, + user_id: Option, + uad_lists: &HashMap, +) -> Result> { + let line = line.trim(); + if line.is_empty() { + return Ok(ReplAction::Continue); + } + + let _ = rl.add_history_entry(line); + + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.is_empty() { + return Ok(ReplAction::Continue); + } + + match parts[0] { + "help" => print_repl_help(), + "exit" | "quit" => { + println!("Goodbye!"); + return Ok(ReplAction::Exit); + } + "list" | "ls" => { + handle_list_command(&parts[1..], device, user_id, uad_lists)?; + } + "info" => { + handle_info_command(&parts[1..], device, user.id, uad_lists)?; + } + "uninstall" | "rm" => { + handle_state_change_command( + &parts[1..], + device, + user, + PackageState::Uninstalled, + "Uninstalling", + uad_lists, + )?; + } + "enable" | "restore" => { + handle_state_change_command( + &parts[1..], + device, + user, + PackageState::Enabled, + "Enabling", + uad_lists, + )?; + } + "disable" => { + handle_state_change_command( + &parts[1..], + device, + user, + PackageState::Disabled, + "Disabling", + uad_lists, + )?; + } + "device" => { + println!( + "Device: {} ({}), Android SDK: {}, User: {}", + device.model, device.adb_id, device.android_sdk, user.id + ); + } + "clear" => { + print!("\x1B[2J\x1B[1;1H"); + } + _ => { + eprintln!( + "Unknown command: '{}'. Type 'help' for available commands.", + parts[0] + ); + } + } + + Ok(ReplAction::Continue) +} + +/// Parse REPL arguments into filters +struct ReplListArgs { + state_filter: Option, + search_term: Option, +} + +impl ReplListArgs { + fn parse(args: &[&str]) -> Result { + let mut state_filter = None; + let mut search_term = None; + let mut i = 0; + + while i < args.len() { + match args[i] { + "--state" | "-s" => { + if i + 1 >= args.len() { + return Err("--state requires a value".to_string()); + } + state_filter = match args[i + 1].to_lowercase().as_str() { + "enabled" => Some(StateFilter::Enabled), + "disabled" => Some(StateFilter::Disabled), + "uninstalled" => Some(StateFilter::Uninstalled), + "all" => Some(StateFilter::All), + _ => return Err(format!("Invalid state: {}", args[i + 1])), + }; + i += 2; + } + "--search" | "-q" => { + if i + 1 >= args.len() { + return Err("--search requires a value".to_string()); + } + search_term = Some(args[i + 1].to_string()); + i += 2; + } + _ => { + return Err(format!("Unknown option: {}", args[i])); + } + } + } + + Ok(Self { + state_filter, + search_term, + }) + } +} + +/// Handle list command in REPL +fn handle_list_command( + args: &[&str], + device: &Phone, + user_id: Option, + uad_lists: &HashMap, +) -> Result<(), Box> { + let parsed = ReplListArgs::parse(args)?; + + let pm_flag = parsed.state_filter.and_then(StateFilter::to_pm_flag); + let system_packages = ACommand::new() + .shell(&device.adb_id) + .pm() + .list_packages_sys(pm_flag, user_id)?; + + let context = PackageListContext { + state_filter: parsed.state_filter, + removal_filter: None, + list_filter: None, + search: parsed.search_term, + }; + + let displayed_count = display_package_list( + &system_packages, + uad_lists, + &device.adb_id, + user_id, + &context, + )?; + + if displayed_count == 0 { + println_or_exit!(" No packages found."); + } else { + println_or_exit!("\nTotal: {} package(s)", displayed_count); + } + + Ok(()) +} + +/// Handle info command in REPL +fn handle_info_command( + args: &[&str], + device: &Phone, + user_id: u16, + uad_lists: &HashMap, +) -> Result<(), Box> { + if args.is_empty() { + eprintln!("Usage: info "); + return Ok(()); + } + + let package = args[0]; + println!("Package: {}", package); + + if let Some(pkg_info) = uad_lists.get(package) { + println!(" List: {}", pkg_info.list); + println!(" Removal: {}", pkg_info.removal); + println!(" Description: {}", pkg_info.description); + } else { + println!(" Not found in UAD lists (unlisted package)"); + } + + let state = get_package_state(&device.adb_id, package, Some(user_id)) + .ok_or("Package not found on device")?; + println!(" State: {}", state); + + Ok(()) +} + +/// Handle state change command in REPL +fn handle_state_change_command( + args: &[&str], + device: &Phone, + user: User, + target_state: PackageState, + action_name: &str, + uad_lists: &HashMap, +) -> Result<(), Box> { + if args.is_empty() { + eprintln!( + "Usage: {} [package_name...]", + action_name.to_lowercase() + ); + return Ok(()); + } + + for pkg_name in args { + process_package_change(pkg_name, device, user, target_state, action_name, uad_lists)?; + } + + Ok(()) +} + +/// Process state change for a single package in REPL +fn process_package_change( + pkg_name: &str, + device: &Phone, + user: User, + target_state: PackageState, + action_name: &str, + uad_lists: &HashMap, +) -> Result<(), Box> { + let current_state = get_package_state(&device.adb_id, pkg_name, Some(user.id)) + .ok_or("Package not found on device")?; + + println!("{} {} (current: {})", action_name, pkg_name, current_state); + + if current_state == target_state { + println!(" → Already in target state, skipping"); + return Ok(()); + } + + let pkg_info = uad_lists.get(pkg_name); + if let Some(info) = pkg_info { + if info.removal == Removal::Unsafe { + println!(" ⚠ WARNING: This package is marked as UNSAFE to remove!"); + } + } + + let core_pkg = CorePackage { + name: pkg_name.to_string(), + description: pkg_info.map(|p| p.description.clone()).unwrap_or_default(), + removal: pkg_info.map(|p| p.removal).unwrap_or(Removal::Unlisted), + state: current_state, + list: pkg_info.map(|p| p.list).unwrap_or(UadList::Unlisted), + }; + + let commands = apply_pkg_state_commands(&core_pkg, target_state, user, device); + + execute_with_fallback( + pkg_name, + target_state, + &core_pkg, + user, + device, + &commands, + " ", + ) +} + +/// Print REPL help message +fn print_repl_help() { + println!("Available commands:"); + println!(" list [--state ] [--search ]"); + println!(" List packages with optional filters"); + println!(" info "); + println!(" Show information about a package"); + println!(" uninstall [package_name...]"); + println!(" Uninstall one or more packages"); + println!(" enable [package_name...]"); + println!(" Enable/restore one or more packages"); + println!(" disable [package_name...]"); + println!(" Disable one or more packages"); + println!(" device"); + println!(" Show current device information"); + println!(" clear"); + println!(" Clear the screen"); + println!(" help"); + println!(" Show this help message"); + println!(" exit, quit"); + println!(" Exit the interactive mode"); +} diff --git a/crates/uad-core/Cargo.toml b/crates/uad-core/Cargo.toml new file mode 100644 index 0000000..f7d3a43 --- /dev/null +++ b/crates/uad-core/Cargo.toml @@ -0,0 +1,52 @@ +[package] +name = "uad-core" +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +keywords.workspace = true +categories = ["command-line-utilities"] +edition.workspace = true + +[features] +default = [] +self-update = ["dep:flate2", "dep:tar"] + +[dependencies] +serde.workspace = true +serde_json.workspace = true +log.workspace = true +chrono.workspace = true +toml.workspace = true +dirs.workspace = true +ureq.workspace = true +retry.workspace = true +csv.workspace = true +flate2 = { workspace = true, optional = true } +tar = { workspace = true, optional = true } + +[target.'cfg(target_os = "windows")'.dependencies] +win32console.workspace = true + +[lints.rust] +deprecated_safe = "warn" + +[lints.clippy] +undocumented_unsafe_blocks = "forbid" +exit = "deny" +panic_in_result_fn = "warn" +infinite_loop = "warn" +mem_forget = "warn" +implicit_clone = "warn" +format_push_string = "warn" +large_include_file = "warn" +shadow_unrelated = "warn" +struct_field_names = "allow" # annoying + +disallowed_types = "deny" +disallowed_methods = "deny" + +allow_attributes_without_reason = "warn" +pedantic = { level = "warn", priority = -1 } diff --git a/src/core/adb.rs b/crates/uad-core/src/adb.rs similarity index 57% rename from src/core/adb.rs rename to crates/uad-core/src/adb.rs index c28a56e..f2335e0 100644 --- a/src/core/adb.rs +++ b/crates/uad-core/src/adb.rs @@ -38,18 +38,37 @@ //! For comprehensive info about ADB, //! [see this](https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/master/docs/) -use regex::Regex; -use serde::{Deserialize, Serialize}; -use std::sync::LazyLock; +use std::rc::Rc; #[cfg(target_os = "windows")] use std::os::windows::process::CommandExt; -pub fn to_trimmed_utf8(v: Vec) -> String { - String::from_utf8(v) - .expect("ADB should always output valid ASCII (or UTF-8, at least)") - .trim_end() - .to_string() +use crate::utils::is_all_w_c; +use log::{error, info, warn}; + +/// Convert ADB output bytes to a trimmed UTF-8 string. +/// Uses lossy conversion to prevent panics on non-UTF8 output from certain OEMs. +#[must_use] +pub fn to_trimmed_utf8(v: &[u8]) -> String { + String::from_utf8_lossy(v).trim_end().to_string() +} + +#[cfg(debug_assertions)] +#[must_use] +fn is_version_triple(s: &str) -> bool { + let mut components = s.split('.'); + for _ in 0..3 { + if !components + .next() + .is_some_and(|comp| comp.as_bytes().iter().all(u8::is_ascii_digit)) + { + return false; + } + } + if components.next().is_some() { + return false; + } + true } /// Builder object for an Android Debug Bridge CLI command, @@ -112,7 +131,7 @@ impl ACommand { .collect()) } - /// `version` sub-command, splitted by lines + /// `version` sub-command /// /// ## Format /// This is just a sample, @@ -131,42 +150,35 @@ impl ACommand { /// Installed as /platform-tools/adb[.exe] /// Running on () /// ``` - pub fn version(mut self) -> Result, String> { - #[cfg(debug_assertions)] - static TRIPLE: LazyLock = LazyLock::new(|| { - Regex::new(r"^Android Debug Bridge version \d+.\d+.\d+$") - .unwrap_or_else(|_| unreachable!()) - }); - #[cfg(debug_assertions)] - static DISTRO: LazyLock = LazyLock::new(|| { - Regex::new(r"^Version \d+.\d+.\d+-\S+$").unwrap_or_else(|_| unreachable!()) - }); - + #[expect(clippy::panic_in_result_fn, reason = "Assertions are fine")] + pub fn version(mut self) -> Result { self.0.arg("version"); - Ok(self - .run()? - .lines() - .enumerate() - // typically 5 allocs. - // ideally 0, if we didn't use `lines`. - .map(|(i, ln)| { - // DO NOT "REFACTOR" TO `debug_assert`! - // it's not the same! - #[cfg(debug_assertions)] - assert!(match i { - 0 => TRIPLE.is_match(ln), - 1 => DISTRO.is_match(ln), - 2 => - // missing test for valid path - ln.starts_with("Installed as ") - && (ln.ends_with("adb") || ln.ends_with("adb.exe")), - // missing test for x86/ARM (both 64b) - 3 => ln.starts_with("Running on "), - _ => unreachable!("Expected < 5 lines"), - }); - ln.to_string() - }) - .collect()) + let out = self.run()?; + + #[cfg(debug_assertions)] + { + const ADBV: &str = "Android Debug Bridge version "; + const V: &str = "Version "; + + let mut lns = out.lines(); + + assert!( + lns.next() + .is_some_and(|ln| ln.starts_with(ADBV) && is_version_triple(&ln[ADBV.len()..])) + ); + assert!(lns.next().is_some_and(|ln| ln.starts_with(V) + && is_version_triple(&ln[V.len()..ln.find('-').unwrap_or(ln.len())]))); + // missing test for valid path + assert!(lns.next().is_some_and(|ln| ln.starts_with("Installed as ") + && (ln.ends_with("adb") || ln.ends_with("adb.exe")))); + // missing test for x86/ARM (both 64b) + assert!(lns.next().is_some_and(|ln| ln.starts_with("Running on "))); + if lns.next().is_some() { + unreachable!("Expected < 5 lines") + } + } + + Ok(out) } /// General executor @@ -184,15 +196,15 @@ impl ACommand { ); match cmd.output() { Err(e) => { - error!("ADB: {}", e); + error!("ADB: {e}"); Err("Cannot run ADB, likely not found".to_string()) } Ok(o) => { - let stdout = to_trimmed_utf8(o.stdout); + let stdout = to_trimmed_utf8(&o.stdout); if o.status.success() { Ok(stdout) } else { - let stderr = to_trimmed_utf8(o.stderr); + let stderr = to_trimmed_utf8(&o.stderr); // ADB does really weird things: // Some errors are not redirected to `stderr` let err = if stdout.is_empty() { stderr } else { stdout }; @@ -203,6 +215,12 @@ impl ACommand { } } +impl Default for ACommand { + fn default() -> Self { + Self::new() + } +} + /// Builder object for a command that runs on the device's default `sh` implementation. /// Typically MKSH, but could be Ash. /// @@ -232,23 +250,53 @@ impl ShellCommand { self.0.0.arg("reboot"); self.0.run() } + + /// Execute an arbitrary shell action string on the device's default shell. + /// The action string is passed as a single argument to `adb shell` and + /// interpreted by the remote shell (which splits on spaces). + pub fn raw(mut self, action: &str) -> Result { + self.0.0.arg(action); + self.0.run() + } +} + +#[must_use] +pub const fn is_pkg_component(s: &[u8]) -> bool { + if s.is_empty() { + return false; + } + s[0].is_ascii_alphabetic() + && if s.len() > 1 { + is_all_w_c(s.split_at(1).1) + } else { + true + } } /// String with the invariant of being a valid package-name. -/// See its `new` constructor for more info. -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)] -pub struct PackageId(Box); +/// See [`PackageId::new`] for validation details. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PackageId(Rc); impl PackageId { - /// Creates a package-ID if it's valid according to - /// [this](https://developer.android.com/build/configure-app-module#set-application-id) - pub fn new(p_id: Box) -> Option { - static RE: LazyLock = LazyLock::new(|| { - Regex::new(r"^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+$") - .unwrap_or_else(|_| unreachable!()) - }); - - if RE.is_match(p_id.as_ref()) { - Some(Self(p_id)) + /// Creates a package-ID if it's `"android"` or valid according to: + /// - + /// - + #[must_use] + pub fn new(p_id: &str) -> Option { + if p_id == "android" { + return Some(Self(p_id.into())); + } + let mut components = p_id.split('.'); + for _ in 0..2 { + if !components + .next() + .is_some_and(|comp| is_pkg_component(comp.as_bytes())) + { + return None; + } + } + if components.all(|comp| is_pkg_component(comp.as_bytes())) { + Some(Self(p_id.into())) } else { None } @@ -287,16 +335,16 @@ const PACK_PREFIX: &str = "package:"; pub const PM_CLEAR_PACK: &str = "pm clear"; /// Builder object for an Android Package Manager command. -/// -/// [More info](https://developer.android.com/tools/adb#pm) +/// #[derive(Debug)] +#[must_use] pub struct PmCommand(ShellCommand); impl PmCommand { - /// `list packages -s` sub-command, [`PACK_PREFIX`] stripped. + /// `list packages -s` sub-command, [`PACK_PREFIX`] stripped from each element. /// /// `Ok` variant: - /// - isn't guaranteed to contain valid pack-IDs, - /// as "android" can be printed but it's invalid + /// - isn't 100% guaranteed to contain valid pack-IDs + /// but you can assume it does (except in `unsafe {}` blocks) /// - isn't sorted /// - duplicates never _seem_ to happen, but don't assume uniqueness pub fn list_packages_sys( @@ -309,35 +357,111 @@ impl PmCommand { cmd.args(["list", "packages", "-s"]); if let Some(s) = f { cmd.arg(s.to_str()); - }; + } if let Some(u) = user_id { cmd.arg("--user"); cmd.arg(u.to_string()); - }; + } self.0.0.run().map(|pack_ls| { pack_ls .lines() - .map(|p_ln| { + .filter_map(|p_ln| { debug_assert!(p_ln.starts_with(PACK_PREFIX)); - String::from(&p_ln[PACK_PREFIX.len()..]) + let p = &p_ln[PACK_PREFIX.len()..]; + if PackageId::new(p).is_some() { + Some(String::from(p)) + } else { + warn!("skipping nonstandard package name: {p:?}"); + None + } }) .collect() }) } - /// `list users` sub-command. - /// Output isn't parsed, because - /// we don't know if the format is stable across Android versions. + /// `list users` sub-command, deserialized/parsed. /// /// - /// - - pub fn list_users(mut self) -> Result { + pub fn list_users(mut self) -> Result, String> { self.0.0.0.args(["list", "users"]); - self.0.0.run() + Ok(self + .0 + .0 + .run()? + .lines() + .skip(1) // omit header + .map(|ln| { + // this could be optimized by making more API-stability assumptions + let ln = ln.trim_ascii_start(); + let ln = ln.strip_prefix("UserInfo").unwrap_or(ln).trim_ascii_start(); + let ln = ln.strip_prefix('{').unwrap_or(ln).trim_ascii(); + //let run; + let ln = if let Some(l) = ln.strip_suffix("running") { + //run = true; + l.trim_ascii_end() + } else { + //run = false; + ln + }; + let ln = ln.strip_suffix('}').unwrap_or(ln).trim_ascii_end(); + // https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/core/java/android/content/pm/UserInfo.java + // The format looks stable today, but google may change it in future Android versions + // (and very old Androids might differ). Keep parsing defensive. + // Expected shape: "UserInfo{::}[ running]" + + let mut comps = ln.split(':'); + + let id = comps + .next() + .expect("There must be at least 1 ':'-separated component") + .parse() + .expect("string assumed to be UID numeral"); + //let name = comps + // .next() + // .expect("There must be at least 2 ':'-separated components. 2nd is user-name"); + //let flags = u32::from_str_radix( + // comps.next().expect( + // "There must be at least 3 ':'-separated components. 3rd is user bit-flags", + // ), + // 16, + //) + //.expect("string assumed to be hexadecimal bit-flags"); + UserInfo { + id, + //name: name.into(), + //flags, + //running: run, + } + }) + .collect()) } } +/// Mirror of AOSP `UserInfo` Java Class, with an extra field +#[derive(Debug, Clone)] +pub struct UserInfo { + id: u16, + //name: Box, + //flags: u32, + //running: bool, +} +impl UserInfo { + #[must_use] + pub const fn get_id(&self) -> u16 { + self.id + } + /* + /// Check if the user was logged-in at the time `pm list users` was invoked + #[must_use] + #[allow(dead_code, reason = "Currently unused by UI; kept for future features")] + pub const fn was_running(&self) -> bool { + self.running + } + */ +} + #[cfg(test)] mod tests { use super::*; @@ -356,7 +480,7 @@ mod tests { "the.🎂.is.a.lie", "EXCLAMATION!!!!", ] { - assert_eq!(PackageId::new(p_id.into()), None); + assert_eq!(PackageId::new(p_id), None); } } @@ -373,7 +497,7 @@ mod tests { "com.github.w1nst0n", "this_.String_.is_.not_.real_", ] { - assert_ne!(PackageId::new(p_id.into()), None); + assert_ne!(PackageId::new(p_id), None); } } } diff --git a/src/core/config.rs b/crates/uad-core/src/config.rs similarity index 77% rename from src/core/config.rs rename to crates/uad-core/src/config.rs index ce8f1f9..5c41d78 100644 --- a/src/core/config.rs +++ b/crates/uad-core/src/config.rs @@ -1,13 +1,15 @@ use crate::CACHE_DIR; use crate::CONFIG_DIR; -use crate::core::utils::DisplayablePath; -use crate::core::{sync::User, theme::Theme}; -use crate::gui::views::settings::Settings; +use crate::sync::User; +use crate::utils::DisplayablePath; +use log::error; use serde::{Deserialize, Serialize}; use std::fs; use std::path::PathBuf; use std::sync::LazyLock; +const DEFAULT_THEME: &str = "Auto (follow system theme)"; + #[derive(Default, Debug, Serialize, Deserialize, Clone)] pub struct Config { pub general: GeneralSettings, @@ -35,7 +37,7 @@ pub struct BackupSettings { pub struct DeviceSettings { /// Unique serial identifier pub device_id: String, - pub disable_mode: bool, + pub disable_mode: bool, // should be `enum RemovalMode` pub multi_user_mode: bool, #[serde(skip)] pub backup: BackupSettings, @@ -44,7 +46,7 @@ pub struct DeviceSettings { impl Default for GeneralSettings { fn default() -> Self { Self { - theme: Theme::default().to_string(), + theme: DEFAULT_THEME.to_string(), expert_mode: false, backup_folder: CACHE_DIR.join("backups"), } @@ -54,30 +56,33 @@ impl Default for GeneralSettings { static CONFIG_FILE: LazyLock = LazyLock::new(|| CONFIG_DIR.join("config.toml")); impl Config { - pub fn save_changes(settings: &Settings, device_id: &String) { - let mut config = Self::load_configuration_file(); - if let Some(device) = config + pub fn save_device_settings( + &mut self, + device_settings: DeviceSettings, + general: GeneralSettings, + ) { + if let Some(device) = self .devices .iter_mut() - .find(|x| x.device_id == *device_id) + .find(|x| x.device_id == device_settings.device_id) { - device.clone_from(&settings.device); + *device = device_settings; } else { - debug!("config: New device settings saved"); - config.devices.push(settings.device.clone()); + self.devices.push(device_settings); } - config.general.clone_from(&settings.general); - let toml = toml::to_string(&config).unwrap(); + self.general = general; + let toml = toml::to_string(&self).unwrap(); fs::write(&*CONFIG_FILE, toml).expect("Could not write config file to disk!"); } + #[must_use] pub fn load_configuration_file() -> Self { match fs::read_to_string(&*CONFIG_FILE) { Ok(s) => match toml::from_str(&s) { Ok(config) => return config, - Err(e) => error!("Invalid config file: `{}`", e), + Err(e) => error!("Invalid config file: `{e}`"), }, - Err(e) => error!("Failed to read config file: `{}`", e), + Err(e) => error!("Failed to read config file: `{e}`"), } error!("Restoring default config file"); let toml = toml::to_string(&Self::default()).unwrap(); @@ -109,12 +114,15 @@ mod tests { fn test_load_configuration_file() { create_default_config_file(); let config = Config::load_configuration_file(); - assert_eq!(config.devices.len(), 0); - assert_eq!(config.general.theme, Theme::default().to_string()); + // non-deterministic + //assert_eq!(config.devices.len(), 0); + assert_eq!(config.general.theme, DEFAULT_THEME); assert!(!config.general.expert_mode); assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups")); } + // non-deterministic + /* #[test] fn test_save_changes() { let mut settings = Settings::default(); @@ -124,12 +132,13 @@ mod tests { let config = Config::load_configuration_file(); assert_eq!(config.devices[0].device_id, device_id); } + */ #[test] fn test_default_config() { let config = Config::default(); assert_eq!(config.devices.len(), 0); - assert_eq!(config.general.theme, Theme::default().to_string()); + assert_eq!(config.general.theme, DEFAULT_THEME); assert!(!config.general.expert_mode); assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups")); } diff --git a/crates/uad-core/src/lib.rs b/crates/uad-core/src/lib.rs new file mode 100644 index 0000000..be3e5b4 --- /dev/null +++ b/crates/uad-core/src/lib.rs @@ -0,0 +1,23 @@ +#![allow( + clippy::missing_panics_doc, + clippy::missing_errors_doc, + clippy::collapsible_if, + clippy::uninlined_format_args, + clippy::result_unit_err, + reason = "Doc+style pedantic lints are out-of-scope for this pass" +)] + +pub mod adb; +pub mod config; +pub mod save; +pub mod sync; +pub mod uad_lists; +pub mod update; +pub mod utils; + +use std::path::PathBuf; +use std::sync::LazyLock; +pub static CONFIG_DIR: LazyLock = + LazyLock::new(|| utils::setup_uad_dir(&dirs::config_dir().expect("Can't detect config dir"))); +pub static CACHE_DIR: LazyLock = + LazyLock::new(|| utils::setup_uad_dir(&dirs::cache_dir().expect("Can't detect cache dir"))); diff --git a/src/core/save.rs b/crates/uad-core/src/save.rs similarity index 66% rename from src/core/save.rs rename to crates/uad-core/src/save.rs index e76da6b..8c1db07 100644 --- a/src/core/save.rs +++ b/crates/uad-core/src/save.rs @@ -1,7 +1,7 @@ -use crate::core::config::{Config, DeviceSettings}; -use crate::core::sync::{CorePackage, Phone, User, apply_pkg_state_commands}; -use crate::core::utils::DisplayablePath; -use crate::gui::widgets::package_row::PackageRow; +use crate::config::{Config, DeviceSettings}; +use crate::sync::{CorePackage, Phone, User, apply_pkg_state_commands}; +use crate::utils::DisplayablePath; +use log::{error, info, warn}; use serde::{Deserialize, Serialize}; use std::{ fs, @@ -21,10 +21,10 @@ pub struct UserBackup { } /// Backup all `Uninstalled` and `Disabled` packages -pub async fn backup_phone( +pub fn backup_phone( users: Vec, device_id: String, - phone_packages: Vec>, + phone_packages: &[Vec], ) -> Result { let mut backup = PhoneBackup { device_id: device_id.clone(), @@ -37,11 +37,8 @@ pub async fn backup_phone( ..UserBackup::default() }; - for p in phone_packages[u.index].clone() { - user_backup.packages.push(CorePackage { - name: p.name.clone(), - state: p.state, - }); + for p in phone_packages[u.index].iter().cloned() { + user_backup.packages.push(p); } backup.users.push(user_backup); } @@ -52,9 +49,9 @@ pub async fn backup_phone( let backup_path = &*backup_dir.join(device_id); if let Err(e) = fs::create_dir_all(backup_path) { - error!("BACKUP: could not create backup dir: {}", e); + error!("BACKUP: could not create backup dir: {e}"); return Err(e.to_string()); - }; + } let backup_filename = format!("{}.json", chrono::Local::now().format("%Y-%m-%d_%H-%M-%S")); @@ -78,24 +75,21 @@ pub fn list_available_backups(dir: &Path) -> Vec { } } +#[must_use] pub fn list_available_backup_user(backup: DisplayablePath) -> Vec { match fs::read_to_string(backup.path) { - Ok(data) => { - let phone_backup: PhoneBackup = - serde_json::from_str(&data).expect("Unable to parse backup file"); - - let mut users = vec![]; - for u in phone_backup.users { - users.push(User { - id: u.id, - index: 0, - protected: false, - }); - } - users - } + Ok(data) => serde_json::from_str::(&data) + .expect("Unable to parse backup file") + .users + .into_iter() + .map(|u| User { + id: u.id, + index: 0, + protected: false, + }) + .collect(), Err(e) => { - error!("[BACKUP]: Selected backup file not found: {}", e); + error!("[BACKUP]: Selected backup file not found: {e}"); vec![] } } @@ -103,15 +97,22 @@ pub fn list_available_backup_user(backup: DisplayablePath) -> Vec { #[derive(Debug)] pub struct BackupPackage { + pub i_user: usize, pub index: usize, pub commands: Vec, } +#[derive(Debug)] +pub struct RestoreResult { + pub packages: Vec, + pub skipped_count: usize, +} + pub fn restore_backup( selected_device: &Phone, - packages: &[Vec], + packages: &[Vec], settings: &DeviceSettings, -) -> Result, String> { +) -> Result { match fs::read_to_string( settings .backup @@ -126,24 +127,26 @@ pub fn restore_backup( serde_json::from_str(&data).expect("Unable to parse backup file"); let mut commands = vec![]; + let mut skipped_packages = 0; for u in phone_backup.users { - let index = match selected_device.user_list.iter().find(|x| x.id == u.id) { + let i_user = match selected_device.user_list.iter().find(|x| x.id == u.id) { Some(i) => i.index, None => return Err(format!("user {} doesn't exist", u.id)), }; for (i, backup_package) in u.packages.iter().enumerate() { - let package: CorePackage = match packages[index] + let package: CorePackage = if let Some(p) = packages[i_user] .iter() .find(|x| x.name == backup_package.name) { - Some(p) => p.into(), - None => { - return Err(format!( - "{} not found for user {}", - backup_package.name, u.id - )); - } + p.clone() + } else { + skipped_packages += 1; + warn!( + "{} not found for user {} - skipping package during restore", + backup_package.name, u.id + ); + continue; }; let p_commands = apply_pkg_state_commands( &package, @@ -156,19 +159,29 @@ pub fn restore_backup( ); if !p_commands.is_empty() { commands.push(BackupPackage { + i_user, index: i, commands: p_commands, }); } } } + if skipped_packages > 0 { + info!( + "Restore completed with {skipped_packages} packages skipped (not found on device)" + ); + } if !commands.is_empty() { commands.push(BackupPackage { + i_user: 0, index: 0, commands: vec![], }); } - Ok(commands) + Ok(RestoreResult { + packages: commands, + skipped_count: skipped_packages, + }) } Err(e) => Err(e.to_string()), } diff --git a/crates/uad-core/src/sync.rs b/crates/uad-core/src/sync.rs new file mode 100644 index 0000000..f90b6ee --- /dev/null +++ b/crates/uad-core/src/sync.rs @@ -0,0 +1,663 @@ +use crate::{ + adb::{ACommand as AdbCommand, PM_CLEAR_PACK, PackageId}, + uad_lists::PackageState, +}; +use log::{error, info}; +use retry::{OperationResult, delay::Fixed, retry}; +use serde::{Deserialize, Serialize}; + +/// An Android device, typically a phone +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Phone { + /// Non-market name + pub model: String, // could be `Copy` + /// Android API level version + pub android_sdk: u8, + /// In theory, `len < u16::MAX` _should_ always be `true`. + /// In practice, `len <= u8::MAX`. + pub user_list: Vec, + /// Unique serial identifier + pub adb_id: String, // could be `Copy` +} + +impl Default for Phone { + fn default() -> Self { + Self { + model: "fetching devices...".to_string(), + android_sdk: 0, + user_list: vec![], + adb_id: String::default(), + } + } +} + +impl std::fmt::Display for Phone { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.model) + } +} + +/// `UserInfo` but relevant to UAD +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub struct User { + pub id: u16, + pub index: usize, + pub protected: bool, +} + +impl std::fmt::Display for User { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "user {}", self.id) + } +} + +/// An enum to contain different variants for errors yielded by ADB. +#[derive(Debug, Clone)] +pub enum AdbError { + Generic(String), +} + +/// Run an arbitrary shell action via the typed ADB wrapper. +/// This replaces the deprecated `adb_shell_command`. +/// +/// If `serial` is empty, it lets ADB choose the default device. +pub fn run_adb_shell_action>( + device_serial: S, + action: &str, +) -> Result { + let serial = device_serial.as_ref(); + + match AdbCommand::new().shell(serial).raw(action) { + Ok(o) => { + if ["Error", "Failure"].iter().any(|&e| o.contains(e)) { + let friendly_msg = make_friendly_error_message(&o, action); + return Err(AdbError::Generic(friendly_msg)); + } + info!("{action} -> {o}"); + Ok(o) + } + Err(err) => { + if !err.contains("[not installed for") { + let friendly_msg = make_friendly_error_message(&err, action); + return Err(AdbError::Generic(friendly_msg)); + } + Err(AdbError::Generic(err)) + } + } +} + +/// Convert common OEM-specific ADB error messages into user-friendly explanations. +fn make_friendly_error_message(error_output: &str, action: &str) -> String { + // Common Samsung errors + if error_output.contains("DELETE_FAILED_USER_RESTRICTED") { + return format!( + "Cannot uninstall: This package is restricted by the device manufacturer (Samsung Knox or similar).\n\ + Error: {error_output}\n\ + Tip: Try disabling the package instead, or check device settings for Knox/security restrictions." + ); + } + + if error_output.contains("NOT_INSTALLED_FOR_USER") { + return format!( + "Package is not installed for the current user.\n\ + Error: {error_output}\n\ + Tip: The package may be installed for a different user profile or work profile." + ); + } + + // Empty package name error + if error_output.contains("Shell cannot change component state for null") { + return format!( + "Invalid package: Empty package name detected.\n\ + Error: {error_output}\n\ + Tip: Please refresh the package list and try again." + ); + } + + // Generic permission errors + if error_output.contains("Permission denied") + || error_output.contains("INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE") + { + return format!( + "Permission denied: Insufficient privileges to perform this action.\n\ + Error: {error_output}\n\ + Tip: This may require root access or the package is protected by the system." + ); + } + + // Work profile / managed device errors + if error_output.contains("DELETE_FAILED_DEVICE_POLICY_MANAGER") { + return format!( + "Cannot modify: Package is managed by device policy (MDM/EMM).\n\ + Error: {error_output}\n\ + Tip: Contact your IT administrator if this is a work device." + ); + } + + // Generic failure with context + format!("{action} -> {error_output}") +} + +/// If `None`, returns an empty String, not " --user 0" +#[must_use] +pub fn user_flag(user_id: Option) -> String { + user_id + .map(|user| format!(" --user {}", user.id)) + .unwrap_or_default() +} + +// Minimum information for processing adb commands +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] +pub struct CorePackage { + pub name: String, + pub description: String, + #[serde(default)] + pub removal: crate::uad_lists::Removal, + #[serde(default)] + pub state: PackageState, + #[serde(default)] + pub list: crate::uad_lists::UadList, +} + +#[must_use] +pub fn apply_pkg_state_commands( + package: &CorePackage, + wanted_state: PackageState, + selected_user: User, + phone: &Phone, +) -> Vec { + // https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/ADB-reference + // ALWAYS PUT THE COMMAND THAT CHANGES THE PACKAGE STATE FIRST! + let commands = match wanted_state { + PackageState::Enabled => match package.state { + PackageState::Disabled => vec!["pm enable"], + PackageState::Uninstalled => match phone.android_sdk { + i if i >= 23 => vec!["cmd package install-existing"], + 21 | 22 => vec!["pm unhide"], + 19 | 20 => vec!["pm unblock", PM_CLEAR_PACK], + _ => unreachable!("already prevented by the GUI"), + }, + _ => vec![], + }, + PackageState::Disabled => match package.state { + PackageState::Uninstalled | PackageState::Enabled => { + if supports_disabling(phone) { + vec!["pm disable-user", "am force-stop", PM_CLEAR_PACK] + } else { + vec![] + } + } + _ => vec![], + }, + PackageState::Uninstalled => match package.state { + PackageState::Enabled | PackageState::Disabled => match phone.android_sdk { + sdk if sdk >= 23 => vec!["pm uninstall"], // > Marshmallow (6.0) + 21 | 22 => vec!["pm hide", PM_CLEAR_PACK], // Lollipop (5.x) + _ => vec!["pm block", PM_CLEAR_PACK], // Disable mode is unavailable on older devices because the specific ADB commands need root + }, + _ => vec![], + }, + PackageState::All => vec![], + }; // this should be a `tinyvec`, as `len <= 4` + + let user = supports_multi_user(phone).then_some(selected_user); + request_builder(&commands, &package.name, user) +} + +/// Build a command request to be sent via ADB to a device. +/// `commands` accepts one or more ADB shell commands +/// which act on a common `package` and `user`. +#[must_use] +pub fn request_builder(commands: &[&str], package: &str, user: Option) -> Vec { + // Defense-in-depth: `package` is interpolated verbatim into a device-shell + // action, so refuse any invalid name/ID. Every current caller already + // reconciles the name against the live device package list before reaching + // here, so this rejects nothing legitimate — it just keeps the no-injection + // guarantee local to the sink instead of relying on each caller to sanitise. + // Fail closed: emit no command for a malformed name rather than an injectable + // device-shell string. + if PackageId::new(package).is_none() { + error!("request_builder: refusing invalid package name: {package:?}"); + return Vec::new(); + } + let maybe_user_flag = user_flag(user); + commands + .iter() + .map(|c| format!("{c}{maybe_user_flag} {package}")) + .collect() +} + +/// Get the model by querying the `ro.product.model` property. +/// +/// If `serial` is empty, it lets ADB choose the default device. +#[must_use] +pub fn get_device_model(serial: &str) -> String { + AdbCommand::new() + .shell(serial) + .getprop("ro.product.model") + .unwrap_or_else(|err| { + eprintln!("ERROR: {err}"); + error!("{err}"); + if err.contains("adb: no devices/emulators found") { + "no devices/emulators found".to_string() + } else { + err + } + }) +} + +/// Get the brand by querying the `ro.product.brand` property. +/// +/// If `serial` is empty, it lets ADB choose the default device. +#[must_use] +pub fn get_device_brand(serial: &str) -> String { + AdbCommand::new() + .shell(serial) + .getprop("ro.product.brand") + // `trim` is just-in-case + .map(|s| s.trim().to_string()) + .unwrap_or_default() +} + +/// Get Android SDK version by querying the +// `ro.build.version.sdk` property or defaulting to 0. +/// +/// If `device_serial` is empty, it lets ADB choose the default device. +#[must_use] +pub fn get_android_sdk(device_serial: &str) -> u8 { + AdbCommand::new() + .shell(device_serial) + .getprop("ro.build.version.sdk") + .map_or(0, |sdk| { + sdk.parse().expect("SDK version numeral must be valid") + }) +} + +/// Capture the current state of a package across all non-protected users. +/// This is used to detect cross-user behavior by comparing before and after states. +/// +/// Only includes users where the package exists (Some state). Users where the package +/// doesn't exist (None) are not tracked. +#[must_use] +pub fn capture_cross_user_states( + package_name: &str, + device_serial: &str, + target_user_id: u16, + phone: &Phone, +) -> Vec<(u16, PackageState)> { + phone + .user_list + .iter() + .filter(|u| !u.protected && u.id != target_user_id) + .filter_map(|u| { + verify_package_state(package_name, device_serial, Some(u.id)).map(|state| (u.id, state)) + }) + .collect() +} + +/// Detect cross-user behavior and return appropriate notification message. +/// This handles unexpected cross-user behavior: +/// - Case A: Uninstall → Restore (package appears on other users) +/// - Case B: Uninstall → Uninstall (package disappears from other users that previously had it) +/// - Case C: Restore → Restore (package appears on other users) +#[must_use] +pub fn detect_cross_user_behavior( + package_name: &str, + device_serial: &str, + target_user_id: u16, + wanted_state: PackageState, + actual_state: PackageState, + phone: &Phone, + before_states: &[(u16, PackageState)], +) -> Option { + // Only check if operation was successful on target user + if actual_state != wanted_state { + return None; + } + + // Only check if we have multiple users + if phone.user_list.len() < 2 { + return None; + } + + let after_states = + check_cross_user_package_existence(package_name, device_serial, target_user_id, phone); + + match wanted_state { + PackageState::Uninstalled => { + if after_states.is_empty() { + // Case B: Uninstall → Uninstall (check if all users lost package) + let affected_users: Vec<_> = before_states + .iter() + .filter(|(uid, before_state)| { + // Only flag if the package was installed/enabled/disabled before + *before_state != PackageState::Uninstalled + // And is NOT in after_states (doesn't exist in usable state anymore) + && !after_states.iter().any(|(after_uid, _)| after_uid == uid) + }) + .map(|(uid, _)| uid) + .collect(); + + if affected_users.is_empty() { + None + } else { + let user_list = affected_users + .iter() + .map(|uid| format!("user {uid}")) + .collect::>() + .join(", "); + + Some(format!( + "Detected cross-user uninstall: package was also uninstalled from {user_list} after uninstalling from user {target_user_id}" + )) + } + } else { + // Case A: Uninstall → Restore (package appears on other users) + let user_list = after_states + .iter() + .map(|(uid, state)| format!("user {uid} ({state:?})")) + .collect::>() + .join(", "); + + Some(format!( + "Detected cross-user restoration: package exists on {user_list} after uninstalling from user {target_user_id}" + )) + } + } + PackageState::Enabled | PackageState::Disabled => { + // Case C: Restore → Restore (package appears on other users) + + // Check if a user didn't have the package before (not tracked or package didn't exist). + // Detects packages that appear on users where they didn't exist previously (OEM cross-user restoration). + let was_package_absent_before = |uid: &u16| { + before_states + .iter() + .find(|(before_uid, _)| before_uid == uid) + .is_none_or(|(_, before_state)| *before_state == PackageState::Uninstalled) + }; + + let newly_appeared: Vec<_> = after_states + .iter() + .filter(|(uid, _after_state)| was_package_absent_before(uid)) + .collect(); + + if newly_appeared.is_empty() { + None + } else { + let user_list = newly_appeared + .iter() + .map(|(uid, state)| format!("user {uid} ({state:?})")) + .collect::>() + .join(", "); + + Some(format!( + "Detected cross-user restoration: package exists on {user_list} after {} from user {target_user_id}", + if wanted_state == PackageState::Enabled { + "enabling" + } else { + "disabling" + } + )) + } + } + PackageState::All => None, + } +} + +#[must_use] +pub const fn supports_disabling(dev: &Phone) -> bool { + // >= Marshmallow (6.0) + dev.android_sdk >= 23 +} + +/// Check if it might support multi-user mode, +/// by simply comparing SDK version. +/// `true` isn't reliable, you can only trust `false`. +/// +/// See: +/// - +/// - +#[must_use] +pub const fn supports_multi_user(dev: &Phone) -> bool { + // >= Lollipop (5.0) + dev.android_sdk >= 21 +} + +/// Check if a `user_id` is protected on a device by trying +/// to list associated packages. +/// +/// If `device_serial` is empty, it lets ADB choose the default device. +pub fn is_protected_user>(user_id: u16, device_serial: S) -> bool { + AdbCommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(None, Some(user_id)) + .is_err() +} + +#[must_use] +pub fn list_users_idx_prot(device_serial: &str) -> Vec { + AdbCommand::new() + .shell(device_serial) + .pm() + .list_users() + .map(|out| { + out.into_iter() + .enumerate() + .map(|(i, user)| { + let id = user.get_id(); + User { + id, + index: i, + protected: is_protected_user(id, device_serial), + } + }) + .collect() + }) + .unwrap_or_default() +} + +/// This matches serials (`getprop ro.serialno`) +/// that are authorized by the user. +#[must_use] +pub fn get_devices_list() -> Vec { + retry( + Fixed::from_millis(500).take(if cfg!(debug_assertions) { 3 } else { 10 }), + || match AdbCommand::new().devices() { + Ok(devices) => { + let mut device_list: Vec = vec![]; + if devices.iter().all(|(_, stat)| stat != "device") { + return OperationResult::Retry(vec![]); + } + for device in devices { + let serial = &device.0; + device_list.push(Phone { + model: format!("{} {}", get_device_brand(serial), get_device_model(serial)), + android_sdk: get_android_sdk(serial), + user_list: list_users_idx_prot(serial), + adb_id: serial.clone(), + }); + } + OperationResult::Ok(device_list) + } + Err(err) => { + error!("get_devices_list() -> {err}"); + let test: Vec = vec![]; + OperationResult::Retry(test) + } + }, + ) + .unwrap_or_default() +} + +#[must_use] +pub fn initial_load() -> bool { + match AdbCommand::new().devices() { + Ok(_devices) => true, + Err(_err) => false, + } +} + +/// Get the current state of a package on a device +#[must_use] +pub fn get_package_state( + device_serial: &str, + package_name: &str, + user_id: Option, +) -> Option { + use crate::adb::{ACommand as AdbCommand, PmListPacksFlag}; + + // Check if package is enabled + if let Ok(enabled_packages) = AdbCommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(Some(PmListPacksFlag::OnlyEnabled), user_id) + && enabled_packages.contains(&package_name.to_string()) + { + return Some(PackageState::Enabled); + } + + // Check if package is disabled + if let Ok(disabled_packages) = AdbCommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(Some(PmListPacksFlag::OnlyDisabled), user_id) + && disabled_packages.contains(&package_name.to_string()) + { + return Some(PackageState::Disabled); + } + + // Check if package exists at all (including uninstalled) + if let Ok(all_packages) = AdbCommand::new() + .shell(device_serial) + .pm() + .list_packages_sys(Some(PmListPacksFlag::IncludeUninstalled), user_id) + && all_packages.contains(&package_name.to_string()) + { + return Some(PackageState::Uninstalled); + } + + // Package not found at all - it doesn't exist on this device/user + None +} + +/// Verify the current state of a package on a device. +/// Returns the package state, or `None` if the package doesn't exist. +#[must_use] +pub fn verify_package_state( + package_name: &str, + device_serial: &str, + user_id: Option, +) -> Option { + get_package_state(device_serial, package_name, user_id) +} + +/// Check if a package exists on any other users besides the target user. +/// This helps detect OEM-specific cross-user restoration behavior. +/// +/// Only includes users where the package exists in a non-uninstalled state +/// (i.e., Enabled or Disabled). +#[must_use] +pub fn check_cross_user_package_existence( + package_name: &str, + device_serial: &str, + target_user_id: u16, + phone: &Phone, +) -> Vec<(u16, PackageState)> { + let mut other_user_states = Vec::new(); + + for user in &phone.user_list { + if user.id != target_user_id + && !user.protected + && let Some(state) = verify_package_state(package_name, device_serial, Some(user.id)) + && state != PackageState::Uninstalled + { + other_user_states.push((user.id, state)); + } + } + + other_user_states +} + +/// Creates a `CorePackage` with the specified state, preserving other fields from the original. +fn package_with_state(package: &CorePackage, state: PackageState) -> CorePackage { + CorePackage { + state, + ..package.clone() + } +} + +/// Executes the first available command and returns the result. +fn execute_first_command(commands: &[String], phone: &Phone) -> Result<(), String> { + if commands.is_empty() { + return Err("No command available".to_string()); + } + AdbCommand::new() + .shell(&phone.adb_id) + .raw(&commands[0]) + .map(|_| ()) + .map_err(|err| err.clone()) +} + +/// Attempt fallback action when package state verification fails +pub fn attempt_fallback( + package: &CorePackage, + wanted_state: PackageState, + actual_state: PackageState, + user: User, + phone: &Phone, +) -> Result { + match (wanted_state, actual_state) { + // Case 1: Tried to uninstall but package was reinstalled -> disable it + (PackageState::Uninstalled, PackageState::Enabled) => { + let pkg = package_with_state(package, PackageState::Enabled); + let commands = apply_pkg_state_commands(&pkg, PackageState::Disabled, user, phone); + execute_first_command(&commands, phone) + .map(|()| "disabled package instead of uninstalling".to_string()) + .map_err(|e| format!("Failed to disable package: {e}")) + } + + // Case 2: Tried to disable but package re-enabled itself -> try uninstall + (PackageState::Disabled, PackageState::Enabled) => { + let pkg = package_with_state(package, PackageState::Enabled); + let commands = apply_pkg_state_commands(&pkg, PackageState::Uninstalled, user, phone); + execute_first_command(&commands, phone) + .map_err(|e| format!("Failed to uninstall: {e}"))?; + + // Verify the package was actually uninstalled + match verify_package_state(&package.name, &phone.adb_id, Some(user.id)) { + Some(PackageState::Uninstalled) | None => { + Ok("uninstalled package instead of disabling".to_string()) + } + _ => Err("Package still exists after uninstall attempt".to_string()), + } + } + + // Case 3: Tried to enable but package was disabled -> try uninstall then reinstall + (PackageState::Enabled, PackageState::Disabled) => { + let pkg = package_with_state(package, PackageState::Disabled); + let uninstall_cmds = + apply_pkg_state_commands(&pkg, PackageState::Uninstalled, user, phone); + execute_first_command(&uninstall_cmds, phone) + .map_err(|e| format!("Failed to uninstall for reinstall: {e}"))?; + + // Now try to reinstall/enable + let pkg_uninstalled = package_with_state(package, PackageState::Uninstalled); + let enable_cmds = + apply_pkg_state_commands(&pkg_uninstalled, PackageState::Enabled, user, phone); + + if enable_cmds.is_empty() { + return Ok("uninstalled package but couldn't reinstall".to_string()); + } + + execute_first_command(&enable_cmds, phone) + .map(|()| "uninstalled and reinstalled package to enable it".to_string()) + .map_err(|e| format!("Failed to reinstall package: {e}")) + } + + // Other cases - no fallback available + _ => Err(format!( + "No fallback available for wanted state {wanted_state:?} and actual state {actual_state:?}" + )), + } +} diff --git a/src/core/uad_lists.rs b/crates/uad-core/src/uad_lists.rs similarity index 82% rename from src/core/uad_lists.rs rename to crates/uad-core/src/uad_lists.rs index 0deece6..35cade9 100644 --- a/src/core/uad_lists.rs +++ b/crates/uad-core/src/uad_lists.rs @@ -1,5 +1,6 @@ use crate::CACHE_DIR; -use crate::core::utils::{format_diff_time_from_now, last_modified_date}; +use crate::utils::{format_diff_time_from_now, last_modified_date}; +use log::warn; use retry::{OperationResult, delay::Fixed, retry}; use serde::{Deserialize, Serialize}; use serde_json; @@ -15,7 +16,7 @@ pub const LIST_FNAME: &str = "uad_lists.json"; reason = "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/discussions/608" )] // not `const`, because it's too big -pub static DATA: &str = include_str!("../../resources/assets/uad_lists.json"); +pub static DATA: &str = include_str!("../../../resources/assets/uad_lists.json"); #[derive(Deserialize, Debug, Clone, PartialEq, Hash, Eq)] #[serde(rename_all = "camelCase")] @@ -28,7 +29,7 @@ pub struct Package { pub removal: Removal, } -#[derive(Default, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Default, Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum UadList { #[default] All, @@ -73,6 +74,7 @@ impl UadList { Self::Unlisted, ]; + #[must_use] pub const fn as_str(self) -> &'static str { match self { Self::All => "All lists", @@ -148,7 +150,7 @@ impl Opposite for PackageState { } // Bad names. To be changed! -#[derive(Default, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Default, Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)] pub enum Removal { #[default] Recommended, @@ -176,6 +178,7 @@ impl Removal { Self::Unlisted, ]; + #[must_use] pub const fn as_str(self) -> &'static str { match self { Self::All => "All removals", @@ -206,23 +209,32 @@ pub fn load_debloat_lists(remote: bool) -> Result { - // TODO: max resp size is 10MB, list is ~1.3MB; - // TODO: https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/discussions/608 - #[warn(clippy::expect_used, reason = "this will panic if GH servers rate-limit the user, or many other reasons.")] - let text = data.into_string().expect("response should be Ok type"); + Ok(mut data) => { + // https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/discussions/608 + let text = data + .body_mut() + .with_config() + .limit(1 << (3 + 10 + 10)) + .read_to_string() + .expect("remote list is bigger than 8MiB"); fs::write(cached_uad_lists.clone(), &text).expect("Unable to write file"); - let list: PackageHashMap = serde_json::from_str(&text).expect("Unable to parse"); + let list: PackageHashMap = + serde_json::from_str(&text).expect("Unable to parse"); OperationResult::Ok(list) } Err(e) => { - warn!("Could not load remote debloat list: {}", e); + warn!("Could not load remote debloat list: {e}"); error = true; OperationResult::Retry(PackageHashMap::new()) } diff --git a/src/core/update.rs b/crates/uad-core/src/update.rs similarity index 88% rename from src/core/update.rs rename to crates/uad-core/src/update.rs index 6f5b831..51e52e4 100644 --- a/src/core/update.rs +++ b/crates/uad-core/src/update.rs @@ -1,9 +1,9 @@ -use crate::core::utils::NAME; - use serde::Deserialize; #[cfg(feature = "self-update")] use { + crate::utils::NAME, + log::{debug, error}, retry::{OperationResult, delay::Fibonacci, retry}, std::fs, std::io, @@ -55,15 +55,14 @@ impl std::fmt::Display for SelfUpdateStatus { /// Download a file from the internet #[cfg(feature = "self-update")] #[allow(clippy::unused_async, reason = "`.call` is equivalent to `.await`")] -pub async fn download_file(url: T, dest_file: PathBuf) -> Result<(), String> { - let url = url.to_string(); - debug!("downloading file from {}", &url); +pub async fn download_file(url: &str, dest_file: PathBuf) -> Result<(), String> { + debug!("downloading file from {url}"); - match ureq::get(&url).call() { - Ok(res) => { + match ureq::get(url).call() { + Ok(mut res) => { let mut file = fs::File::create(dest_file).map_err(|e| e.to_string())?; - if let Err(e) = copy(&mut res.into_reader(), &mut file) { + if let Err(e) = copy(&mut res.body_mut().as_reader(), &mut file) { return Err(e.to_string()); } } @@ -77,7 +76,7 @@ pub async fn download_file(url: T, dest_file: PathBuf) -> Re /// then returns both the original file name (new version) and temp path (old version) #[cfg(feature = "self-update")] pub async fn download_update_to_temp_file( - bin_name: String, + bin_name: &str, release: Release, ) -> Result<(PathBuf, PathBuf), ()> { let current_bin_path = std::env::current_exe().map_err(|_| ())?; @@ -110,8 +109,8 @@ pub async fn download_update_to_temp_file( let archive_path = current_bin_path.parent().ok_or(())?.join(&asset_name); - if let Err(e) = download_file(asset.download_url, archive_path.clone()).await { - error!("Couldn't download {NAME} update: {}", e); + if let Err(e) = download_file(&asset.download_url, archive_path.clone()).await { + error!("Couldn't download {NAME} update: {e}"); return Err(()); } @@ -133,7 +132,7 @@ pub async fn download_update_to_temp_file( .cloned() .ok_or(())?; - if let Err(e) = download_file(asset.download_url, download_path.clone()).await { + if let Err(e) = download_file(&asset.download_url, download_path.clone()).await { error!("Couldn't download {NAME} update: {}", e); return Err(()); } @@ -147,23 +146,17 @@ pub async fn download_update_to_temp_file( let mut permissions = fs::metadata(&download_path).map_err(|_| ())?.permissions(); permissions.set_mode(0o755); if let Err(e) = fs::set_permissions(&download_path, permissions) { - error!("[SelfUpdate] Couldn't set permission to temp file: {}", e); + error!("[SelfUpdate] Couldn't set permission to temp file: {e}"); return Err(()); } } if let Err(e) = rename(¤t_bin_path, &tmp_path) { - error!( - "[SelfUpdate] Couldn't rename from current to temporary binary path: {}", - e - ); + error!("[SelfUpdate] Couldn't rename from current to temporary binary path: {e}"); return Err(()); } if let Err(e) = rename(&download_path, ¤t_bin_path) { - error!( - "[SelfUpdate] Couldn't rename from downloaded to current binary path: {}", - e - ); + error!("[SelfUpdate] Couldn't rename from downloaded to current binary path: {e}"); return Err(()); } @@ -182,10 +175,10 @@ pub fn get_latest_release() -> Result, ()> { pub fn get_latest_release() -> Result, ()> { debug!("Checking for {NAME} update"); - if let Ok(res) = ureq::get("https://api.github.com/repos/Universal-Debloater-Alliance/universal-android-debloater/releases/latest") + if let Ok(mut res) = ureq::get("https://api.github.com/repos/Universal-Debloater-Alliance/universal-android-debloater/releases/latest") .call() { let release: Release = serde_json::from_value( - res.into_json::() + res.body_mut().read_json::() .map_err(|_| ())? .clone(), ) @@ -232,7 +225,7 @@ pub fn extract_binary_from_tar(archive_path: &Path, temp_file: &Path) -> io::Res /// Hardcoded binary names for each compilation target /// that gets published to the GitHub Release #[cfg(feature = "self-update")] -pub const fn bin_name() -> &'static str { +pub const BIN_NAME: &str = { #[cfg(target_os = "windows")] { "uad-ng-windows.exe" @@ -252,7 +245,7 @@ pub const fn bin_name() -> &'static str { { "uad-ng-linux" } -} +}; /// Rename a file or directory to a new name, retrying if the operation fails because of permissions /// diff --git a/src/core/utils.rs b/crates/uad-core/src/utils.rs similarity index 61% rename from src/core/utils.rs rename to crates/uad-core/src/utils.rs index 0f17280..3569162 100644 --- a/src/core/utils.rs +++ b/crates/uad-core/src/utils.rs @@ -1,14 +1,13 @@ #![warn(clippy::unwrap_used)] -use crate::core::{ +use crate::{ adb::{ACommand as AdbCommand, PmListPacksFlag}, - sync::User, - theme::Theme, + sync::{CorePackage, User}, uad_lists::{PackageHashMap, PackageState, Removal, UadList}, }; -use crate::gui::widgets::package_row::PackageRow; use chrono::{DateTime, offset::Utc}; use csv::Writer; +use log::error; use std::{ collections::HashSet, fmt, fs, @@ -17,8 +16,32 @@ use std::{ /// Canonical shortened name of the application pub const NAME: &str = "UAD-ng"; +/// Full name of the application +pub const FULL_NAME: &str = "Universal Android Debloater Next Generation"; pub const EXPORT_FILE_NAME: &str = "selection_export.txt"; +/// Returns `true` if `c` matches the regex `\w` +#[inline] +#[must_use] +pub const fn is_w(c: u8) -> bool { + // https://github.com/rust-lang/rust/issues/93279 + // https://github.com/rust-lang/rust/issues/83623 + (c == b'_') | c.is_ascii_alphanumeric() +} + +/// Returns `true` if `s` matches the regex `^\w+$` +#[must_use] +pub const fn is_all_w_c(s: &[u8]) -> bool { + let mut i = 0; + while i < s.len() { + if !is_w(s[i]) { + return false; + } + i += 1; + } + true +} + // Takes a time-stamp parameter, // for purity and testability. // @@ -42,11 +65,12 @@ pub enum Error { DialogClosed, } +#[must_use] pub fn fetch_packages( uad_lists: &PackageHashMap, device_serial: &str, user_id: Option, -) -> Vec { +) -> Vec { let all_sys_packs = AdbCommand::new() .shell(device_serial) .pm() @@ -68,24 +92,24 @@ pub fn fetch_packages( .collect(); let mut description; - let mut uad_list; - let mut state; let mut removal; - let mut user_package: Vec = Vec::new(); + let mut state; + let mut list; + let mut user_package: Vec = Vec::new(); for pack_name in all_sys_packs { let p_name = &pack_name; - state = PackageState::Uninstalled; - description = "[No description]: CONTRIBUTION WELCOMED"; - uad_list = UadList::Unlisted; + description = String::from("[No description]: CONTRIBUTION WELCOMED"); removal = Removal::Unlisted; + state = PackageState::Uninstalled; + list = UadList::Unlisted; if let Some(package) = uad_lists.get(p_name) { if !package.description.is_empty() { - description = &package.description; + description = package.description.clone(); } - uad_list = package.list; removal = package.removal; + list = package.list; } if enabled_sys_packs.contains(p_name) { @@ -94,34 +118,30 @@ pub fn fetch_packages( state = PackageState::Disabled; } - let package_row = - PackageRow::new(p_name, state, description, uad_list, removal, false, false); - user_package.push(package_row); + let package = CorePackage { + name: p_name.clone(), + description, + removal, + state, + list, + }; + user_package.push(package); } - user_package.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + user_package.sort_by_key(|package| package.name.to_lowercase()); user_package } -pub fn string_to_theme(theme: &str) -> Theme { - match theme { - "Dark" => Theme::Dark, - "Light" => Theme::Light, - "Lupin" => Theme::Lupin, - // Auto uses `Display`, so it doesn't have a canonical repr - t if t.starts_with("Auto") => Theme::Auto, - _ => Theme::default(), - } -} - +#[must_use] pub fn setup_uad_dir(dir: &Path) -> PathBuf { let dir = dir.join("uad"); if let Err(e) = fs::create_dir_all(&dir) { - error!("Can't create directory: {dir:?}"); + error!("Can't create directory: {}", dir.display()); panic!("{e}"); - }; + } dir } +/// Open a directory or file with the system's default file manager. pub fn open_url(dir: PathBuf) { const OPENER: &str = match std::env::consts::OS.as_bytes() { b"windows" => "explorer", @@ -132,16 +152,23 @@ pub fn open_url(dir: PathBuf) { match std::process::Command::new(OPENER).arg(dir).output() { Ok(o) => { if !o.status.success() { - // does Windows print UTF-16? - let stderr = String::from_utf8(o.stderr).unwrap().trim_end().to_string(); - error!("Can't open the following URL: {}", stderr); + // Use lossy conversion for stderr - some systems (like Windows) + // may output non-UTF8 characters in error messages + let stderr = String::from_utf8_lossy(&o.stderr); + let stderr_trimmed = stderr.trim_end(); + if stderr_trimmed.is_empty() { + error!("Can't open URL: command failed with no error message"); + } else { + error!("Can't open the following URL: {stderr_trimmed}"); + } } } - Err(e) => error!("Failed to run command to open the file explorer: {}", e), + Err(e) => error!("Failed to run command to open the file explorer: {e}"), } } #[rustfmt::skip] +#[must_use] pub fn last_modified_date(file: PathBuf) -> DateTime { fs::metadata(file).map_or_else(|_| Utc::now(), |metadata| match metadata.modified() { Ok(time) => time.into(), @@ -149,6 +176,7 @@ pub fn last_modified_date(file: PathBuf) -> DateTime { }) } +#[must_use] pub fn format_diff_time_from_now(date: DateTime) -> String { let now: DateTime = Utc::now(); let last_update = now - date; @@ -163,15 +191,10 @@ pub fn format_diff_time_from_now(date: DateTime) -> String { } } -/// Export selected packages. +/// Export selected package names. /// File will be saved in same directory where UAD-ng is located. -pub async fn export_selection(packages: Vec) -> Result { - let selected = packages - .iter() - .filter(|p| p.selected) - .map(|p| p.name.clone()) - .collect::>() - .join("\n"); +pub fn export_selection(package_names: &[String]) -> Result { + let selected = package_names.join("\n"); match fs::write(EXPORT_FILE_NAME, selected) { Ok(()) => Ok(true), @@ -191,10 +214,11 @@ impl fmt::Display for DisplayablePath { error!("[PATH STEM]: No file stem found"); "[File steam not found]".to_string() }, - |p| match p.to_os_string().into_string() { - Ok(stem) => stem, - Err(e) => { - error!("[PATH ENCODING]: {:?}", e); + |p| { + if let Ok(stem) = p.to_os_string().into_string() { + stem + } else { + error!("[PATH ENCODING]: {}", self.path.display()); "[PATH ENCODING ERROR]".to_string() } }, @@ -204,22 +228,9 @@ impl fmt::Display for DisplayablePath { } } -/// Can be used to choose any folder. -pub async fn open_folder() -> Result { - let picked_folder = rfd::AsyncFileDialog::new() - .pick_folder() - .await - .ok_or(Error::DialogClosed)?; - - Ok(picked_folder.path().to_owned()) -} - /// Export uninstalled packages in a csv file. /// Exported information will contain package name and description. -pub async fn export_packages( - user: User, - phone_packages: Vec>, -) -> Result { +pub fn export_packages(user: User, phone_packages: &[Vec]) -> Result { let backup_file = generate_backup_name(chrono::Local::now()); let file = fs::File::create(backup_file).map_err(|err| err.to_string())?; @@ -228,7 +239,7 @@ pub async fn export_packages( wtr.write_record(["Package Name", "Description"]) .map_err(|err| err.to_string())?; - let uninstalled_packages: Vec<&PackageRow> = phone_packages[user.index] + let uninstalled_packages: Vec<&CorePackage> = phone_packages[user.index] .iter() .filter(|p| p.state == PackageState::Uninstalled) .collect(); @@ -243,6 +254,36 @@ pub async fn export_packages( Ok(true) } +/// Truncate description to fit within max length, taking only the first line +#[must_use] +pub fn truncate_description(desc: &str, max_len: usize) -> String { + let first_line = desc.split('\n').next().unwrap_or("").trim_end(); + + if first_line.len() <= max_len { + first_line.to_string() + } else { + format!("{}...", &first_line[..max_len.saturating_sub(3)]) + } +} + +/// Check if package matches search term (checks name and description) +#[must_use] +pub fn matches_search(pkg_name: &str, search_term: &str, pkg_description: Option<&str>) -> bool { + let search_lower = search_term.to_lowercase(); + + if pkg_name.to_lowercase().contains(&search_lower) { + return true; + } + + if let Some(description) = pkg_description { + if description.to_lowercase().contains(&search_lower) { + return true; + } + } + + false +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/uad-gui/Cargo.toml b/crates/uad-gui/Cargo.toml new file mode 100644 index 0000000..4a50636 --- /dev/null +++ b/crates/uad-gui/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "uad-gui" +version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +keywords.workspace = true +categories = ["gui"] +edition.workspace = true + +[[bin]] +name = "uad-ng" +path = "src/main.rs" + +[features] +default = ["wgpu", "self-update", "img"] +wgpu = [] # Iced/wgpu is default +self-update = ["flate2", "tar"] +no-self-update = [] +img = ["image", "iced/image"] + +[dependencies] +uad-core = { path = "../uad-core", features = ["self-update"] } +iced.workspace = true +image = { workspace = true, optional = true } +rfd.workspace = true +dark-light.workspace = true +fern.workspace = true +chrono.workspace = true +dirs.workspace = true +log.workspace = true +flate2 = { workspace = true, optional = true } +tar = { workspace = true, optional = true } + +[target.'cfg(target_os = "windows")'.dependencies] +win32console.workspace = true + +[build-dependencies] +embed-resource = "3" + +[lints.rust] +deprecated_safe = "warn" + +[lints.clippy] +undocumented_unsafe_blocks = "forbid" +exit = "deny" +panic_in_result_fn = "warn" +infinite_loop = "warn" +mem_forget = "warn" +implicit_clone = "warn" +format_push_string = "warn" +large_include_file = "warn" +shadow_unrelated = "warn" +struct_field_names = "allow" # annoying + +disallowed_types = "deny" +disallowed_methods = "deny" + +allow_attributes_without_reason = "warn" +pedantic = { level = "warn", priority = -1 } diff --git a/src/gui/mod.rs b/crates/uad-gui/src/gui.rs similarity index 70% rename from src/gui/mod.rs rename to crates/uad-gui/src/gui.rs index 09dffa6..925aedf 100644 --- a/src/gui/mod.rs +++ b/crates/uad-gui/src/gui.rs @@ -1,32 +1,32 @@ -pub mod style; -pub mod views; -pub mod widgets; - -use crate::core::adb; -use crate::core::sync::{Phone, get_devices_list, initial_load}; -use crate::core::theme::{OS_COLOR_SCHEME, Theme}; -use crate::core::uad_lists::UadListState; -use crate::core::update::{Release, SelfUpdateState, SelfUpdateStatus, get_latest_release}; -use crate::core::utils::{NAME, string_to_theme}; - -use iced::advanced::graphics::image::image_rs::ImageFormat; -use iced::font; -use iced::window::icon; -use views::about::{About as AboutView, Message as AboutMessage}; -use views::list::{List as AppsView, LoadingState as ListLoadingState, Message as AppsMessage}; -use views::settings::{Message as SettingsMessage, Settings as SettingsView}; -use widgets::navigation_menu::nav_menu; - -use iced::widget::column; -use iced::{ - Alignment, Application, Command, Element, Length, Renderer, Settings, - window::Settings as Window, +#[cfg(feature = "img")] +use crate::theme::OS_COLOR_SCHEME; +use crate::theme::Theme; +use crate::theme::string_to_theme; +use crate::views::about::{About as AboutView, Message as AboutMessage}; +use crate::views::list::{ + List as AppsView, LoadingState as ListLoadingState, Message as AppsMessage, }; +use crate::views::settings::{Message as SettingsMessage, Settings as SettingsView}; +use crate::widgets::navigation_menu::nav_menu; +use iced::font; +use iced::widget::column; +#[cfg(feature = "img")] +use iced::window::icon; +use iced::{Alignment, Element, Length, Settings, Task, window::Settings as Window}; +use iced::{Subscription, event, keyboard}; +#[cfg(feature = "img")] +use image::ImageFormat; +use log::{debug, error, info}; #[cfg(feature = "self-update")] use std::path::PathBuf; +use uad_core::adb; +use uad_core::sync::{Phone, get_devices_list, initial_load}; +use uad_core::uad_lists::UadListState; +use uad_core::update::{Release, SelfUpdateState, SelfUpdateStatus, get_latest_release}; +use uad_core::utils::{FULL_NAME, NAME}; #[cfg(feature = "self-update")] -use crate::core::update::{bin_name, download_update_to_temp_file, remove_file}; +use uad_core::update::{BIN_NAME, download_update_to_temp_file, remove_file}; #[derive(Default, Debug, Clone)] enum View { @@ -38,11 +38,11 @@ enum View { #[derive(Default, Clone)] pub struct UpdateState { - self_update: SelfUpdateState, - uad_list: UadListState, + pub self_update: SelfUpdateState, + pub uad_list: UadListState, } -#[derive(Default, Clone)] +#[derive(Default)] pub struct UadGui { view: View, apps_view: AppsView, @@ -77,22 +77,28 @@ pub enum Message { ADBSatisfied(bool), } -impl Application for UadGui { - type Theme = Theme; - type Executor = iced::executor::Default; - type Message = Message; - type Flags = (); +impl UadGui { + #[allow( + clippy::unused_self, + reason = "required by iced's Application trait interface" + )] + fn title(&self) -> String { + self.selected_device.as_ref().map_or_else( + || FULL_NAME.to_string(), + |device| format!("{FULL_NAME} - {}", device.model), + ) + } - fn new(_flags: ()) -> (Self, Command) { + fn new() -> (Self, Task) { ( Self::default(), - Command::batch([ - // Used in crate::gui::widgets::navigation_menu::ICONS. Name is `icomoon`. - font::load(include_bytes!("../../resources/assets/icons.ttf").as_slice()) + Task::batch([ + // Used in crate::widgets::navigation_menu::ICONS. Name is `icomoon`. + font::load(include_bytes!("../../../resources/assets/icons.ttf").as_slice()) .map(Message::FontLoaded), - Command::perform(initial_load(), Message::ADBSatisfied), - Command::perform(get_devices_list(), Message::LoadDevices), - Command::perform( + Task::perform(async { initial_load() }, Message::ADBSatisfied), + Task::perform(async { get_devices_list() }, Message::LoadDevices), + Task::perform( async move { get_latest_release() }, Message::GetLatestRelease, ), @@ -100,15 +106,57 @@ impl Application for UadGui { ) } - fn theme(&self) -> Theme { - string_to_theme(&self.settings_view.general.theme) + #[allow( + clippy::unused_self, + reason = "required by iced's Application trait interface" + )] + fn subscription(&self) -> Subscription { + if self.selected_device.is_some() { + event::listen_with(Self::keyboard_shortcuts_with_device) + } else { + event::listen_with(Self::keyboard_shortcuts_without_device) + } } - fn title(&self) -> String { - String::from("Universal Android Debloater Next Generation") + fn keyboard_shortcuts_with_device( + event: iced::Event, + _status: iced::event::Status, + _window: iced::window::Id, + ) -> Option { + Self::keyboard_shortcuts(event, true) } - #[allow(clippy::too_many_lines)] - fn update(&mut self, msg: Message) -> Command { + + fn keyboard_shortcuts_without_device( + event: iced::Event, + _status: iced::event::Status, + _window: iced::window::Id, + ) -> Option { + Self::keyboard_shortcuts(event, false) + } + + fn keyboard_shortcuts(event: iced::Event, can_control_device: bool) -> Option { + match event { + iced::Event::Keyboard(keyboard::Event::KeyPressed { + key: keyboard::Key::Character(c), + modifiers, + .. + }) if modifiers.control() && modifiers.shift() => match c.as_str() { + "r" if can_control_device => Some(Message::RebootButtonPressed), + "5" if can_control_device => Some(Message::RefreshButtonPressed), + "a" => Some(Message::AppsPress), + "i" => Some(Message::AboutPressed), + "s" => Some(Message::SettingsPressed), + _ => None, + }, + _ => None, + } + } + + #[allow( + clippy::too_many_lines, + reason = "Root GUI update orchestrates many flows" + )] + fn update(&mut self, msg: Message) -> Task { match msg { Message::LoadDevices(devices_list) => { self.selected_device = match &self.selected_device { @@ -132,19 +180,19 @@ impl Application for UadGui { } Message::AppsPress => { self.view = View::List; - Command::none() + Task::none() } Message::AboutPressed => { self.view = View::About; self.update_state.self_update = SelfUpdateState::default(); - Command::perform( + Task::perform( async move { get_latest_release() }, Message::GetLatestRelease, ) } Message::SettingsPressed => { self.view = View::Settings; - Command::none() + Task::none() } Message::RefreshButtonPressed => { self.apps_view = AppsView::default(); @@ -154,7 +202,7 @@ impl Application for UadGui { self.adb_satisfied, ))); } - Command::perform(get_devices_list(), Message::LoadDevices) + Task::perform(async { get_devices_list() }, Message::LoadDevices) } Message::RebootButtonPressed => { self.apps_view = AppsView::default(); @@ -164,7 +212,7 @@ impl Application for UadGui { }; self.selected_device = None; self.devices_list = vec![]; - Command::perform( + Task::perform( async { adb::ACommand::new().shell(serial).reboot() }, |_| Message::Nothing, ) @@ -240,18 +288,17 @@ impl Application for UadGui { { self.update_state.self_update.status = SelfUpdateStatus::Updating; self.apps_view.loading_state = ListLoadingState::_UpdatingUad; - let bin_name = bin_name().to_owned(); - Command::perform( - download_update_to_temp_file(bin_name, release.clone()), + Task::perform( + download_update_to_temp_file(BIN_NAME, release.clone()), Message::_NewReleaseDownloaded, ) } else { - Command::none() + Task::none() } #[cfg(not(feature = "self-update"))] - Command::none() + Task::none() } - AboutMessage::UrlPressed(_) => Command::none(), + AboutMessage::UrlPressed(_) => Task::none(), } } Message::DeviceSelected(s_device) => { @@ -300,15 +347,15 @@ impl Application for UadGui { { Ok(_) => { if let Err(e) = remove_file(cleanup_path) { - error!("Could not remove temp update file: {}", e); + error!("Could not remove temp update file: {e}"); } std::process::exit(0) } Err(error) => { if let Err(e) = remove_file(cleanup_path) { - error!("Could not remove temp update file: {}", e); + error!("Could not remove temp update file: {e}"); } - error!("Failed to update {NAME}: {}", error); + error!("Failed to update {NAME}: {error}"); } } } else { @@ -319,7 +366,7 @@ impl Application for UadGui { self.update_state.self_update.status = SelfUpdateStatus::Failed; } } - Command::none() + Task::none() } Message::GetLatestRelease(release) => { match release { @@ -328,15 +375,15 @@ impl Application for UadGui { self.update_state.self_update.latest_release = r; } Err(()) => self.update_state.self_update.status = SelfUpdateStatus::Failed, - }; - Command::none() + } + Task::none() } Message::FontLoaded(result) => { if let Err(error) = result { error!("Couldn't load font: {error:?}"); } - Command::none() + Task::none() } Message::ADBSatisfied(result) => { self.adb_satisfied = result; @@ -344,11 +391,11 @@ impl Application for UadGui { self.adb_satisfied, ))) } - Message::Nothing => Command::none(), + Message::Nothing => Task::none(), } } - fn view(&self) -> Element { + fn view(&self) -> Element<'_, Message, Theme> { let navigation_container = nav_menu( &self.devices_list, self.selected_device.clone(), @@ -374,37 +421,55 @@ impl Application for UadGui { column![navigation_container, main_container] .width(Length::Fill) - .align_items(Alignment::Center) + .align_x(Alignment::Center) .into() } + + fn theme(&self) -> Theme { + string_to_theme(&self.settings_view.general.theme) + } } impl UadGui { pub fn start() -> iced::Result { + #[cfg(feature = "img")] let logo: &[u8] = match *OS_COLOR_SCHEME { - // remember to keep `Unspecified` in sync with `src/core/theme` + // remember to keep `Unspecified` in sync with `src/theme` dark_light::Mode::Dark | dark_light::Mode::Unspecified => { - include_bytes!("../../resources/assets/logo-dark.png") + include_bytes!("../../../resources/assets/logo-dark.png") } dark_light::Mode::Light => { - include_bytes!("../../resources/assets/logo-light.png") + include_bytes!("../../../resources/assets/logo-light.png") } }; - Self::run(Settings { - id: Some(String::from(NAME)), - window: Window { + iced::application(UadGui::new, UadGui::update, UadGui::view) + .title(UadGui::title) + .theme(UadGui::theme) + .subscription(UadGui::subscription) + .settings(Settings { + id: Some(String::from(NAME)), + default_text_size: iced::Pixels(16.0), + // HACK: avoid glyph clipping on some systems. Details: + // https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/pull/1337 + #[cfg(target_os = "linux")] + default_font: iced::Font { + family: iced::font::Family::Name("Adwaita Sans"), + ..Default::default() + }, + ..Settings::default() + }) + .window(Window { size: iced::Size { width: 950.0, height: 700.0, }, resizable: true, decorations: true, + #[cfg(feature = "img")] icon: icon::from_file_data(logo, Some(ImageFormat::Png)).ok(), ..iced::window::Settings::default() - }, - default_text_size: iced::Pixels(16.0), - ..Settings::default() - }) + }) + .run() } } diff --git a/crates/uad-gui/src/helpers.rs b/crates/uad-gui/src/helpers.rs new file mode 100644 index 0000000..25c06f1 --- /dev/null +++ b/crates/uad-gui/src/helpers.rs @@ -0,0 +1,23 @@ +use crate::style; +use crate::theme::Theme; +use iced::Element; +use iced::widget::button::Button; + +/// Wrapper function for `iced::widget::button` with padding and style applied +pub fn button_primary<'a, Message>( + content: impl Into>, +) -> Button<'a, Message, Theme> { + iced::widget::button(content) + .padding([5, 10]) + .style(style::Button::Primary) +} + +/// Opens a file picker dialog to select a folder +pub async fn open_folder() -> Result { + rfd::AsyncFileDialog::new() + .set_title("Choose a backup location") + .pick_folder() + .await + .ok_or(uad_core::utils::Error::DialogClosed) + .map(|f| f.path().to_path_buf()) +} diff --git a/crates/uad-gui/src/lib.rs b/crates/uad-gui/src/lib.rs new file mode 100644 index 0000000..ede5da8 --- /dev/null +++ b/crates/uad-gui/src/lib.rs @@ -0,0 +1,11 @@ +#![allow( + clippy::missing_errors_doc, + reason = "Short-circuit doc lint to keep CI green" +)] + +pub mod gui; +pub mod helpers; +pub mod style; +pub mod theme; +pub mod views; +pub mod widgets; diff --git a/src/main.rs b/crates/uad-gui/src/main.rs similarity index 85% rename from src/main.rs rename to crates/uad-gui/src/main.rs index 8d1433a..07608a5 100644 --- a/src/main.rs +++ b/crates/uad-gui/src/main.rs @@ -1,8 +1,5 @@ #![windows_subsystem = "windows"] -#[macro_use] -extern crate log; -use crate::core::utils::setup_uad_dir; use fern::{ FormatCallback, colors::{Color, ColoredLevelConfig}, @@ -10,12 +7,10 @@ use fern::{ use log::Record; use std::sync::LazyLock; use std::{fmt::Arguments, fs::OpenOptions, path::PathBuf}; +use uad_core::utils::setup_uad_dir; -mod core; -mod gui; +use uad_gui::gui::UadGui; -static CONFIG_DIR: LazyLock = - LazyLock::new(|| setup_uad_dir(&dirs::config_dir().expect("Can't detect config dir"))); static CACHE_DIR: LazyLock = LazyLock::new(|| setup_uad_dir(&dirs::cache_dir().expect("Can't detect cache dir"))); @@ -30,16 +25,15 @@ fn main() -> iced::Result { } setup_logger().expect("setup logging"); - gui::UadGui::start() + UadGui::start() } -/// Sets up logging to a new file in `CACHE_DIR/UAD`_{time}.log +/// Sets up logging to a new file in `CACHE_DIR"/uadng.log"` /// Also attaches the terminal on Windows machines /// ''' /// match `setup_logger().expect("Error` setting up logger") /// ''' fn setup_logger() -> Result<(), fern::InitError> { - /// Attach Windows terminal, only on Windows #[cfg(target_os = "windows")] { attach_windows_console(); @@ -69,20 +63,20 @@ fn setup_logger() -> Result<(), fern::InitError> { .create(true) .append(true) .truncate(false) - .open(CACHE_DIR.join(format!("UAD_{}.log", chrono::Local::now().format("%Y%m%d"))))?; + .open(CACHE_DIR.join("uadng.log"))?; let file_dispatcher = fern::Dispatch::new() .format(make_formatter(false)) .level(default_log_level) // Rust compiler makes module names use _ instead of - - .level_for("uad_ng", log::LevelFilter::Debug) + .level_for("uad_gui", log::LevelFilter::Debug) .chain(log_file); let stdout_dispatcher = fern::Dispatch::new() .format(make_formatter(true)) .level(default_log_level) // Rust compiler makes module names use _ instead of - - .level_for("uad_ng", log::LevelFilter::Warn) + .level_for("uad_gui", log::LevelFilter::Warn) .chain(std::io::stdout()); fern::Dispatch::new() diff --git a/crates/uad-gui/src/style.rs b/crates/uad-gui/src/style.rs new file mode 100644 index 0000000..9eeba68 --- /dev/null +++ b/crates/uad-gui/src/style.rs @@ -0,0 +1,776 @@ +#![allow( + non_snake_case, + clippy::trivially_copy_pass_by_ref, + clippy::wildcard_imports, + reason = "Iced style modules use PascalCase and &Theme; wildcard for local convenience" +)] +use crate::theme::{ColorPalette, Theme}; +use iced::widget::{ + button, checkbox, container, overlay, pick_list, radio, scrollable, text, text_editor, + text_input, +}; +use iced::{Background, Border, Color, Shadow}; + +// Implement theming catalogs for our custom `Theme` so generic widgets +// like `Button<'_, Message, Theme, Renderer>` compile under iced 0.13. + +impl button::Catalog for Theme { + type Class<'a> = button::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: button::Status| Button::Primary(t, s)) + } + + fn style( + &self, + class: &::Class<'_>, + status: button::Status, + ) -> button::Style { + (class)(self, status) + } +} + +impl checkbox::Catalog for Theme { + type Class<'a> = checkbox::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: checkbox::Status| CheckBox::SettingsEnabled(t, s)) + } + + fn style( + &self, + class: &::Class<'_>, + status: checkbox::Status, + ) -> checkbox::Style { + (class)(self, status) + } +} + +impl container::Catalog for Theme { + type Class<'a> = container::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme| Container::Background(t)) + } + + fn style(&self, class: &::Class<'_>) -> container::Style { + (class)(self) + } +} + +impl scrollable::Catalog for Theme { + type Class<'a> = scrollable::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: scrollable::Status| Scrollable::Description(t, s)) + } + + fn style( + &self, + class: &::Class<'_>, + status: scrollable::Status, + ) -> scrollable::Style { + (class)(self, status) + } +} + +impl text::Catalog for Theme { + type Class<'a> = text::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme| Text::Default(t)) + } + + fn style(&self, class: &::Class<'_>) -> text::Style { + (class)(self) + } +} + +// Additional catalogs required by Iced 0.13 generic theming + +impl text_input::Catalog for Theme { + type Class<'a> = text_input::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: text_input::Status| { + let p = t.palette(); + + let active = text_input::Style { + background: Background::Color(p.base.foreground), + border: Border { + color: p.base.foreground, + width: 0.0, + radius: 5.0.into(), + }, + icon: Color { + a: 0.5, + ..p.normal.primary + }, + placeholder: p.normal.surface, + value: p.bright.primary, + selection: p.normal.primary, + }; + + let focused = text_input::Style { + background: Background::Color(p.base.foreground), + border: Border { + color: Color { + a: 0.5, + ..p.normal.primary + }, + width: 1.0, + radius: 2.0.into(), + }, + icon: Color { + a: 0.5, + ..p.normal.primary + }, + placeholder: p.normal.surface, + value: p.bright.primary, + selection: p.normal.primary, + }; + + let disabled = text_input::Style { + background: Background::Color(p.base.background), + border: Border { + color: Color { + a: 0.5, + ..p.base.foreground + }, + width: 1.0, + radius: 2.0.into(), + }, + icon: Color { + a: 0.5, + ..p.base.foreground + }, + placeholder: p.normal.surface, + value: p.bright.primary, + selection: p.normal.primary, + }; + + match s { + text_input::Status::Active => active, + text_input::Status::Focused { .. } | text_input::Status::Hovered => focused, + text_input::Status::Disabled => disabled, + } + }) + } + + fn style( + &self, + class: &::Class<'_>, + status: text_input::Status, + ) -> text_input::Style { + (class)(self, status) + } +} + +impl pick_list::Catalog for Theme { + type Class<'a> = pick_list::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: pick_list::Status| { + let p = t.palette(); + let border_color = match s { + pick_list::Status::Hovered => p.normal.primary, + _ => Color { + a: 0.5, + ..p.normal.primary + }, + }; + pick_list::Style { + text_color: p.bright.surface, + placeholder_color: p.bright.surface, + handle_color: p.bright.surface, + background: Background::Color(p.base.background), + border: Border { + color: border_color, + width: 1.0, + radius: 2.0.into(), + }, + } + }) + } + + fn style( + &self, + class: &::Class<'_>, + status: pick_list::Status, + ) -> pick_list::Style { + (class)(self, status) + } +} + +impl overlay::menu::Catalog for Theme { + type Class<'a> = overlay::menu::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme| { + let p = t.palette(); + overlay::menu::Style { + text_color: p.bright.surface, + background: p.base.background.into(), + border: Border { + color: p.base.background, + width: 1.0, + radius: 2.0.into(), + }, + selected_text_color: p.bright.surface, + selected_background: p.normal.primary.into(), + shadow: Shadow::default(), + } + }) + } + + fn style(&self, class: &::Class<'_>) -> overlay::menu::Style { + (class)(self) + } +} + +impl radio::Catalog for Theme { + type Class<'a> = radio::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, s: radio::Status| { + let p = t.palette(); + let active = radio::Style { + background: Color::TRANSPARENT.into(), + dot_color: p.bright.primary, + border_width: 1.0, + border_color: p.bright.primary, + text_color: None, + }; + + match s { + radio::Status::Active { .. } => active, + radio::Status::Hovered { .. } => radio::Style { + border_width: 2.0, + ..active + }, + } + }) + } + + fn style( + &self, + class: &::Class<'_>, + status: radio::Status, + ) -> radio::Style { + (class)(self, status) + } +} + +impl text_editor::Catalog for Theme { + type Class<'a> = text_editor::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme, _s: text_editor::Status| { + let p = t.palette(); + text_editor::Style { + background: Background::Color(p.base.foreground), + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 0.0.into(), + }, + placeholder: p.normal.surface, + value: p.bright.surface, + selection: Color { + a: 0.3, + ..p.normal.primary + }, + } + }) + } + + fn style( + &self, + class: &::Class<'_>, + status: text_editor::Status, + ) -> text_editor::Style { + (class)(self, status) + } +} + +// Rule styling for custom Theme (needed by vertical_rule) +impl iced::widget::rule::Catalog for Theme { + type Class<'a> = iced::widget::rule::StyleFn<'a, Theme>; + + fn default<'a>() -> ::Class<'a> { + Box::new(|t: &Theme| { + let p = t.palette(); + iced::widget::rule::Style { + color: p.bright.surface, + radius: 2.0.into(), + fill_mode: iced::widget::rule::FillMode::Full, + snap: true, + } + }) + } + + fn style( + &self, + class: &::Class<'_>, + ) -> iced::widget::rule::Style { + (class)(self) + } +} + +pub mod Container { + use super::*; + + #[allow(dead_code, reason = "Used by other themes or future styles")] + #[must_use] + pub fn Invisible(_: &Theme) -> container::Style { + container::Style::default() + } + + #[must_use] + pub fn Frame(theme: &Theme) -> container::Style { + let p = theme.palette(); + container::Style { + background: Some(Background::Color(p.base.foreground)), + text_color: Some(p.bright.surface), + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + #[must_use] + pub fn BorderedFrame(theme: &Theme) -> container::Style { + let p = theme.palette(); + container::Style { + background: Some(Background::Color(p.base.foreground)), + text_color: Some(p.bright.surface), + border: Border { + color: p.normal.error, + width: 1.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + #[allow(dead_code, reason = "Currently unused in some views")] + #[must_use] + pub fn Tooltip(theme: &Theme) -> container::Style { + let p = theme.palette(); + container::Style { + background: Some(Background::Color(p.base.foreground)), + text_color: Some(p.bright.surface), + border: Border { + color: p.normal.primary, + width: 1.0, + radius: 8.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + #[must_use] + pub fn Background(theme: &Theme) -> container::Style { + let p = theme.palette(); + container::Style { + background: Some(Background::Color(p.base.background)), + text_color: Some(p.bright.surface), + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } +} + +pub mod Button { + use super::*; + + #[allow( + dead_code, + reason = "Helper used by multiple styles; may be inlined by compiler" + )] + fn base(border_color: Color) -> button::Style { + button::Style { + background: None, + text_color: Color::WHITE, + border: Border { + color: border_color, + width: 1.0, + radius: 2.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + #[must_use] + pub fn Primary(theme: &Theme, status: button::Status) -> button::Style { + let p = theme.palette(); + let mut style = style_active_hover_disabled(p.bright.primary, p.bright.primary, status); + if matches!(status, button::Status::Active | button::Status::Pressed) { + style.background = Some(Background::Color(p.base.foreground)); + } + style + } + + #[allow( + dead_code, + reason = "Alias kept for semantic clarity in some call-sites" + )] + #[must_use] + pub fn SelfUpdate(theme: &Theme, status: button::Status) -> button::Style { + Primary(theme, status) + } + + #[must_use] + pub fn RestorePackage(theme: &Theme, status: button::Status) -> button::Style { + let p = theme.palette(); + let mut style = style_active_hover_disabled(p.bright.secondary, p.bright.secondary, status); + if matches!(status, button::Status::Active | button::Status::Pressed) { + style.background = Some(Background::Color(p.base.foreground)); + } + if matches!(status, button::Status::Disabled) { + style.background = Some(Background::Color(Color { + a: 0.05, + ..p.normal.primary + })); + style.text_color = p.bright.primary; + } + style + } + + #[must_use] + pub fn UninstallPackage(theme: &Theme, status: button::Status) -> button::Style { + let p = theme.palette(); + let mut style = style_active_hover_disabled(p.bright.error, p.bright.error, status); + if matches!(status, button::Status::Active | button::Status::Pressed) { + style.background = Some(Background::Color(p.base.foreground)); + } + style + } + + #[allow( + dead_code, + reason = "Style exposed for disabled state buttons in some contexts" + )] + #[must_use] + pub fn Unavailable(theme: &Theme, status: button::Status) -> button::Style { + UninstallPackage(theme, status) + } + + #[must_use] + pub fn NormalPackage(theme: &Theme, status: button::Status) -> button::Style { + let p = theme.palette(); + match status { + button::Status::Hovered => button::Style { + background: Some(Background::Color(Color { + a: 0.25, + ..p.normal.primary + })), + text_color: p.bright.surface, + border: Border { + color: p.base.background, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + }, + _ => button::Style { + background: Some(Background::Color(p.base.foreground)), + text_color: p.bright.surface, + border: Border { + color: p.base.background, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + }, + } + } + + #[must_use] + pub fn SelectedPackage(theme: &Theme, _status: button::Status) -> button::Style { + let p = theme.palette(); + button::Style { + background: Some(Background::Color(Color { + a: 0.25, + ..p.normal.primary + })), + text_color: p.bright.primary, + border: Border { + color: p.normal.primary, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + #[allow(dead_code, reason = "Used in views where buttons must be invisible")] + #[must_use] + pub fn Hidden(_: &Theme, _: button::Status) -> button::Style { + button::Style { + background: Some(Background::Color(Color::TRANSPARENT)), + text_color: Color::TRANSPARENT, + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + snap: true, + } + } + + fn style_active_hover_disabled( + main: Color, + text: Color, + status: button::Status, + ) -> button::Style { + match status { + button::Status::Active | button::Status::Pressed => button::Style { + background: Some(Background::Color(main)), + text_color: text, + border: Border { + color: Color { a: 0.5, ..main }, + width: 1.0, + radius: 2.0.into(), + }, + shadow: Shadow::default(), + snap: true, + }, + button::Status::Hovered => button::Style { + background: Some(Background::Color(Color { a: 0.25, ..main })), + text_color: text, + border: Border { + color: Color { a: 0.5, ..main }, + width: 1.0, + radius: 2.0.into(), + }, + shadow: Shadow::default(), + snap: true, + }, + button::Status::Disabled => button::Style { + background: Some(Background::Color(Color { a: 0.05, ..main })), + text_color: Color { a: 0.5, ..text }, + border: Border { + color: Color { a: 0.5, ..main }, + width: 1.0, + radius: 2.0.into(), + }, + shadow: Shadow::default(), + snap: true, + }, + } + } +} + +pub mod Scrollable { + use super::*; + + #[allow(dead_code, reason = "Kept for future custom rails variations")] + fn rails(scroller_color: Color) -> (scrollable::Rail, scrollable::Rail) { + let rail = scrollable::Rail { + background: Some(Background::Color(Color::TRANSPARENT)), + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 5.0.into(), + }, + scroller: scrollable::Scroller { + background: Background::Color(scroller_color), + border: Border { + color: Color::TRANSPARENT, + width: 1.0, + radius: 5.0.into(), + }, + }, + }; + (rail, rail) + } + + fn autoscroll(p: ColorPalette) -> scrollable::AutoScroll { + scrollable::AutoScroll { + background: Background::Color(Color { + a: 0.05, + ..p.base.background + }), + border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: 5.0.into(), + }, + shadow: Shadow::default(), + icon: p.bright.surface, + } + } + + #[must_use] + pub fn Description(theme: &Theme, _status: scrollable::Status) -> scrollable::Style { + let p = theme.palette(); + let (v, h) = rails(p.normal.surface); + scrollable::Style { + container: container::Style::default(), + vertical_rail: v, + horizontal_rail: h, + gap: Some(Background::Color(Color::TRANSPARENT)), + auto_scroll: autoscroll(p), + } + } + + #[must_use] + pub fn Packages(theme: &Theme, _status: scrollable::Status) -> scrollable::Style { + let p = theme.palette(); + let (v, h) = rails(p.base.foreground); + scrollable::Style { + container: container::Style::default(), + vertical_rail: v, + horizontal_rail: h, + gap: Some(Background::Color(Color::TRANSPARENT)), + auto_scroll: autoscroll(p), + } + } +} + +pub mod CheckBox { + use super::*; + + #[must_use] + pub fn PackageEnabled(theme: &Theme, _status: checkbox::Status) -> checkbox::Style { + let p = theme.palette(); + checkbox::Style { + background: Background::Color(p.base.background), + icon_color: p.bright.primary, + border: Border { + color: p.base.background, + width: 1.0, + radius: 5.0.into(), + }, + text_color: Some(p.bright.surface), + } + } + + #[must_use] + pub fn PackageDisabled(theme: &Theme, _status: checkbox::Status) -> checkbox::Style { + let p = theme.palette(); + checkbox::Style { + background: Background::Color(Color { + a: 0.55, + ..p.base.background + }), + icon_color: p.bright.primary, + border: Border { + color: p.normal.primary, + width: 1.0, + radius: 5.0.into(), + }, + text_color: Some(p.normal.primary), + } + } + + #[must_use] + pub fn SettingsEnabled(theme: &Theme, _status: checkbox::Status) -> checkbox::Style { + let p = theme.palette(); + checkbox::Style { + background: Background::Color(p.base.background), + icon_color: p.bright.primary, + border: Border { + color: p.bright.primary, + width: 1.0, + radius: 5.0.into(), + }, + text_color: Some(p.bright.surface), + } + } + + #[must_use] + pub fn SettingsDisabled(theme: &Theme, _status: checkbox::Status) -> checkbox::Style { + let p = theme.palette(); + checkbox::Style { + background: Background::Color(p.base.foreground), + icon_color: p.bright.primary, + border: Border { + color: p.normal.primary, + width: 1.0, + radius: 5.0.into(), + }, + text_color: Some(p.bright.surface), + } + } +} + +pub mod Text { + use super::*; + + #[must_use] + pub fn Default(theme: &Theme) -> text::Style { + let _ = theme; + text::Style::default() + } + + #[must_use] + pub fn Ok(theme: &Theme) -> text::Style { + let p = theme.palette(); + text::Style { + color: Some(p.bright.secondary), + } + } + + #[must_use] + pub fn Danger(theme: &Theme) -> text::Style { + let p = theme.palette(); + text::Style { + color: Some(p.bright.error), + } + } + + #[must_use] + pub fn Commentary(theme: &Theme) -> text::Style { + let p = theme.palette(); + text::Style { + color: Some(p.normal.surface), + } + } + + #[allow( + dead_code, + reason = "Convenience factory used by dynamic text coloring" + )] + pub fn Color(c: Color) -> impl Fn(&Theme) -> text::Style { + move |_t: &Theme| text::Style { color: Some(c) } + } +} + +// Unit tests +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_palette() { + let palette = Theme::Dark.palette(); + + assert_ne!(palette.base.background, palette.base.foreground); + assert_ne!(palette.normal.primary, Color::BLACK); + assert_ne!(palette.normal.surface, Color::BLACK); + assert_ne!(palette.bright.primary, Color::BLACK); + // if `LIGHT` then this can be `BLACK` + // https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/pull/730#issuecomment-2525405134 + //assert_ne!(palette.bright.surface, Color::BLACK); + assert_ne!(palette.normal.error, Color::BLACK); + assert_ne!(palette.bright.error, Color::BLACK); + } +} diff --git a/src/core/theme.rs b/crates/uad-gui/src/theme.rs similarity index 69% rename from src/core/theme.rs rename to crates/uad-gui/src/theme.rs index 2c78d7e..e18a428 100644 --- a/src/core/theme.rs +++ b/crates/uad-gui/src/theme.rs @@ -1,4 +1,4 @@ -use dark_light; +use iced::theme::{self, Mode, Palette, Style}; use iced::{Color, color}; use std::sync::LazyLock; @@ -37,7 +37,7 @@ pub struct BaseColors { #[derive(Debug, Clone, Copy)] pub struct NormalColors { pub primary: Color, - #[allow(dead_code)] + #[allow(dead_code, reason = "Reserved for future palette updates")] pub secondary: Color, pub surface: Color, pub error: Color, @@ -149,3 +149,71 @@ impl std::fmt::Display for Theme { ) } } + +/// Converts a string to the GUI's Theme type +#[must_use] +pub fn string_to_theme(theme: &str) -> Theme { + match theme { + "Lupin" => Theme::Lupin, + "Dark" => Theme::Dark, + "Light" => Theme::Light, + _ => Theme::Auto, + } +} + +impl theme::Base for Theme { + fn default(preference: Mode) -> Self { + match preference { + Mode::Light => Self::Light, + Mode::Dark => Self::Dark, + Mode::None => match *OS_COLOR_SCHEME { + dark_light::Mode::Light => Self::Light, + dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark, + }, + } + } + + fn mode(&self) -> Mode { + let resolved = match self { + Self::Auto => match *OS_COLOR_SCHEME { + dark_light::Mode::Light => Self::Light, + dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark, + }, + other => *other, + }; + + match resolved { + Self::Light => Mode::Light, + _ => Mode::Dark, + } + } + + fn base(&self) -> Style { + let p = Self::palette(*self); + Style { + background_color: p.base.background, + text_color: p.bright.surface, + } + } + + fn palette(&self) -> Option { + let p = Self::palette(*self); + Some(Palette { + background: p.base.background, + text: p.bright.surface, + primary: p.normal.primary, + success: p.bright.secondary, + warning: p.normal.surface, + danger: p.normal.error, + }) + } + + fn name(&self) -> &str { + match self { + Self::Dark => "Dark", + Self::Light => "Light", + Self::Lupin => "Lupin", + Self::Auto => "Auto", + } + } +} diff --git a/src/gui/views/about.rs b/crates/uad-gui/src/views/about.rs similarity index 70% rename from src/gui/views/about.rs rename to crates/uad-gui/src/views/about.rs index 8867d96..42cb723 100644 --- a/src/gui/views/about.rs +++ b/crates/uad-gui/src/views/about.rs @@ -1,16 +1,17 @@ -use crate::CACHE_DIR; -use crate::core::adb; -use crate::core::helpers::button_primary; -use crate::core::theme::Theme; -use crate::core::uad_lists::LIST_FNAME; -use crate::core::utils::{NAME, last_modified_date, open_url}; -use crate::gui::{UpdateState, style, widgets::text}; +use crate::helpers::button_primary; +use crate::theme::Theme; +use crate::{gui::UpdateState, style, widgets::text}; use iced::widget::{Space, column, container, row}; use iced::{Alignment, Element, Length, Renderer}; +use log::error; use std::path::PathBuf; +use uad_core::CACHE_DIR; +use uad_core::adb; +use uad_core::uad_lists::LIST_FNAME; +use uad_core::utils::{FULL_NAME, NAME, last_modified_date, open_url}; #[cfg(feature = "self-update")] -use crate::core::update::SelfUpdateStatus; +use uad_core::update::SelfUpdateStatus; #[derive(Default, Debug, Clone)] pub struct About {} @@ -23,15 +24,23 @@ pub enum Message { } impl About { + #[allow( + clippy::unused_self, + reason = "Trait-like shape required by GUI architecture" + )] pub fn update(&mut self, msg: Message) { if let Message::UrlPressed(url) = msg { open_url(url); } // other events are handled by UadGui update() } - pub fn view(&self, update_state: &UpdateState) -> Element { + #[allow( + clippy::unused_self, + reason = "Trait-like shape required by GUI architecture" + )] + pub fn view(&self, update_state: &UpdateState) -> Element<'_, Message, Theme, Renderer> { let about_text = text(format!( - "Universal Android Debloater Next Generation ({NAME}) is a free and open-source community project \naiming at simplifying the removal of pre-installed apps on any Android device." + "{FULL_NAME} ({NAME}) is a free and open-source community project \naiming at simplifying the removal of pre-installed apps on any Android device." )); let descr_container = container(about_text) @@ -76,13 +85,13 @@ impl About { let last_self_update_text = text(self_update_text).style(style::Text::Default); row![uad_version_text, self_update_btn, last_self_update_text,] - .align_items(Alignment::Center) + .align_y(Alignment::Center) .spacing(10) .width(550) }; let uad_list_row = row![uad_list_text, uad_lists_btn, last_update_text,] - .align_items(Alignment::Center) + .align_y(Alignment::Center) .spacing(10) .width(550); @@ -94,34 +103,36 @@ impl About { the numbers will be out of sync! However, the server will still be the "old" version - until the next start + until it's killed */ - let adb_version_text = text( - adb::ACommand::new() - .version() - .map_err(|e| error!("{e}")) - .ok() - // 1st line is the relevant one. - // 2nd could be useful, too - .unwrap_or_default()[0] - // there must be some way to avoid this... - .clone(), - ) + let adb_version_text = text(match adb::ACommand::new().version() { + Ok(s) => s + .lines() + .nth(0) + .unwrap_or_else(|| unreachable!()) + // This allocation is good. + // If it was a ref, the app would hold the entire string + // instead of the relevant slice. + .to_string(), + Err(e) => { + error!("{e}"); + "Couldn't fetch ADB version. Is it installed?".into() + // satisfy `match` by inferring the type of the `Ok` arm + } + }) .width(250); - let adb_version_row = row![adb_version_text] - .align_items(Alignment::Center) - .width(550); + let adb_version_row = row![adb_version_text].align_y(Alignment::Center).width(550); #[cfg(feature = "self-update")] let update_column = column![uad_list_row, self_update_row, adb_version_row]; #[cfg(not(feature = "self-update"))] let update_column = column![uad_list_row, adb_version_row]; - let update_column = update_column.align_items(Alignment::Center).spacing(10); + let update_column = update_column.align_x(Alignment::Center).spacing(10); let update_container = container(update_column) .width(Length::Fill) - .center_x() + .center_x(Length::Fill) .padding(10) .style(style::Container::Frame); @@ -145,14 +156,14 @@ impl About { let row = row![website_btn, wiki_btn, issue_btn, log_btn,].spacing(20); let content = column![ - Space::new(Length::Fill, Length::Shrink), + Space::new().width(Length::Fill).height(Length::Shrink), descr_container, update_container, row, ] .width(Length::Fill) .spacing(20) - .align_items(Alignment::Center); + .align_x(Alignment::Center); container(content) .width(Length::Fill) diff --git a/crates/uad-gui/src/views/list.rs b/crates/uad-gui/src/views/list.rs new file mode 100644 index 0000000..a9792dd --- /dev/null +++ b/crates/uad-gui/src/views/list.rs @@ -0,0 +1,1597 @@ +use crate::helpers::button_primary; +use crate::style; +use crate::theme::Theme; +use crate::widgets::navigation_menu::ICONS; +use log::{error, info, warn}; +use std::path::PathBuf; +use uad_core::config::DeviceSettings; +use uad_core::sync::{AdbError, Phone, User, apply_pkg_state_commands}; +use uad_core::uad_lists::{ + Opposite, PackageHashMap, PackageState, Removal, UadList, UadListState, load_debloat_lists, +}; +use uad_core::utils::{ + EXPORT_FILE_NAME, NAME, export_selection, fetch_packages, matches_search, open_url, +}; + +use crate::views::settings::Settings; +use crate::widgets::modal::Modal; +use crate::widgets::package_row::{Message as RowMessage, PackageRow}; +use crate::widgets::text; +use iced::widget::scrollable::{Direction, Scrollbar}; +use iced::widget::{ + Column, Space, button, checkbox, column, container, pick_list, radio, row, rule, scrollable, + text_editor, text_input, tooltip, +}; +use iced::{Alignment, Element, Length, Renderer, Task, alignment}; + +#[derive(Debug, Default, Clone)] +pub struct PackageInfo { + pub i_user: usize, + pub index: usize, + pub removal: String, + pub before_cross_user_states: Vec<(u16, PackageState)>, +} + +#[derive(Default, Debug, Clone)] +pub enum LoadingState { + DownloadingList, + #[default] + FindingPhones, + LoadingPackages, + _UpdatingUad, + Ready, + RestoringDevice(String), + FailedToUpdate, +} + +#[derive(Default, Debug)] +#[allow(clippy::struct_excessive_bools, reason = "Not a state-machine")] +pub struct List { + pub loading_state: LoadingState, + pub uad_lists: PackageHashMap, + /// packages of all users of the phone + pub phone_packages: Vec>, + /// `phone_packages` indexes of the selected user (= what you see on screen) + filtered_packages: Vec, + /// Vec of `(user_index, pkg_index)` + selected_packages: Vec<(usize, usize)>, + selected_removal: Option, + selected_package_state: Option, + selected_list: Option, + pub selected_user: Option, + all_selected: bool, + pub input_value: String, + description: String, + description_content: text_editor::Content, + selection_modal: bool, + error_modal: Option, + export_modal: bool, + current_package_index: usize, + is_adb_satisfied: bool, + copy_confirmation: bool, + fallback_notifications: Vec, +} + +#[derive(Debug, Clone)] +pub enum Message { + LoadUadList(bool), + LoadPhonePackages((PackageHashMap, UadListState)), + RestoringDevice(Result), + ApplyFilters(Vec>), + DismissFallbackNotifications, + VerifyAndFallbackFinished(VerifyAndFallbackResult), + SearchInputChanged(String), + ToggleAllSelected(bool), + ListSelected(UadList), + UserSelected(User), + RemovalSelected(Removal), + PackageStateSelected(PackageState), + ApplyActionOnSelection, + List(usize, RowMessage), + VerifyAndFallback(Result), + Nothing, + ModalHide, + ModalUserSelected(User), + ModalValidate, + ClearSelectedPackages, + ADBSatisfied(bool), + UpdateFailed, + GoToUrl(PathBuf), + ExportSelection, + SelectionExported(Result), + DescriptionEdit(text_editor::Action), + CopyError(String), + HideCopyConfirmation, +} + +pub struct SummaryEntry { + category: Removal, + discard: u8, + restore: u8, +} + +#[derive(Debug, Clone)] +pub struct VerifyAndFallbackResult { + pub i_user: usize, + pub index: usize, + pub new_state: PackageState, + pub notification: Option, + pub error_modal: Option, +} + +impl From for SummaryEntry { + fn from(category: Removal) -> Self { + Self { + category, + discard: 0, + restore: 0, + } + } +} + +impl List { + pub fn update( + &mut self, + settings: &mut Settings, + selected_device: &mut Phone, + list_update_state: &mut UadListState, + message: Message, + ) -> Task { + match message { + Message::ModalHide => self.on_modal_hide(), + Message::ModalValidate => self.on_modal_validate(settings, selected_device), + Message::RestoringDevice(output) => self.on_restoring_device(output), + Message::LoadUadList(remote) => self.on_load_uad_list(remote, selected_device), + Message::LoadPhonePackages(payload) => { + self.on_load_phone_packages(payload, selected_device, list_update_state) + } + Message::ApplyFilters(packages) => self.on_apply_filters(packages), + Message::DismissFallbackNotifications => self.on_dismiss_fallback_notifications(), + Message::ToggleAllSelected(selected) => { + self.on_toggle_all_selected(selected, settings, selected_device, list_update_state) + } + Message::SearchInputChanged(letter) => self.on_search_input_changed(letter), + Message::ListSelected(list) => self.on_list_selected(list), + Message::RemovalSelected(removal) => self.on_removal_selected(removal), + Message::PackageStateSelected(state) => self.on_package_state_selected(state), + Message::List(i, row_msg) => self.on_list_row(i, &row_msg, settings, selected_device), + Message::ApplyActionOnSelection => self.on_apply_action_on_selection(), + Message::UserSelected(user) => self.on_user_selected(user), + Message::VerifyAndFallback(res) => { + self.on_verify_and_fallback(res, settings, selected_device) + } + Message::VerifyAndFallbackFinished(result) => { + self.on_verify_and_fallback_finished(result) + } + Message::ModalUserSelected(user) => { + self.on_modal_user_selected(user, settings, selected_device, list_update_state) + } + Message::ClearSelectedPackages => self.on_clear_selected_packages(), + Message::ADBSatisfied(result) => self.on_adb_satisfied(result), + Message::UpdateFailed => self.on_update_failed(), + Message::GoToUrl(url) => Self::on_go_to_url(url), + Message::ExportSelection => self.on_export_selection(), + Message::SelectionExported(res) => self.on_selection_exported(res), + Message::Nothing => Task::none(), + Message::DescriptionEdit(action) => self.on_description_edit(action), + Message::CopyError(err) => self.on_copy_error(err), + Message::HideCopyConfirmation => self.on_hide_copy_confirmation(), + } + } + + // Handle verification completion on the UI thread after async work + fn on_verify_and_fallback_finished( + &mut self, + result: VerifyAndFallbackResult, + ) -> Task { + let package = &mut self.phone_packages[result.i_user][result.index]; + if let Some(notification) = result.notification { + self.fallback_notifications.push(notification); + } + if let Some(err) = result.error_modal { + self.error_modal = Some(err); + } + package.state = result.new_state; + package.selected = false; + self.selected_packages + .retain(|&x| x.1 != result.index && x.0 != result.i_user); + Self::filter_package_lists(self); + Task::none() + } + + /// Builds the main view for the app list interface + pub fn view( + &self, + settings: &Settings, + selected_device: &Phone, + ) -> Element<'_, Message, Theme, Renderer> { + match &self.loading_state { + LoadingState::DownloadingList => waiting_view( + &format!("Downloading latest {NAME} lists from GitHub. Please wait..."), + Some(button("No internet?").on_press(Message::LoadUadList(false))), + style::Text::Default, + ), + LoadingState::FindingPhones => { + if self.is_adb_satisfied { + waiting_view("Finding connected devices...", None, style::Text::Default) + } else { + waiting_view( + "ADB is not installed on your system, install ADB and relaunch application.", + Some(button("Read on how to get started.") + .on_press(Message::GoToUrl(PathBuf::from( + "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Getting-started", + )))), + style::Text::Danger, + ) + } + } + LoadingState::LoadingPackages => waiting_view( + "Pulling packages from the device. Please wait...", + None, + style::Text::Default, + ), + LoadingState::_UpdatingUad => waiting_view( + &format!("Updating {NAME}. Please wait..."), + None, + style::Text::Default, + ), + LoadingState::RestoringDevice(device) => waiting_view( + &format!("Restoring device: {device}"), + None, + style::Text::Default, + ), + LoadingState::Ready => self.ready_view(settings, selected_device), + LoadingState::FailedToUpdate => waiting_view( + "Failed to download update", + Some(button("Go back").on_press(Message::LoadUadList(false))), + style::Text::Danger, + ), + } + } + + fn control_panel(&self, selected_device: &Phone) -> Element<'_, Message, Theme, Renderer> { + let search_packages = text_input("Search packages...", &self.input_value) + .width(Length::Fill) + .on_input(Message::SearchInputChanged) + .padding([5, 10]); + + let select_all_checkbox = checkbox(self.all_selected) + .on_toggle(Message::ToggleAllSelected) + .size(20) + .style(style::CheckBox::SettingsEnabled) + .spacing(0); // no label, so remove space entirely + + let col_sel_all = row![ + tooltip( + select_all_checkbox, + if self.all_selected { + "Deselect all" + } else { + "Select all" + }, + tooltip::Position::Top, + ) + .style(style::Container::Tooltip) + .gap(4) + ] + .padding(8); + + let user_picklist = pick_list( + selected_device.user_list.clone(), + self.selected_user, + Message::UserSelected, + ) + .width(85); + + let list_picklist = + pick_list(UadList::ALL, self.selected_list, Message::ListSelected).width(96); + + let package_state_picklist = pick_list( + PackageState::ALL, + self.selected_package_state, + Message::PackageStateSelected, + ) + .width(120); + + let removal_picklist = pick_list( + Removal::ALL, + self.selected_removal, + Message::RemovalSelected, + ) + .width(150); + + row![ + col_sel_all, + search_packages, + user_picklist, + removal_picklist, + package_state_picklist, + list_picklist, + ] + .width(Length::Fill) + .align_y(Alignment::Center) + .spacing(6) + .padding(iced::Padding { + top: 0.0, + right: 16.0, + bottom: 0.0, + left: 0.0, + }) + .into() + } + + #[allow( + clippy::too_many_lines, + reason = "Complex layout; further refactor later" + )] + fn ready_view( + &self, + settings: &Settings, + selected_device: &Phone, + ) -> Element<'_, Message, Theme, Renderer> { + let packages = self + .filtered_packages + .iter() + .fold(column![].spacing(6), |col, &i| { + col.push( + self.phone_packages[self.selected_user.unwrap_or_default().index][i] + .view(settings, selected_device) + .map(move |msg| Message::List(i, msg)), + ) + }); + + let packages_scrollable = scrollable(packages) + .height(Length::FillPortion(6)) + .style(style::Scrollable::Packages); + + let description_scroll = + scrollable(text_editor(&self.description_content).on_action(Message::DescriptionEdit)) + .style(style::Scrollable::Description); + + let description_panel = container(description_scroll) + .padding(6) + .height(Length::FillPortion(2)) + .width(Length::Fill) + .style(style::Container::Frame); + + let review_selection = { + let tmp_widget = text(format!( + "Review selection ({})", + self.selected_packages.len() + )); + if self.selected_packages.is_empty() { + button(tmp_widget).padding([5, 10]) + } else { + button_primary(tmp_widget).on_press(Message::ApplyActionOnSelection) + } + }; + + let mut export_selection = button(text(format!( + "Export current selection ({})", + self.selected_packages.len() + ))) + .padding([5, 10]); + if !self.selected_packages.is_empty() { + export_selection = export_selection + .on_press(Message::ExportSelection) + .style(style::Button::Primary); + } + // lock + let export_selection = export_selection; + + let action_row = row![ + export_selection, + Space::new().width(Length::Fill).height(Length::Shrink), + review_selection + ] + .width(Length::Fill) + .spacing(10) + .align_y(Alignment::Center); + + let unavailable = container( + column![ + text("ADB is not authorized to access this user!").size(20) + .style(style::Text::Danger), + text("The most likely reason is that it is the user of your work profile (also called Secure Folder on Samsung devices). There's really no solution, other than completely disabling your work profile in your device settings.") + .style(style::Text::Commentary) + .align_x(alignment::Horizontal::Center), + ] + .spacing(6) + .align_x(Alignment::Center) + ) + .padding(10) + .center_x(Length::Shrink) + .style(style::Container::BorderedFrame); + + let control_panel = self.control_panel(selected_device); + + // Fallback notifications area + let notifications_area: Element<'_, Message, Theme, Renderer> = + if self.fallback_notifications.is_empty() { + Space::new().into() + } else { + let notification_texts: Vec<_> = self + .fallback_notifications + .iter() + .map(|msg| text(msg).style(style::Text::Commentary).into()) + .collect(); + + container( + column![ + text("Fallback Actions Performed:").style(style::Text::Default), + column(notification_texts).spacing(4), + row![ + Space::new().width(Length::Fill).height(Length::Shrink), + button(text("Dismiss")) + .on_press(Message::DismissFallbackNotifications) + .style(style::Button::Primary) + .padding([4, 10]), + ] + ] + .spacing(6), + ) + .padding(8) + .style(style::Container::BorderedFrame) + .into() + }; + + let content = if selected_device.user_list.is_empty() + || match self.selected_user { + Some(u) => !self.phone_packages[u.index].is_empty(), + // If no user has been selected, + // then it could be considered as "equivalent" + // to the case where the `user_list` is empty? + // However, this is inconsistent, + // because other parts of the code simply use a `default` `User`. + None => true, + } { + column![ + control_panel, + notifications_area, + packages_scrollable, + description_panel, + action_row, + ] + } else { + column![ + control_panel, + notifications_area, + container(unavailable) + .height(Length::Fill) + .center_y(Length::Fill), + ] + } + .width(Length::Fill) + .spacing(10) + .align_x(Alignment::Center); + + if self.selection_modal { + return Modal::new( + content.padding(10), + self.apply_selection_modal( + selected_device, + settings, + &self.phone_packages[self.selected_user.unwrap_or_default().index], + ), + ) + .on_blur(Message::ModalHide) + .into(); + } + + if self.export_modal { + let title = container(row![text("Success").size(24)].align_y(Alignment::Center)) + .width(Length::Fill) + .style(style::Container::Frame) + .padding([10, 0]) + .center_y(Length::Shrink) + .center_x(Length::Shrink); + + let text_box = row![ + text(format!("Exported current selection into file.\nFile is exported in same directory where {NAME} is located.")).width(Length::Fill), + ].padding(20); + + let file_row = row![text(EXPORT_FILE_NAME).style(style::Text::Commentary)].padding(20); + + let modal_btn_row = row![ + Space::new().width(Length::Fill).height(Length::Shrink), + button(text("Close").width(Length::Shrink)) + .width(Length::Shrink) + .on_press(Message::ModalHide), + Space::new().width(Length::Fill).height(Length::Shrink), + ]; + + let ctn = container(column![title, text_box, file_row, modal_btn_row]) + .height(Length::Shrink) + .width(500) + .padding(10) + .style(style::Container::Frame); + + return Modal::new(content.padding(10), ctn) + .on_blur(Message::ModalHide) + .into(); + } + + if let Some(err) = &self.error_modal { + error_view(err, content, self.copy_confirmation).into() + } else { + container(content).height(Length::Fill).padding(10).into() + } + } + + #[allow( + clippy::too_many_lines, + reason = "Modal construction is verbose by nature" + )] + fn apply_selection_modal( + &self, + device: &Phone, + settings: &Settings, + packages: &[PackageRow], + ) -> Element<'_, Message, Theme, Renderer> { + const PACK_NO_USER_MSG: &str = "`selected_packages` implies a user must be selected"; + + // 5 element slice is cheap + let mut summaries = Removal::CATEGORIES.map(SummaryEntry::from); + for p in packages.iter().filter(|p| p.selected) { + let summary = &mut summaries[p.removal as usize]; + match p.state { + PackageState::Uninstalled | PackageState::Disabled => summary.restore += 1, + _ => summary.discard += 1, + } + } + + let radio_btn_users = device.user_list.iter().filter(|&u| !u.protected).fold( + row![].spacing(10), + |row, &user| { + row.push( + radio( + format!("{}", user.clone()), + user, + self.selected_user, + Message::ModalUserSelected, + ) + .size(24), + ) + }, + ); + + let title_ctn = + container(row![text("Review your selection").size(24)].align_y(Alignment::Center)) + .width(Length::Fill) + .style(style::Container::Frame) + .padding([10, 0]) + .center_y(Length::Shrink) + .center_x(Length::Fill); + + let users_ctn = container(radio_btn_users) + .padding(10) + .center_x(Length::Shrink) + .style(style::Container::Frame); + + let explaination_ctn = container( + row![ + text("The action for the selected user will be applied to all other users") + .style(style::Text::Danger), + tooltip( + text("\u{EA0C}") + .font(ICONS) + .width(22) + .align_x(alignment::Horizontal::Center) + .style(style::Text::Commentary), + "Let's say you choose user 0. If a selected package on user 0\n\ + is set to be uninstalled and if this same package is disabled on user 10,\n\ + then the package on both users will be uninstalled.", + tooltip::Position::Top, + ) + .gap(20) + .padding(10) + .style(style::Container::Tooltip) + ] + .spacing(10), + ) + .center_x(Length::Shrink) + .padding(10) + .style(style::Container::BorderedFrame); + + let modal_btn_row = row![ + button(text("Cancel")).on_press(Message::ModalHide), + Space::new().width(Length::Fill), + button(text("Apply")).on_press(Message::ModalValidate), + ] + .padding(iced::Padding { + top: 0.0, + right: 15.0, + bottom: 10.0, + left: 10.0, + }); + + let recap_view = summaries + .iter() + .fold(column![].spacing(6).width(Length::Fill), |col, r| { + col.push(recap(settings, r)) + }); + + let selected_pkgs_ctn = container( + container( + scrollable( + container( + if self + .selected_packages + .iter() + .any(|s| s.0 == self.selected_user.expect(PACK_NO_USER_MSG).index) + { + self.selected_packages + .iter() + .filter(|s| { + s.0 == self.selected_user.expect(PACK_NO_USER_MSG).index + }) + .fold( + column![].spacing(6).width(Length::Shrink), + |col, selection| { + col.push( + row![ + row![text( + self.phone_packages[selection.0][selection.1] + .removal + .to_string() + )] + .width(120), + row![text( + self.phone_packages[selection.0][selection.1] + .list + .to_string() + )] + .width(55), + row![text( + self.phone_packages[selection.0][selection.1] + .name + .clone() + ),] + .width(540), + row![match self.phone_packages[selection.0] + [selection.1] + .state + { + PackageState::Enabled => + if settings.device.disable_mode { + text("Disable") + .style(style::Text::Danger) + } else { + text("Uninstall") + .style(style::Text::Danger) + }, + PackageState::Disabled => + text("Enable").style(style::Text::Ok), + PackageState::Uninstalled => + text("Restore").style(style::Text::Ok), + PackageState::All => text("Impossible") + .style(style::Text::Danger), + },] + .width(70), + ] + .width(Length::Shrink) + .spacing(20), + ) + }, + ) + } else { + column![text("No packages selected for this user")] + .align_x(Alignment::Center) + .width(Length::Fill) + }, + ) + .padding(10) + .width(Length::Shrink) + .style(style::Container::Invisible), + ) + .direction(Direction::Both { + vertical: Scrollbar::default(), + horizontal: Scrollbar::default(), + }) + .style(style::Scrollable::Description), + ) + .width(Length::Fill) + .style(style::Container::Frame), + ) + .width(Length::Fill) + .max_height(150) + .padding([0, 10]); + + container( + if device.user_list.iter().filter(|&u| !u.protected).count() > 1 + && settings.device.multi_user_mode + { + column![ + title_ctn, + users_ctn, + row![explaination_ctn].padding([0, 10]), + container(recap_view).padding(10), + selected_pkgs_ctn, + modal_btn_row, + ] + .spacing(10) + .align_x(Alignment::Center) + } else if !settings.device.multi_user_mode { + column![ + title_ctn, + users_ctn, + container(recap_view).padding(10), + selected_pkgs_ctn, + modal_btn_row, + ] + .spacing(10) + .align_x(Alignment::Center) + } else { + column![ + title_ctn, + container(recap_view).padding(10), + selected_pkgs_ctn, + modal_btn_row, + ] + .spacing(10) + .align_x(Alignment::Center) + }, + ) + .width(900) + .height(Length::Shrink) + .max_height(700) + .style(style::Container::Background) + .into() + } + + fn filter_package_lists(&mut self) { + let list_filter: UadList = self.selected_list.expect("UAD-list type must be selected"); + let package_filter: PackageState = self + .selected_package_state + .expect("pack-state must be selected"); + let removal_filter: Removal = self + .selected_removal + .expect("removal recommendation must be selected"); + + self.filtered_packages = self.phone_packages + [self.selected_user.expect("User must be selected").index] + .iter() + // we must filter the indices associated with pack-rows, + // that's why `enumerate` is before `filter`. + .enumerate() + .filter(|(_, p)| { + (list_filter == UadList::All || p.list == list_filter) + && (package_filter == PackageState::All || p.state == package_filter) + && (removal_filter == Removal::All || p.removal == removal_filter) + && (self.input_value.is_empty() + || matches_search(&p.name, &self.input_value, Some(&p.description))) + }) + .map(|(i, _)| i) + .collect(); + } + + #[expect(clippy::unused_async, reason = "1 call-site")] + async fn load_packages>( + uad_list: PackageHashMap, + device_serial: S, + user_list: Vec, + ) -> Vec> { + let serial = device_serial.as_ref(); + if user_list.len() <= 1 { + vec![ + fetch_packages(&uad_list, serial, None) + .into_iter() + .map(PackageRow::from) + .collect(), + ] + } else { + user_list + .iter() + .map(|user| { + fetch_packages(&uad_list, serial, Some(user.id)) + .into_iter() + .map(PackageRow::from) + .collect() + }) + .collect() + } + } + + #[expect(clippy::unused_async, reason = "1 call-site")] + async fn init_apps_view(remote: bool, phone: Phone) -> (PackageHashMap, UadListState) { + let uad_lists = load_debloat_lists(remote); + match uad_lists { + Ok(list) => { + if phone.adb_id.is_empty() { + warn!("AppsView ready but no phone found"); + } + (list, UadListState::Done) + } + Err(local_list) => { + error!( + "Error loading remote debloat list for the phone. Fallback to embedded (and outdated) list" + ); + (local_list, UadListState::Failed) + } + } + } + + // === Split handlers to keep update short === + fn on_modal_hide(&mut self) -> Task { + self.selection_modal = false; + self.error_modal = None; + self.export_modal = false; + Task::none() + } + + fn on_modal_validate( + &mut self, + settings: &Settings, + selected_device: &mut Phone, + ) -> Task { + self.fallback_notifications.clear(); + let mut commands = vec![]; + self.selected_packages.sort_unstable(); + self.selected_packages.dedup(); + for selection in &self.selected_packages { + commands.append(&mut build_action_pkg_commands( + &self.phone_packages, + selected_device, + &settings.device, + *selection, + )); + } + self.selection_modal = false; + Task::batch(commands) + } + + fn on_restoring_device(&mut self, output: Result) -> Task { + let i_user = self.selected_user.unwrap_or_default().index; + if let Ok(p) = output { + self.loading_state = + LoadingState::RestoringDevice(self.phone_packages[i_user][p.index].name.clone()); + } else { + self.loading_state = LoadingState::RestoringDevice("Error [TODO]".to_string()); + } + Task::none() + } + + fn on_load_uad_list(&mut self, remote: bool, selected_device: &Phone) -> Task { + info!("{:-^65}", "-"); + info!( + "ANDROID_SDK: {} | DEVICE: {}", + selected_device.android_sdk, selected_device.model + ); + info!("{:-^65}", "-"); + self.loading_state = LoadingState::DownloadingList; + Task::perform( + Self::init_apps_view(remote, selected_device.clone()), + Message::LoadPhonePackages, + ) + } + + fn on_load_phone_packages( + &mut self, + payload: (PackageHashMap, UadListState), + selected_device: &Phone, + list_update_state: &mut UadListState, + ) -> Task { + let (uad_list, list_state) = payload; + self.loading_state = LoadingState::LoadingPackages; + self.uad_lists.clone_from(&uad_list); + *list_update_state = list_state; + Task::perform( + Self::load_packages( + uad_list, + selected_device.adb_id.clone(), + selected_device.user_list.clone(), + ), + Message::ApplyFilters, + ) + } + + fn on_apply_filters(&mut self, packages: Vec>) -> Task { + let i_user = self.selected_user.unwrap_or_default().index; + self.phone_packages = packages; + self.filtered_packages = (0..self.phone_packages[i_user].len()).collect(); + self.selected_removal = Some(Removal::Recommended); + self.selected_package_state = Some(PackageState::Enabled); + self.selected_list = Some(UadList::All); + self.selected_user = Some(User::default()); + self.fallback_notifications.clear(); + Self::filter_package_lists(self); + self.loading_state = LoadingState::Ready; + Task::none() + } + + fn on_toggle_all_selected( + &mut self, + selected: bool, + settings: &mut Settings, + selected_device: &mut Phone, + list_update_state: &mut UadListState, + ) -> Task { + let i_user = self.selected_user.unwrap_or_default().index; + for i in self.filtered_packages.clone() { + if self.phone_packages[i_user][i].selected != selected { + #[expect(unused_must_use, reason = "side-effect")] + self.update( + settings, + selected_device, + list_update_state, + Message::List(i, RowMessage::ToggleSelection(selected)), + ); + } + } + self.all_selected = selected; + Task::none() + } + + fn on_search_input_changed(&mut self, letter: String) -> Task { + self.input_value = letter; + Self::filter_package_lists(self); + Task::none() + } + + fn on_list_selected(&mut self, list: UadList) -> Task { + self.selected_list = Some(list); + Self::filter_package_lists(self); + Task::none() + } + + fn on_package_state_selected(&mut self, package_state: PackageState) -> Task { + self.selected_package_state = Some(package_state); + Self::filter_package_lists(self); + Task::none() + } + + fn on_removal_selected(&mut self, removal: Removal) -> Task { + self.selected_removal = Some(removal); + Self::filter_package_lists(self); + Task::none() + } + + fn on_list_row( + &mut self, + i_package: usize, + row_message: &RowMessage, + settings: &Settings, + selected_device: &mut Phone, + ) -> Task { + let i_user = self.selected_user.unwrap_or_default().index; + #[expect(unused_must_use, reason = "side-effect")] + { + self.phone_packages[i_user][i_package] + .update(row_message) + .map(move |row_message| Message::List(i_package, row_message)); + } + + let package = &mut self.phone_packages[i_user][i_package]; + + match *row_message { + RowMessage::ToggleSelection(toggle) => { + if package.removal == Removal::Unsafe && !settings.general.expert_mode { + package.selected = false; + return Task::none(); + } + + if settings.device.multi_user_mode { + for u in selected_device.user_list.iter().filter(|&u| !u.protected) { + if let Some(pkg) = self + .phone_packages + .get_mut(u.index) + .and_then(|pkgs| pkgs.get_mut(i_package)) + { + pkg.selected = toggle; + if toggle && !self.selected_packages.contains(&(u.index, i_package)) { + self.selected_packages.push((u.index, i_package)); + } + } + } + if !toggle { + self.selected_packages.retain(|&x| x.1 != i_package); + } + } else { + package.selected = toggle; + if toggle { + if !self.selected_packages.contains(&(i_user, i_package)) { + self.selected_packages.push((i_user, i_package)); + } + } else { + self.selected_packages + .retain(|&x| x.1 != i_package || x.0 != i_user); + } + } + Task::none() + } + RowMessage::ActionPressed => { + self.fallback_notifications.clear(); + self.phone_packages[i_user][i_package].selected = true; + Task::batch(build_action_pkg_commands( + &self.phone_packages, + selected_device, + &settings.device, + (i_user, i_package), + )) + } + RowMessage::PackagePressed => { + self.description = package.clone().description; + self.description_content = text_editor::Content::with_text(&package.description); + package.current = true; + if self.current_package_index != i_package { + self.phone_packages[i_user][self.current_package_index].current = false; + } + self.current_package_index = i_package; + Task::none() + } + } + } + + fn on_apply_action_on_selection(&mut self) -> Task { + self.selection_modal = true; + Task::none() + } + + fn on_user_selected(&mut self, user: User) -> Task { + self.selected_user = Some(user); + self.fallback_notifications.clear(); + self.filtered_packages = (0..self.phone_packages[user.index].len()).collect(); + Self::filter_package_lists(self); + Task::none() + } + + #[allow( + clippy::too_many_lines, + reason = "Complex verification and fallback logic" + )] + //this functions matches the adb command to two types, when it is a soft issue and when it is a hard issue + // soft issue: utilizes core::sync::attempt_fallback in the case the state that wanted to be changed wasn't in fact changed + // hard issue: does basically nothing in most cases FIXME, besides handling enabling packages. + // also this really should be refactored, these are gigantic code blocks + fn on_verify_and_fallback( + &mut self, + res: Result, + settings: &Settings, + selected_device: &Phone, + ) -> Task { + match res { + Ok(p) => { + // Snapshot minimal info to move into background task + let i_user = p.i_user; + let index = p.index; + let pkg_name = self.phone_packages[i_user][index].name.clone(); + let current_state = self.phone_packages[i_user][index].state; + let wanted_state = current_state.opposite(settings.device.disable_mode); + let before_cross_user_states = p.before_cross_user_states.clone(); + let device = selected_device.clone(); + let user_id = device.user_list[i_user].id; + + // Offload verification + potential fallback to background + Task::perform( + async move { + // Blocking ADB calls happen here (off UI thread) + let actual_state_opt = uad_core::sync::verify_package_state( + &pkg_name, + device.adb_id.as_str(), + Some(user_id), + ); + + match actual_state_opt { + Some(actual_state) if actual_state == wanted_state => { + // Check cross-user behavior + let error_modal = uad_core::sync::detect_cross_user_behavior( + &pkg_name, + device.adb_id.as_str(), + user_id, + wanted_state, + actual_state, + &device, + &before_cross_user_states, + ) + .map(|notification| { + format!( + "Cross-User Behavior Detected:\n\n{notification}\n\n\ + This is unusual behavior that may be specific to your device manufacturer (OEM). \ + The package state has been successfully changed on the target user." + ) + }); + + VerifyAndFallbackResult { + i_user, + index, + new_state: wanted_state, + notification: None, + error_modal, + } + } + actual_state_opt => { + // Package doesn't exist (None) or has wrong state - try fallback + let actual_state = + actual_state_opt.unwrap_or(PackageState::Uninstalled); + // Create CorePackage for fallback + let core_package = uad_core::sync::CorePackage { + name: pkg_name.clone(), + description: String::new(), + removal: Removal::All, + state: current_state, + list: UadList::Unlisted, + }; + let fallback_result = uad_core::sync::attempt_fallback( + &core_package, + wanted_state, + actual_state, + device.user_list[i_user], + &device, + ); + + let state_description = match actual_state_opt { + Some(PackageState::Uninstalled) => "remains uninstalled", + Some(PackageState::Disabled) => "was disabled", + Some(PackageState::Enabled) => "was enabled", + Some(PackageState::All) => { + "unexpected state (error determining state)" + } + None => "does not exist on device", + }; + + let (notification, new_state) = match fallback_result { + Ok(fallback_action) => ( + Some(format!( + "Package '{pkg_name}' was {} but {} instead. Fallback: {fallback_action}", + match wanted_state { + PackageState::Uninstalled => "uninstalled", + PackageState::Disabled => "disabled", + PackageState::Enabled => "enabled", + PackageState::All => "modified", + }, + state_description + )), + actual_state, + ), + Err(err) => ( + Some(format!( + "Package '{pkg_name}' verification failed: {err}" + )), + current_state, // no change if fallback failed + ), + }; + + VerifyAndFallbackResult { + i_user, + index, + new_state, + notification, + error_modal: None, + } + } + } + }, + Message::VerifyAndFallbackFinished, + ) + } + + //this is an example of how errors should be done, this is hard to implement however. + // Err(AdbError::SecurityException(err)) => { + + // } + //FIXME: this has to be changed as soon as possible, generic errors are bad practice + // keep in mind most solutions to hard errors like this are going to be hacky + // and weird. + Err(AdbError::Generic(err)) => { + // this is such a hacky solution + if err.contains("Shell cannot change component state") { + // look for the "pm enable --user " to get the command + if let Some(start_index) = err.find("pm enable --user ") { + // slice the string starting from the end of the prefix + let remainder = &err[start_index + "pm enable --user ".len()..]; + // split by whitespace to get the arguments: [ID, PACKAGE, ...] + let parts: Vec<&str> = remainder.split_whitespace().collect(); + + if parts.len() >= 2 { + let user_id_str = parts[0]; + let pkg_name_str = parts[1]; + + let found_user = selected_device + .user_list + .iter() + .enumerate() + .find(|(_, u)| u.id.to_string() == user_id_str); + + if let Some((i_user, user_ref)) = found_user { + // find the package index + let found_pkg = self.phone_packages[i_user] + .iter() + .enumerate() + .find(|(_, p)| p.name == pkg_name_str); + + if let Some((index, _)) = found_pkg { + let user = *user_ref; + let device = selected_device.clone(); + let pkg_name = pkg_name_str.to_string(); + + // fallback task + return Task::perform( + async move { + let temp_pkg = uad_core::sync::CorePackage { + name: pkg_name.clone(), + description: String::new(), + removal: Removal::All, + state: PackageState::Disabled, + list: UadList::Unlisted, + }; + + // get uninstall command + let uninstall_cmds = + uad_core::sync::apply_pkg_state_commands( + &temp_pkg, + PackageState::Uninstalled, + user, + &device, + ); + + if let Some(cmd) = uninstall_cmds.first() { + let _ = uad_core::sync::run_adb_shell_action( + &device.adb_id, + cmd, + ); + } + + // reinstall/enable + let temp_pkg_uninstalled = + uad_core::sync::CorePackage { + name: pkg_name.clone(), + description: String::new(), + removal: Removal::All, + state: PackageState::Uninstalled, + list: UadList::Unlisted, + }; + + let enable_cmds = + uad_core::sync::apply_pkg_state_commands( + &temp_pkg_uninstalled, + PackageState::Enabled, + user, + &device, + ); + + // lets enable the new package + if let Some(cmd) = enable_cmds.first() { + let _ = uad_core::sync::run_adb_shell_action( + &device.adb_id, + cmd, + ); + } + + //verifies the final state for thread confirmation + let actual_state = + uad_core::sync::verify_package_state( + &pkg_name, + &device.adb_id, + Some(user.id), + ) + .unwrap_or(PackageState::Uninstalled); + VerifyAndFallbackResult { + i_user, + index, + new_state: actual_state, + notification: Some(format!( + "Attempted recovery for {pkg_name}" + )), + error_modal: None, + } + }, + Message::VerifyAndFallbackFinished, + ); + } + } + } + } + } + + // Fallthrough: default error handling if parsing failed or unrelated error + self.error_modal = Some(err); + Task::none() + } + } + } + + fn on_modal_user_selected( + &mut self, + user: User, + settings: &mut Settings, + selected_device: &mut Phone, + list_update_state: &mut UadListState, + ) -> Task { + self.selected_user = Some(user); + self.update( + settings, + selected_device, + list_update_state, + Message::UserSelected(user), + ) + } + + fn on_clear_selected_packages(&mut self) -> Task { + self.selected_packages = Vec::new(); + Task::none() + } + + fn on_adb_satisfied(&mut self, result: bool) -> Task { + self.is_adb_satisfied = result; + Task::none() + } + + fn on_update_failed(&mut self) -> Task { + self.loading_state = LoadingState::FailedToUpdate; + Task::none() + } + + fn on_go_to_url(url: PathBuf) -> Task { + open_url(url); + Task::none() + } + + fn on_export_selection(&mut self) -> Task { + let i_user = self.selected_user.unwrap_or_default().index; + let package_names: Vec = self.phone_packages[i_user] + .iter() + .filter(|p| p.selected) + .map(|p| p.name.clone()) + .collect(); + Task::perform( + async move { export_selection(&package_names) }, + Message::SelectionExported, + ) + } + + fn on_selection_exported(&mut self, export: Result) -> Task { + match export { + Ok(_) => self.export_modal = true, + Err(err) => error!("Failed to export current selection: {err:?}"), + } + Task::none() + } + + fn on_description_edit(&mut self, action: text_editor::Action) -> Task { + match action { + text_editor::Action::Scroll { lines: _ } | text_editor::Action::Edit(_) => {} + _ => { + self.description_content.perform(action); + } + } + Task::none() + } + + fn on_copy_error(&mut self, err: String) -> Task { + self.copy_confirmation = true; + Task::batch(vec![ + iced::clipboard::write::(err), + Task::perform( + // intentional delay + async { std::thread::sleep(std::time::Duration::from_secs(1)) }, + |()| Message::HideCopyConfirmation, + ), + ]) + } + + fn on_hide_copy_confirmation(&mut self) -> Task { + self.copy_confirmation = false; + Task::none() + } +} + +impl List { + fn on_dismiss_fallback_notifications(&mut self) -> Task { + self.fallback_notifications.clear(); + Task::none() + } +} +fn error_view<'a>( + error: &'a str, + content: Column<'a, Message, Theme, Renderer>, + copy_confirmation: bool, +) -> Modal<'a, Message, Theme, Renderer> { + let title_ctn = container( + row![text("Failed to perform ADB operation").size(24)].align_y(Alignment::Center), + ) + .width(Length::Fill) + .style(style::Container::Frame) + .padding([10, 0]) + .center_y(Length::Shrink) + .center_x(Length::Shrink); + + let modal_btn_row = row![ + button( + text(if copy_confirmation { + "Copied!" + } else { + "Copy error" + }) + .width(Length::Fill) + .align_x(alignment::Horizontal::Center), + ) + .width(Length::Fill) + .on_press_maybe(if copy_confirmation { + None + } else { + Some(Message::CopyError(error.to_string())) + }) + .style(style::Button::Primary), + button( + text("Close") + .width(Length::Fill) + .align_x(alignment::Horizontal::Center), + ) + .width(Length::Fill) + .on_press(Message::ModalHide) + ] + .padding(iced::Padding { + top: 10.0, + right: 0.0, + bottom: 0.0, + left: 0.0, + }); + + let text_box = scrollable(text(error).width(Length::Fill)).height(400); + + let ctn = container(column![title_ctn, text_box, modal_btn_row]) + .height(Length::Shrink) + .max_height(700) + .padding(10) + .style(style::Container::Frame); + + Modal::new(content, ctn).on_blur(Message::ModalHide) +} + +fn waiting_view<'a>( + displayed_text: &(impl ToString + ?Sized), + btn: Option>, + text_style: impl Fn(&Theme) -> iced::widget::text::Style + 'a, +) -> Element<'a, Message, Theme, Renderer> { + let col = column![] + .spacing(10) + .align_x(Alignment::Center) + .push(text(displayed_text.to_string()).style(text_style).size(20)); + + let col = match btn { + Some(btn) => col.push(btn.style(style::Button::Primary).padding([5, 10])), + None => col, + }; + + container(col) + .width(Length::Fill) + .height(Length::Fill) + .center_y(Length::Fill) + .center_x(Length::Fill) + .style(style::Container::Frame) + .into() +} + +fn build_action_pkg_commands( + packages: &[Vec], + device: &Phone, + settings: &DeviceSettings, + selection: (usize, usize), +) -> Vec> { + let pkg = &packages[selection.0][selection.1]; + let wanted_state = pkg.state.opposite(settings.disable_mode); + + let mut commands = vec![]; + for u in device.user_list.iter().filter(|&&u| { + !u.protected + && packages + .get(u.index) + .and_then(|user_pkgs| user_pkgs.get(selection.1)) + .is_some_and(|row_pkg| { + // Only apply to users where package is explicitly selected + // OR if multi_user_mode is enabled AND this is the initiating user + row_pkg.selected || (settings.multi_user_mode && u.index == selection.0) + }) + }) { + let u_pkg = &packages[u.index][selection.1]; + let wanted_state = if settings.multi_user_mode { + wanted_state + } else { + u_pkg.state.opposite(settings.disable_mode) + }; + + let actions = apply_pkg_state_commands(&u_pkg.into(), wanted_state, *u, device); + + for (j, action) in actions.into_iter().enumerate() { + let p_info = PackageInfo { + i_user: u.index, + index: selection.1, + removal: pkg.removal.to_string(), + // Will be filled asynchronously before running the adb action + before_cross_user_states: vec![], + }; + // Clone data before async block to avoid borrowing issues + let device_serial = device.adb_id.clone(); + let package_name = u_pkg.name.clone(); + let user_id = u.id; + let phone = device.clone(); + // In the end there is only one package state change + // even if we run multiple adb commands + commands.push(Task::perform( + async move { + run_adb_action_with_before_states( + &device_serial, + &action, + p_info, + &package_name, + user_id, + &phone, + ) + }, + if j == 0 { + Message::VerifyAndFallback + } else { + |_| Message::Nothing + }, + )); + } + } + commands +} + +fn run_adb_action_with_before_states( + device_serial: &str, + action: &str, + mut p_info: PackageInfo, + package_name: &str, + target_user_id: u16, + phone: &Phone, +) -> Result { + // Capture before-state in background to avoid blocking UI thread + let before_states = uad_core::sync::capture_cross_user_states( + package_name, + device_serial, + target_user_id, + phone, + ); + p_info.before_cross_user_states = before_states; + // Run the ADB action + uad_core::sync::run_adb_shell_action(device_serial, action)?; + Ok(p_info) +} + +fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message, Theme, Renderer> { + container( + row![ + text(recap.category.to_string()) + .size(19) + .width(Length::FillPortion(1)), + rule::vertical(5), + row![ + if settings.device.disable_mode { + text("Disable").style(style::Text::Danger) + } else { + text("Uninstall").style(style::Text::Danger) + }, + Space::new().width(Length::Fill), + text(recap.discard.to_string()).style(style::Text::Danger) + ] + .width(Length::FillPortion(1)), + rule::vertical(5), + row![ + if settings.device.disable_mode { + text("Enable").style(style::Text::Ok) + } else { + text("Restore").style(style::Text::Ok) + }, + Space::new().width(Length::Fill), + text(recap.restore.to_string()).style(style::Text::Ok) + ] + .width(Length::FillPortion(1)) + ] + .spacing(20) + .padding(iced::Padding { + top: 0.0, + right: 10.0, + bottom: 0.0, + left: 0.0, + }) + .width(Length::Fill) + .align_y(Alignment::Center), + ) + .padding(10) + .width(Length::Fill) + .height(45) + .style(style::Container::Frame) + .into() +} diff --git a/src/gui/views/mod.rs b/crates/uad-gui/src/views/mod.rs similarity index 100% rename from src/gui/views/mod.rs rename to crates/uad-gui/src/views/mod.rs diff --git a/crates/uad-gui/src/views/settings.rs b/crates/uad-gui/src/views/settings.rs new file mode 100644 index 0000000..3a09b80 --- /dev/null +++ b/crates/uad-gui/src/views/settings.rs @@ -0,0 +1,694 @@ +use crate::helpers::{button_primary, open_folder}; +use crate::theme::Theme; +use crate::theme::string_to_theme; +use crate::{ + style, + views::list::{List as AppsView, PackageInfo}, + widgets::modal::Modal, + widgets::navigation_menu::ICONS, + widgets::package_row::PackageRow, + widgets::text, +}; +use chrono; +use iced::widget::{Space, button, checkbox, column, container, pick_list, radio, row, scrollable}; +use iced::{Alignment, Element, Length, Renderer, Task, alignment}; +use log::{debug, error, info}; +use std::path::PathBuf; +use uad_core::{ + config::{BackupSettings, Config, DeviceSettings, GeneralSettings}, + save::{backup_phone, list_available_backup_user, list_available_backups, restore_backup}, + sync::{ + AdbError, CorePackage, Phone, User, get_android_sdk, run_adb_shell_action, + supports_disabling, supports_multi_user, + }, + utils::{DisplayablePath, Error, NAME, export_packages, generate_backup_name, open_url}, +}; + +#[derive(Debug, Clone)] +pub enum PopUpModal { + ExportUninstalled, +} + +#[derive(Debug, Clone)] +pub struct Settings { + pub general: GeneralSettings, + pub device: DeviceSettings, + is_loading: bool, + modal: Option, +} + +impl Default for Settings { + fn default() -> Self { + Self { + general: Config::load_configuration_file().general, + device: DeviceSettings::default(), + is_loading: false, + modal: None, + } + } +} + +#[derive(Debug, Clone)] +pub enum Message { + LoadDeviceSettings, + ExpertMode(bool), + DisableMode(bool), + MultiUserMode(bool), + ApplyTheme(Theme), + UrlPressed(PathBuf), + BackupSelected(DisplayablePath), + BackupDevice, + RestoreDevice, + RestoringDevice(Result), + DeviceBackedUp(Result), + ChooseBackUpFolder, + FolderChosen(Result), + ExportPackages, + PackagesExported(Result), + ModalHide, +} + +impl Settings { + pub fn update( + &mut self, + phone: &Phone, + packages: &[Vec], + nb_running_async_adb_commands: &mut u32, + msg: Message, + selected_user: Option, + ) -> Task { + match msg { + Message::ModalHide => self.handle_modal_hide(), + Message::ExpertMode(toggled) => self.handle_expert_mode(phone, toggled), + Message::DisableMode(toggled) => self.handle_disable_mode(phone, toggled), + Message::MultiUserMode(toggled) => self.handle_multi_user_mode(phone, toggled), + Message::ApplyTheme(theme) => self.handle_apply_theme(phone, theme), + Message::UrlPressed(url) => Self::handle_url_pressed(url), + Message::LoadDeviceSettings => self.handle_load_device_settings(phone), + Message::BackupSelected(d_path) => self.handle_backup_selected(d_path), + Message::BackupDevice => self.handle_backup_device(phone, packages), + Message::DeviceBackedUp(result) => self.handle_device_backed_up(phone, result), + Message::RestoreDevice => { + self.handle_restore_device(phone, packages, nb_running_async_adb_commands) + } + Message::RestoringDevice(_) => Task::none(), + Message::FolderChosen(result) => self.handle_folder_chosen(phone, result), + Message::ChooseBackUpFolder => self.handle_choose_backup_folder(), + Message::ExportPackages => Self::handle_export_packages(selected_user, packages), + Message::PackagesExported(result) => self.handle_packages_exported(result), + } + } + + fn handle_modal_hide(&mut self) -> Task { + self.modal = None; + Task::none() + } + + fn handle_expert_mode(&mut self, _phone: &Phone, toggled: bool) -> Task { + self.general.expert_mode = toggled; + debug!("Config change: {self:?}"); + let mut config = Config::load_configuration_file(); + config.save_device_settings(self.device.clone(), self.general.clone()); + Task::none() + } + + fn handle_disable_mode(&mut self, phone: &Phone, toggled: bool) -> Task { + if supports_disabling(phone) { + self.device.disable_mode = toggled; + debug!("Config change: {self:?}"); + let mut config = Config::load_configuration_file(); + config.save_device_settings(self.device.clone(), self.general.clone()); + } + Task::none() + } + + fn handle_multi_user_mode(&mut self, _phone: &Phone, toggled: bool) -> Task { + self.device.multi_user_mode = toggled; + debug!("Config change: {self:?}"); + let mut config = Config::load_configuration_file(); + config.save_device_settings(self.device.clone(), self.general.clone()); + Task::none() + } + + fn handle_apply_theme(&mut self, _phone: &Phone, theme: Theme) -> Task { + self.general.theme = theme.to_string(); + debug!("Config change: {self:?}"); + let mut config = Config::load_configuration_file(); + config.save_device_settings(self.device.clone(), self.general.clone()); + Task::none() + } + + fn handle_url_pressed(url: PathBuf) -> Task { + open_url(url); + Task::none() + } + + fn handle_load_device_settings(&mut self, phone: &Phone) -> Task { + self.load_device_settings(phone); + Task::none() + } + + fn load_device_settings(&mut self, phone: &Phone) { + let backups = list_available_backups(&self.general.backup_folder.join(&phone.adb_id)); + let backup = BackupSettings { + backups: backups.clone(), + selected: backups.first().cloned(), + users: phone.user_list.clone(), + selected_user: phone.user_list.first().copied(), + backup_state: String::default(), + }; + + match Config::load_configuration_file() + .devices + .iter() + .find(|d| d.device_id == phone.adb_id) + { + Some(device) => { + self.device.clone_from(device); + self.device.backup = backup; + } + None => { + self.device = DeviceSettings { + device_id: phone.adb_id.clone(), + // see FAQ, and GH-issue #1426 + disable_mode: supports_disabling(phone), + multi_user_mode: supports_multi_user(phone), + backup, + }; + } + } + } + + fn handle_backup_selected(&mut self, d_path: DisplayablePath) -> Task { + self.device.backup.selected = Some(d_path.clone()); + self.device.backup.users = list_available_backup_user(d_path); + Task::none() + } + + fn handle_backup_device( + &mut self, + phone: &Phone, + packages: &[Vec], + ) -> Task { + let core_packages: Vec> = packages + .iter() + .map(|user_packages| user_packages.iter().map(CorePackage::from).collect()) + .collect(); + // Avoid capturing &self and &phone in the future; clone owned data first. + let user_list = phone.user_list.clone(); + let device_id = self.device.device_id.clone(); + let packages_owned = core_packages; + Task::perform( + async move { backup_phone(user_list, device_id, &packages_owned) }, + Message::DeviceBackedUp, + ) + } + + fn handle_device_backed_up( + &mut self, + phone: &Phone, + result: Result, + ) -> Task { + match result { + Ok(_) => { + info!("[BACKUP] Backup successfully created"); + self.device.backup.backups = + list_available_backups(&self.general.backup_folder.join(phone.adb_id.clone())); + self.device.backup.selected = self.device.backup.backups.first().cloned(); + } + Err(err) => { + error!("[BACKUP FAILED] Backup creation failed: {err:?}"); + } + } + Task::none() + } + + fn handle_restore_device( + &mut self, + phone: &Phone, + packages: &[Vec], + nb_running_async_adb_commands: &mut u32, + ) -> Task { + let core_packages: Vec> = packages + .iter() + .map(|user_packages| user_packages.iter().map(CorePackage::from).collect()) + .collect(); + match restore_backup(phone, &core_packages, &self.device) { + Ok(restore_result) => { + let mut commands = vec![]; + *nb_running_async_adb_commands = 0; + for p in &restore_result.packages { + let p_info = PackageInfo { + i_user: p.i_user, + index: p.index, + removal: "RESTORE".to_string(), + before_cross_user_states: vec![], + }; + for command in p.commands.clone() { + *nb_running_async_adb_commands += 1; + let p_info_clone = p_info.clone(); + let phone_id = phone.adb_id.clone(); + commands.push(Task::perform( + async move { + run_adb_shell_action(phone_id, command.as_str()) + .map(|_| p_info_clone) + }, + Message::RestoringDevice, + )); + } + } + if restore_result.skipped_count > 0 { + self.device.backup.backup_state = format!( + "Restore completed with {} packages skipped (not found on device)", + restore_result.skipped_count + ); + } else if restore_result.packages.is_empty() { + if get_android_sdk(&phone.adb_id) == 0 { + self.device.backup.backup_state = "Device is not connected".to_string(); + } else { + self.device.backup.backup_state = + "Device state is already restored".to_string(); + } + } else { + self.device.backup.backup_state = "Restore completed successfully".to_string(); + } + info!( + "[RESTORE] Restoring backup {}", + self.device.backup.selected.as_ref().unwrap() + ); + Task::batch(commands) + } + Err(e) => { + self.device.backup.backup_state.clone_from(&e); + error!("{} - {}", self.device.backup.selected.as_ref().unwrap(), e); + Task::none() + } + } + } + + fn handle_folder_chosen( + &mut self, + phone: &Phone, + result: Result, + ) -> Task { + self.is_loading = false; + + if let Ok(path) = result { + self.general.backup_folder = path; + let mut config = Config::load_configuration_file(); + config.save_device_settings(self.device.clone(), self.general.clone()); + self.load_device_settings(phone); + } + Task::none() + } + + fn handle_choose_backup_folder(&mut self) -> Task { + if self.is_loading { + Task::none() + } else { + self.is_loading = true; + Task::perform(open_folder(), Message::FolderChosen) + } + } + + fn handle_export_packages( + selected_user: Option, + packages: &[Vec], + ) -> Task { + let core_packages: Vec> = packages + .iter() + .map(|user_packages| user_packages.iter().map(CorePackage::from).collect()) + .collect(); + Task::perform( + async move { export_packages(selected_user.unwrap_or_default(), &core_packages) }, + Message::PackagesExported, + ) + } + + fn handle_packages_exported(&mut self, result: Result) -> Task { + match result { + Ok(_) => self.modal = Some(PopUpModal::ExportUninstalled), + Err(err) => error!("Failed to export list of uninstalled packages: {err:?}"), + } + Task::none() + } + + pub fn view( + &self, + phone: &Phone, + apps_view: &AppsView, + ) -> Element<'_, Message, Theme, Renderer> { + let content = if phone.adb_id.is_empty() { + self.build_no_device_content() + } else { + self.build_device_content(phone, apps_view) + }; + + if let Some(PopUpModal::ExportUninstalled) = self.modal { + return Self::render_export_modal(content); + } + + container(scrollable(content)) + .padding(10) + .width(Length::Fill) + .height(Length::Fill) + .into() + } + + fn build_no_device_content(&self) -> Element<'_, Message, Theme, Renderer> { + column![ + text("Theme").size(26), + self.theme_container(), + text("General").size(26), + self.general_container(), + text("Current device").size(26), + Self::no_device_container(), + text("Backup / Restore").size(26), + Self::no_device_container(), + ] + .width(Length::Fill) + .spacing(20) + .into() + } + + fn build_device_content( + &self, + phone: &Phone, + apps_view: &AppsView, + ) -> Element<'_, Message, Theme, Renderer> { + column![ + text("Theme").size(26), + self.theme_container(), + text("General").size(26), + self.general_container(), + text("Current device").size(26), + Self::warning_container(phone), + self.device_specific_container(phone), + text("Backup / Restore").size(26), + self.backup_restore_container(phone, apps_view), + ] + .width(Length::Fill) + .spacing(20) + .into() + } + + fn theme_container(&self) -> Element<'_, Message, Theme, Renderer> { + let radio_btn_theme = Theme::ALL + .iter() + .fold(row![].spacing(10), |column, option| { + column.push( + radio( + format!("{}", option.clone()), + *option, + Some(string_to_theme(&self.general.theme)), + Message::ApplyTheme, + ) + .size(24), + ) + }); + + container(radio_btn_theme) + .padding(10) + .width(Length::Fill) + .height(Length::Shrink) + .style(style::Container::Frame) + .into() + } + + fn general_container(&self) -> Element<'_, Message, Theme, Renderer> { + let expert_mode_checkbox = checkbox(self.general.expert_mode) + .label("Allow to uninstall packages marked as \"unsafe\" (I KNOW WHAT I AM DOING)") + .on_toggle(Message::ExpertMode) + .size(20) + .style(style::CheckBox::SettingsEnabled); + + let expert_mode_descr = + text("Most unsafe packages are known to bootloop the device if removed.") + .style(style::Text::Commentary); + + let choose_backup_descr = text("Note: If you have previous backups, you will need to transfer them manually to newly changed backup folder to be able to use Restore functionality") + .style(style::Text::Commentary); + + let choose_backup_btn = button(text("\u{E930}").font(ICONS)) + .padding([5, 10]) + .on_press(Message::ChooseBackUpFolder) + .style(style::Button::Primary); + + let choose_backup_row = row![ + choose_backup_btn, + "Choose backup folder", + Space::new().width(Length::Fill).height(Length::Shrink), + "Current folder: ", + text(self.general.backup_folder.to_string_lossy()) + ] + .spacing(10) + .align_y(Alignment::Center); + + container( + column![ + expert_mode_checkbox, + expert_mode_descr, + choose_backup_row, + choose_backup_descr, + ] + .spacing(10), + ) + .padding(10) + .width(Length::Fill) + .height(Length::Shrink) + .style(style::Container::Frame) + .into() + } + + fn warning_container(phone: &Phone) -> Element<'static, Message, Theme, Renderer> { + container( + row![ + text("The following settings only affect the currently selected device:") + .style(style::Text::Danger), + text(phone.model.clone()), + Space::new().width(Length::Fill).height(Length::Shrink), + text(phone.adb_id.clone()).style(style::Text::Commentary) + ] + .spacing(7), + ) + .padding(10) + .width(Length::Fill) + .style(style::Container::BorderedFrame) + .into() + } + + fn device_specific_container(&self, phone: &Phone) -> Element<'_, Message, Theme, Renderer> { + let multi_user_mode_descr = row![ + text("This will not affect the following protected work profile users: ") + .style(style::Text::Commentary), + text( + phone + .user_list + .iter() + .filter(|&u| u.protected) + .map(|u| u.id.to_string()) + .collect::>() + .join(", ") + ) + .style(style::Text::Danger) + ]; + + let multi_user_mode_checkbox = checkbox(self.device.multi_user_mode) + .label("Affect all the users of the device (not only the selected user)") + .on_toggle(Message::MultiUserMode) + .size(20) + .style(style::CheckBox::SettingsEnabled); + + let disable_checkbox_style = if supports_disabling(phone) { + style::CheckBox::SettingsEnabled + } else { + style::CheckBox::SettingsDisabled + }; + + let disable_mode_descr = + text("In many cases, it's better to disable a package instead of uninstalling it") + .style(style::Text::Commentary); + + let unavailable_btn = button(text("Unavailable").size(14)) + .on_press(Message::UrlPressed(PathBuf::from( + "https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/FAQ#\ + why-is-the-disable-mode-setting-not-available-for-my-device", + ))) + .height(22) + .style(style::Button::Unavailable); + + let disable_mode_checkbox = checkbox(self.device.disable_mode) + .label("Clear and disable packages instead of uninstalling them") + .on_toggle(Message::DisableMode) + .size(20) + .style(disable_checkbox_style); + + let disable_setting_row = if supports_disabling(phone) { + row![ + disable_mode_checkbox, + Space::new().width(Length::Fill).height(Length::Shrink), + ] + .width(Length::Fill) + } else { + row![ + disable_mode_checkbox, + Space::new().width(Length::Fill).height(Length::Shrink), + unavailable_btn, + ] + .width(Length::Fill) + }; + + container( + column![ + multi_user_mode_checkbox, + multi_user_mode_descr, + disable_setting_row, + disable_mode_descr, + ] + .spacing(10), + ) + .padding(10) + .width(Length::Fill) + .height(Length::Shrink) + .style(style::Container::Frame) + .into() + } + + fn backup_restore_container( + &self, + phone: &Phone, + apps_view: &AppsView, + ) -> Element<'_, Message, Theme, Renderer> { + let backup_pick_list = pick_list( + self.device.backup.backups.clone(), + self.device.backup.selected.clone(), + Message::BackupSelected, + ) + .padding(6); + + let backup_btn = button_primary(text("Backup").align_x(alignment::Horizontal::Center)) + .on_press(Message::BackupDevice) + .width(77); + + let restore_btn = |enabled| { + if enabled { + button(text("Restore").align_x(alignment::Horizontal::Center)) + .padding([5, 10]) + .on_press(Message::RestoreDevice) + .width(77) + } else { + button( + text("No backup") + .align_x(alignment::Horizontal::Center) + .align_y(alignment::Vertical::Center), + ) + .padding([5, 10]) + .width(77) + } + }; + + let locate_backup_btn = if self.device.backup.backups.is_empty() { + button_primary("Open backup directory") + } else { + button_primary("Open backup directory").on_press(Message::UrlPressed( + self.general.backup_folder.join(phone.adb_id.clone()), + )) + }; + + let export_btn = button_primary("Export").on_press(Message::ExportPackages); + + let backup_row = row![ + backup_btn, + "Backup the current state of the phone", + Space::new().width(Length::Fill).height(Length::Shrink), + locate_backup_btn, + ] + .spacing(10) + .align_y(Alignment::Center); + + let restore_row = if self.device.backup.backups.is_empty() { + row![] + } else { + row![ + restore_btn(true), + "Restore the state of the device", + Space::new().width(Length::Fill).height(Length::Shrink), + text(self.device.backup.backup_state.clone()).style(style::Text::Danger), + backup_pick_list, + ] + .spacing(10) + .align_y(Alignment::Center) + }; + + let export_row = row![ + export_btn, + "Export uninstalled packages with their description", + Space::new().width(Length::Fill).height(Length::Shrink), + text(format!( + "Selected: user {}", + apps_view.selected_user.unwrap_or_default().id + )), + ] + .spacing(10) + .align_y(Alignment::Center); + + container(column![backup_row, restore_row, export_row].spacing(10)) + .padding(10) + .width(Length::Fill) + .height(Length::Shrink) + .style(style::Container::Frame) + .into() + } + + fn no_device_container() -> Element<'static, Message, Theme, Renderer> { + container(text("No device detected").style(style::Text::Danger)) + .padding(10) + .width(Length::Fill) + .style(style::Container::BorderedFrame) + .into() + } + + fn render_export_modal<'a>( + content: Element<'a, Message, Theme, Renderer>, + ) -> Element<'a, Message, Theme, Renderer> { + let title = container(row![text("Success").size(24)].align_y(Alignment::Center)) + .width(Length::Fill) + .style(style::Container::Frame) + .padding([10, 0]) + .center_y(Length::Shrink) + .center_x(Length::Shrink); + + let text_box = row![ + text(format!( + "Exported uninstalled packages into file.\nFile is exported in same directory where {NAME} is located." + )) + .width(Length::Fill), + ] + .padding(20); + + let file_row = + row![text(generate_backup_name(chrono::Local::now())).style(style::Text::Commentary)] + .padding(20); + + let modal_btn_row = row![ + Space::new().width(Length::Fill).height(Length::Shrink), + button(text("Close").width(Length::Shrink)) + .width(Length::Shrink) + .on_press(Message::ModalHide), + Space::new().width(Length::Fill).height(Length::Shrink), + ]; + + let ctn = container(column![title, text_box, file_row, modal_btn_row]) + .height(Length::Shrink) + .width(500) + .padding(10) + .style(style::Container::Frame); + + let padded_content: Element<'a, Message, Theme, Renderer> = + container(content).padding(10).into(); + + Modal::new(padded_content, ctn) + .on_blur(Message::ModalHide) + .into() + } +} diff --git a/src/gui/widgets/mod.rs b/crates/uad-gui/src/widgets/mod.rs similarity index 100% rename from src/gui/widgets/mod.rs rename to crates/uad-gui/src/widgets/mod.rs diff --git a/src/gui/widgets/modal.rs b/crates/uad-gui/src/widgets/modal.rs similarity index 84% rename from src/gui/widgets/modal.rs rename to crates/uad-gui/src/widgets/modal.rs index 7eaf7f3..86278a7 100644 --- a/src/gui/widgets/modal.rs +++ b/crates/uad-gui/src/widgets/modal.rs @@ -1,7 +1,7 @@ use iced::advanced::widget::{self, Tree, Widget}; use iced::advanced::{Clipboard, Layout, Shell, layout, overlay, renderer}; use iced::mouse::{self, Cursor}; -use iced::{Alignment, Color, Element, Event, Length, Point, Rectangle, Size, advanced, event}; +use iced::{Alignment, Color, Element, Event, Length, Point, Rectangle, Size, Vector, advanced}; /// A widget that centers a modal element over some base element pub struct Modal<'a, Message, Theme, Renderer> { @@ -25,6 +25,7 @@ impl<'a, Message, Theme, Renderer> Modal<'a, Message, Theme, Renderer> { /// Sets the message that will be produces when the background /// of the [`Modal`] is pressed + #[must_use] pub fn on_blur(self, on_blur: Message) -> Self { Self { on_blur: Some(on_blur), @@ -52,28 +53,28 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { self.base - .as_widget() + .as_widget_mut() .layout(&mut tree.children[0], renderer, limits) } - fn on_event( + fn update( &mut self, state: &mut Tree, - event: Event, + event: &Event, layout: Layout<'_>, cursor_position: Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, viewport: &Rectangle, - ) -> event::Status { - self.base.as_widget_mut().on_event( + ) { + self.base.as_widget_mut().update( &mut state.children[0], event, layout, @@ -82,7 +83,7 @@ where clipboard, shell, viewport, - ) + ); } fn draw( @@ -109,9 +110,10 @@ where fn overlay<'b>( &'b mut self, state: &'b mut Tree, - layout: Layout<'_>, + layout: Layout<'b>, _renderer: &Renderer, - _translation: iced::Vector, + viewport: &Rectangle, + _translation: Vector, ) -> Option> { Some(overlay::Element::new(Box::new(Overlay { position: layout.position(), @@ -119,6 +121,7 @@ where tree: &mut state.children[1], size: layout.bounds().size(), on_blur: self.on_blur.clone(), + viewport: *viewport, }))) } @@ -140,14 +143,14 @@ where } fn operate( - &self, + &mut self, state: &mut Tree, layout: Layout<'_>, renderer: &Renderer, - operation: &mut dyn widget::Operation, + operation: &mut dyn widget::Operation, ) { self.base - .as_widget() + .as_widget_mut() .operate(&mut state.children[0], layout, renderer, operation); } } @@ -158,6 +161,7 @@ struct Overlay<'a, 'b, Message, Theme, Renderer> { tree: &'b mut Tree, size: Size, on_blur: Option, + viewport: Rectangle, } impl overlay::Overlay @@ -173,42 +177,41 @@ where let child = self .content - .as_widget() + .as_widget_mut() .layout(self.tree, renderer, &limits) .align(Alignment::Center, Alignment::Center, limits.max()); layout::Node::with_children(self.size, vec![child]).move_to(self.position) } - fn on_event( + fn update( &mut self, - event: Event, + event: &Event, layout: Layout<'_>, cursor: Cursor, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, - ) -> event::Status { - if let Some(message) = self.on_blur.as_ref() { - if matches!( + ) { + if let Some(message) = self.on_blur.as_ref() + && matches!( event, Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - ) { - if let Some(cursor_position) = cursor.position() { - let content_bounds = layout - .children() - .next() - .expect("Layout must have at least 1 child") - .bounds(); - if !content_bounds.contains(cursor_position) { - shell.publish(message.clone()); - return event::Status::Captured; - } - } + ) + && let Some(cursor_position) = cursor.position() + { + let content_bounds = layout + .children() + .next() + .expect("Layout must have at least 1 child") + .bounds(); + if !content_bounds.contains(cursor_position) { + shell.publish(message.clone()); + return; } } - self.content.as_widget_mut().on_event( + self.content.as_widget_mut().update( self.tree, event, layout.children().next().unwrap(), @@ -216,8 +219,8 @@ where renderer, clipboard, shell, - &layout.bounds(), - ) + &self.viewport, + ); } fn draw( @@ -254,9 +257,9 @@ where &mut self, layout: Layout<'_>, renderer: &Renderer, - operation: &mut dyn widget::Operation, + operation: &mut dyn widget::Operation, ) { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( self.tree, layout.children().next().unwrap(), renderer, @@ -268,14 +271,13 @@ where &self, layout: Layout<'_>, cursor: Cursor, - viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.content.as_widget().mouse_interaction( self.tree, layout.children().next().unwrap(), cursor, - viewport, + &self.viewport, renderer, ) } diff --git a/src/gui/widgets/navigation_menu.rs b/crates/uad-gui/src/widgets/navigation_menu.rs similarity index 67% rename from src/gui/widgets/navigation_menu.rs rename to crates/uad-gui/src/widgets/navigation_menu.rs index dd1a242..d26f1b4 100644 --- a/src/gui/widgets/navigation_menu.rs +++ b/crates/uad-gui/src/widgets/navigation_menu.rs @@ -1,19 +1,22 @@ -use crate::core::helpers::button_primary; -pub use crate::core::sync::Phone; -use crate::core::theme::Theme; -use crate::core::update::{SelfUpdateState, SelfUpdateStatus}; -pub use crate::gui::views::about::Message as AboutMessage; -pub use crate::gui::views::list::{List as AppsView, LoadingState as ListLoadingState}; -use crate::gui::{Message, style, widgets::text}; +use crate::helpers::button_primary; +use crate::theme::Theme; +pub use crate::views::about::Message as AboutMessage; +pub use crate::views::list::{List as AppsView, LoadingState as ListLoadingState}; +use crate::{gui::Message, style, widgets::text}; use iced::widget::{Space, button, container, pick_list, row, tooltip}; use iced::{Alignment, Element, Font, Length, Renderer, alignment, font}; - +pub use uad_core::sync::Phone; +use uad_core::update::{SelfUpdateState, SelfUpdateStatus}; /// resources/assets/icons.ttf, loaded in [`crate::gui::UadGui`] pub const ICONS: Font = Font { family: font::Family::Name("icomoon"), ..Font::DEFAULT }; +#[allow( + clippy::too_many_lines, + reason = "Navigation layout composes many widgets inline" +)] pub fn nav_menu<'a>( device_list: &'a [Phone], selected_device: Option, @@ -24,16 +27,28 @@ pub fn nav_menu<'a>( text("\u{E900}") .font(ICONS) .width(22) - .horizontal_alignment(alignment::Horizontal::Center), + .align_x(alignment::Horizontal::Center), ) .on_press(Message::RefreshButtonPressed); - let apps_refresh_tooltip = tooltip(apps_refresh_btn, "Refresh apps", tooltip::Position::Bottom) - .style(style::Container::Tooltip) - .gap(4); + let apps_refresh_tooltip = tooltip( + apps_refresh_btn, + "Refresh apps (Ctrl+Shift+5)", + tooltip::Position::Bottom, + ) + .style(style::Container::Tooltip) + .gap(4); let reboot_btn = button_primary("Reboot").on_press(Message::RebootButtonPressed); + let reboot_btn = tooltip( + reboot_btn, + "Reboot device (Ctrl+Shift+R)", + tooltip::Position::Bottom, + ) + .style(style::Container::Tooltip) + .gap(4); + let uad_version_text = if let Some(r) = &self_update_state.latest_release { match self_update_state.status { SelfUpdateStatus::Failed => text(format!("Failed to update to {}", r.tag_name)), @@ -60,16 +75,28 @@ pub fn nav_menu<'a>( let apps_btn = button_primary("Apps").on_press(Message::AppsPress); + let apps_btn = tooltip(apps_btn, "(Ctrl+Shift+A)", tooltip::Position::Bottom) + .style(style::Container::Tooltip) + .gap(4); + let about_btn = button_primary("About").on_press(Message::AboutPressed); + let about_btn = tooltip(about_btn, "(Ctrl+Shift+I)", tooltip::Position::Bottom) + .style(style::Container::Tooltip) + .gap(4); + let settings_btn = button_primary( text("\u{E994}") .font(ICONS) .width(22) - .horizontal_alignment(alignment::Horizontal::Center), + .align_x(alignment::Horizontal::Center), ) .on_press(Message::SettingsPressed); + let settings_btn = tooltip(settings_btn, "(Ctrl+Shift+S)", tooltip::Position::Bottom) + .style(style::Container::Tooltip) + .gap(4); + let device_list_text = match apps_view.loading_state { ListLoadingState::FindingPhones => text("Finding connected devices..."), _ => text("No devices/emulators found"), @@ -80,7 +107,7 @@ pub fn nav_menu<'a>( reboot_btn, apps_refresh_tooltip, pick_list(device_list, Some(phone), Message::DeviceSelected,), - Space::new(Length::Fill, Length::Shrink), + Space::new().width(Length::Fill).height(Length::Shrink), uad_version_text, update_btn, apps_btn, @@ -88,13 +115,13 @@ pub fn nav_menu<'a>( settings_btn, ] .width(Length::Fill) - .align_items(Alignment::Center) + .align_y(Alignment::Center) .spacing(10), None => row![ reboot_btn, apps_refresh_tooltip, device_list_text, - Space::new(Length::Fill, Length::Shrink), + Space::new().width(Length::Fill).height(Length::Shrink), uad_version_text, update_btn, apps_btn, @@ -102,7 +129,7 @@ pub fn nav_menu<'a>( settings_btn, ] .width(Length::Fill) - .align_items(Alignment::Center) + .align_y(Alignment::Center) .spacing(10), }; diff --git a/src/gui/widgets/package_row.rs b/crates/uad-gui/src/widgets/package_row.rs similarity index 55% rename from src/gui/widgets/package_row.rs rename to crates/uad-gui/src/widgets/package_row.rs index 59c7e39..9c9c1cd 100644 --- a/src/gui/widgets/package_row.rs +++ b/crates/uad-gui/src/widgets/package_row.rs @@ -1,20 +1,21 @@ -use crate::core::sync::Phone; -use crate::core::theme::Theme; -use crate::core::uad_lists::{PackageState, Removal, UadList}; -use crate::gui::style; -use crate::gui::views::settings::Settings; -use crate::gui::widgets::text; +use crate::style; +use crate::theme::Theme; +use crate::views::settings::Settings; +use crate::widgets::text; +use log::warn; +use uad_core::sync::{CorePackage, Phone}; +use uad_core::uad_lists::{PackageState, Removal, UadList}; use iced::widget::{Space, button, checkbox, row}; -use iced::{Alignment, Command, Element, Length, Renderer, alignment}; +use iced::{Alignment, Element, Length, Renderer, Task, alignment}; #[derive(Clone, Debug)] pub struct PackageRow { pub name: String, - pub state: PackageState, pub description: String, - pub uad_list: UadList, pub removal: Removal, + pub state: PackageState, + pub list: UadList, pub selected: bool, pub current: bool, } @@ -27,34 +28,43 @@ pub enum Message { } impl PackageRow { + #[must_use] pub fn new( name: &str, - state: PackageState, description: &str, - uad_list: UadList, removal: Removal, + state: PackageState, + list: UadList, selected: bool, current: bool, ) -> Self { Self { name: name.to_string(), - state, description: description.to_string(), - uad_list, removal, + state, + list, selected, current, } } - pub fn update(&mut self, _message: &Message) -> Command { - Command::none() + #[allow( + clippy::unused_self, + reason = "Consistent component API; may change later" + )] + pub fn update(&mut self, _message: &Message) -> Task { + Task::none() } - pub fn view(&self, settings: &Settings, _phone: &Phone) -> Element { + pub fn view( + &self, + settings: &Settings, + _phone: &Phone, + ) -> Element<'_, Message, Theme, Renderer> { //let trash_svg = format!("{}/resources/assets/trash.svg", env!("CARGO_MANIFEST_DIR")); //let restore_svg = format!("{}/resources/assets/rotate.svg", env!("CARGO_MANIFEST_DIR")); - let button_style; + let button_style: fn(&Theme, iced::widget::button::Status) -> iced::widget::button::Style; let action_text; let action_btn; let selection_checkbox; @@ -87,24 +97,26 @@ impl PackageRow { || self.state != PackageState::Enabled || settings.general.expert_mode { - selection_checkbox = checkbox("", self.selected) + selection_checkbox = checkbox(self.selected) .on_toggle(Message::ToggleSelection) + .size(20) .style(style::CheckBox::PackageEnabled); action_btn = button( text(action_text) - .horizontal_alignment(alignment::Horizontal::Center) + .align_x(alignment::Horizontal::Center) .width(100), ) .on_press(Message::ActionPressed); } else { - selection_checkbox = checkbox("", self.selected) + selection_checkbox = checkbox(self.selected) .on_toggle(Message::ToggleSelection) + .size(20) .style(style::CheckBox::PackageDisabled); action_btn = button( text(action_text) - .horizontal_alignment(alignment::Horizontal::Center) + .align_x(alignment::Horizontal::Center) .width(100), ); } @@ -116,7 +128,8 @@ impl PackageRow { text(&self.name).width(Length::FillPortion(8)), action_btn.style(button_style) ] - .align_items(Alignment::Center) + .spacing(8) + .align_y(Alignment::Center) ) .padding(8) .style(if self.current { @@ -126,9 +139,62 @@ impl PackageRow { }) .width(Length::Fill) .on_press(Message::PackagePressed), - Space::with_width(15) + Space::new().width(Length::Fixed(15.0)) ] - .align_items(Alignment::Center) + .align_y(Alignment::Center) .into() } } + +// Conversions between PackageRow and CorePackage +impl From for PackageRow { + fn from(core: CorePackage) -> Self { + Self { + name: core.name.clone(), + description: core.description, + removal: core.removal, + state: core.state, + list: core.list, + selected: false, // Default to not selected + current: false, // Default to not current + } + } +} + +impl From<&CorePackage> for PackageRow { + fn from(core: &CorePackage) -> Self { + Self { + name: core.name.clone(), + description: core.description.clone(), + removal: core.removal, + state: core.state, + list: core.list, + selected: false, + current: false, + } + } +} + +impl From<&PackageRow> for CorePackage { + fn from(row: &PackageRow) -> Self { + Self { + name: row.name.clone(), + description: row.description.clone(), + removal: row.removal, + state: row.state, + list: row.list, + } + } +} + +impl From for CorePackage { + fn from(row: PackageRow) -> Self { + Self { + name: row.name, + description: row.description, + removal: row.removal, + state: row.state, + list: row.list, + } + } +} diff --git a/crates/uad-gui/src/widgets/text.rs b/crates/uad-gui/src/widgets/text.rs new file mode 100644 index 0000000..1fdc7c1 --- /dev/null +++ b/crates/uad-gui/src/widgets/text.rs @@ -0,0 +1,13 @@ +#![allow( + clippy::disallowed_types, + reason = "this is the replacement that enforces advanced shaping for disallowed [`iced::widget::Text`]" +)] + +use crate::theme::Theme; +use iced::advanced::text::IntoFragment; +use iced::widget; + +// Creates a new Text widget with advanced shaping. +pub fn text<'a>(text: impl IntoFragment<'a>) -> widget::Text<'a, Theme> { + widget::Text::new(text).shaping(iced::widget::text::Shaping::Advanced) +} diff --git a/flake.lock b/flake.lock index 43fb1b3..b3b5542 100644 --- a/flake.lock +++ b/flake.lock @@ -1,55 +1,25 @@ { "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 0, - "narHash": "sha256-YN/Ciidm+A0fmJPWlHBGvVkcarYWSC+s3NTPk/P+q3c=", - "path": "/nix/store/amxd2p02wx78nyaa4bkb0hjvgwhz1dq7-source", - "type": "path" + "lastModified": 1776949667, + "narHash": "sha256-GMSVw35Q+294GlrTUKlx087E31z7KurReQ1YHSKp5iw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "01fbdeef22b76df85ea168fbfe1bfd9e63681b30", + "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, "root": { "inputs": { - "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ba1a303..c86de56 100644 --- a/flake.nix +++ b/flake.nix @@ -1,37 +1,69 @@ { description = "devshell for uad-ng"; - inputs.flake-utils.url = "github:numtide/flake-utils"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem - (system: - let pkgs = nixpkgs.legacyPackages.${system}; in - { - devShells.default = pkgs.mkShell { - packages = with pkgs; + outputs = + { nixpkgs, ... }: + let + forSystems = + f: + nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed ( + system: f (import nixpkgs { inherit system; }) + ); + in + { + formatter = forSystems (pkgs: pkgs.nixfmt-tree); + + devShells = forSystems ( + pkgs: + let + inherit (pkgs) lib stdenv; + runtimeLibs = [ + pkgs.fontconfig + pkgs.freetype + ] + ++ lib.optionals stdenv.isLinux ( + with pkgs; [ - rustc - cargo - clang - pkg-config - mold - android-tools - ]; + libglvnd + libX11 + libXcursor + libXi + libXrandr + libxkbcommon + wayland + ] + ); + in + { + default = pkgs.mkShell ( + { + nativeBuildInputs = with pkgs; [ + clang + pkg-config + ]; + buildInputs = + with pkgs; + [ + rustc + cargo + rustfmt + rust-analyzer + clippy + android-tools + ] + ++ runtimeLibs; - LD_LIBRARY_PATH = "${nixpkgs.lib.makeLibraryPath [ - pkgs.fontconfig - pkgs.freetype - pkgs.libglvnd - pkgs.xorg.libX11 - pkgs.xorg.libXcursor - pkgs.xorg.libXi - pkgs.xorg.libXrandr - pkgs.libxkbcommon - pkgs.wayland - ]}"; - LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib"; - }; + RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}/lib/rustlib/src/rust"; + LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + } + // lib.optionalAttrs stdenv.isLinux { LD_LIBRARY_PATH = lib.makeLibraryPath runtimeLibs; } + // lib.optionalAttrs stdenv.isDarwin { + DYLD_FALLBACK_LIBRARY_PATH = lib.makeLibraryPath runtimeLibs; + } + ); } ); + }; } diff --git a/resources/assets/uad_lists.json b/resources/assets/uad_lists.json index 67eb5b2..ae97e4e 100644 --- a/resources/assets/uad_lists.json +++ b/resources/assets/uad_lists.json @@ -1,7 +1,1041 @@ { + "org.lineageos.jelly": { + "list": "Oem", + "description": "LineageOS Browser App, based on chromium.\nSafe to remove if you don't need it or have replaced it with another app.\nOtherwise there will be no browser app on your device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.cyanogenmod.filemanager": { + "list": "Oem", + "description": "Cyanogenmod file manager, safe to remove if you use another one.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "android.ext.shared": { + "list": "Aosp", + "description": "Android Shared Library, removing may cause a bootloop.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.wearable.pixel.aspen": { + "list": "Oem", + "description": "Fitbit's Connected Fitness feature for the Pixel Watch. Can be safely removed if you don't need/use it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "org.lineageos.recorder": { + "list": "Oem", + "description": "LineageOS Voice Recorder App.\nSafe to remove if you don't need it or have replaced it with another app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "org.lineageos.aperture": { + "list": "Oem", + "description": "LineageOS Camera App.\nSafe to remove if you've replaced it with another app.\nOtherwise there will be no camera app on your device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "org.lineageos.etar": { + "list": "Oem", + "description": "LineageOS Calendar App.\nSafe to remove if you've replaced it with another app.\nOtherwise there will be no calendar app on your device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "org.lineageos.glimpse": { + "list": "Oem", + "description": "LineageOS Gallery App.\nSafe to remove if you've replaced it with another app.\nOtherwise there will be no gallery app on your device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "org.lineageos.twelve": { + "list": "Oem", + "description": "LineageOS Music App.\nSafe to remove if you don't need it or have replaced it with another app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "org.lineageos.camelot": { + "list": "Oem", + "description": "LineageOS PDF Viewer App.\nSafe to remove if you don't need it or have replaced it with another app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "co.aospa.dolby.xiaomi": { + "list": "Oem", + "description": "AOSPA's Dolby Atmos App on custom ROMs for Xiaomi phones. Providers support for Dolby Atmos on devices with Xiaomi hardware running custom ROMs.\nRemoving it just removes the Dolby Atmos feature and its app. Safe to remove if you don't need it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "io.chaldeaprjkt.gamespace": { + "list": "Oem", + "description": "The Game Space App, often found in custom ROMs. If you don't need it or don't play games, it's safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "org.omnirom.omnistyle": { + "list": "Oem", + "description": "OmniRom customization app. It lets you change the header image on the quick settings panel and the wallpaper for custom ROMs. It's included in custom ROMs mostly for the quick settings header images as the wallpaper activity is not normally accessible.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "tokyo.witaqua.updater": { + "list": "Oem", + "description": "LineageOS Updater rebranded for the WitAqua custom ROM.\nNot safe to remove; could break Updater UI on devices with WitAqua ROMs.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sar.main": { + "list": "Misc", + "description": "!!! WARNING !!! DO NOT DELETE THIS PACKAGE, EVEN IF YOU ENABLED REMOVAL OF UNSAFE PACKAGES. THIS PACKAGE WON'T BOOTLOOP YOUR DEVICE, BUT ITS REMOVAL MAKES THE PHONE MORE DANGEROUS BECAUSE OF INCONTROLLABLE RADIO-FREQUENCY ENERGY EMITTING.\nSarReduce Service (Specific Absorption Rate)\nThis package adjusts the level of radio-frequency energy basing on where and what mode the phone is, found on Lenovo devices mostly.\nAbsolutely not safe to remove; Danger for health. The device won't be lowering the emitted radio-frequency energy while close to body. Networks, such as Wi-Fi, Bluetooth and Mobile Data are also very likely to become unstable.\nWARNING: Removing other core/important system services might influence or break the behavior of this package. BE CAREFUL.\nAlso, removing this package might violate the SAR (Specific Absorption Rate) law in EU.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "androidzte": { + "list": "Oem", + "description": "Basing on APK inspection, this is a framework package that powers all the system UI on ZTE, Nubia, Axon & Blade devices. Totally not safe to remove, it's as important as 'android'", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.wifi.resources.overlay": { + "list": "Aosp", + "description": "A google mainline module overlay for com.android.wifi.resources, which might be useless if gms is removed, as it only provides gms customizations for Wi-Fi, not android system customizations.\n Only safe to remove if you have removed gms.\n There's no such package as com.google.android.wifi.resources, but only com.android.wifi.resources. And there are multiple packages with such names, that cause no damage when removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.providers.partnerbrowsercustomizations": { + "list": "Aosp", + "description": "Provides browser customizations from partners (for chrome only). Total bloatware, especialy useless if you use another browser than Chrome.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.jiiov.fingerprint_factorytest": { + "list": "Misc", + "description": "A factory test app for Jiiov fingerprint scanners (Jiiov fingerprint scanners are mostly used on devices such as Xiaomi, Redmi, POCO, etc..). Mostly not needed for daily phone use, might be needed in service centers during repair or when you'll want to test your fingerprint scanner. Not sure how to even access it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.wifi.resources.overlay.pineapple": { + "list": "Misc", + "description": "An overlay for com.android.wifi.resources for devices using the “pineapple” Wi‑Fi HAL (Google’s internal codename for a Wi‑Fi module configuration). Not safe to remove, especially on Android 13+.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.wifi.resources.overlay.target.sm8635": { + "list": "Misc", + "description": "An overlay for com.android.wifi.resources for devices with the Snapdragon 7s Gen 2 CPU (codename SM8635). Not safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.dti.blu": { + "list": "Oem", + "description": "This package is preinstalled on devices made by cellphone manufacturer BLU, installs unwanted games and other non-essential stuff. Its name 'Mobile Services' makes it scary to remove, but I highly recommend removing it. No damage foukd after removal (did so in at least two different models of Blu phones).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.block.juggle": { + "list": "Misc", + "description": "Block Blast. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.block.puzzle.game.hippo.mi": { + "list": "Misc", + "description": "Block Puzzle Guardian. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sukhavati.gotoplaying.bubble.BubbleShooter.mint": { + "list": "Misc", + "description": "Bubble Shooter And Friends. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.logame.eliminateintruder3d": { + "list": "Misc", + "description": "Dust Settle. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.jewelsblast.ivygames.Adventure.free": { + "list": "Misc", + "description": "Jewels Blast. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.ordinaryjoy.woodblast": { + "list": "Misc", + "description": "Wood Blast. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.mintgames.wordtrip": { + "list": "Misc", + "description": "Word Scenery Crossword. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nf.snake": { + "list": "Misc", + "description": "Snake Zoneio. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.mintgames.triplecrush.tile.fun": { + "list": "Misc", + "description": "Tile Fun. A causal game pre-installed on Xiaomi Poco devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.miui.miwallpaper.config.overlay": { + "list": "Oem", + "description": "Another overlay for com.miui.miwallpaper. Since all other overlays related to it are listed in recommended and marked as useless empty apps, this one is most likely the same.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.uwb.resources.overlay.common": { + "list": "Aosp", + "description": "Overlay for UWB (Ultra-Wideband) resources. Used for device-to-device ranging and location features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.overlay.setupwizard": { + "list": "Aosp", + "description": "An overlay for com.google.android.setupwizard. Safe to remove if com.google.android.setupwizard has been removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.provision.overlay.miui": { + "list": "Oem", + "description": "An overlay for com.android.provision for Xiaomi devices. Since com.android.provision is in Unsafe, this should also be in Unsafe.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.miui.safetycenter.config.overlay": { + "list": "Oem", + "description": "An overlay for com.miui.safetycenter providing configurations and preferences. Safe to delete if com.miui.safetycenter is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.miui.safetycenter.res.overlay": { + "list": "Oem", + "description": "An overlay for com.miui.safetycenter providing resources and preferences. Safe to delete if com.miui.safetycenter is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.miui.settings.rro.device.systemui.overlay": { + "list": "Oem", + "description": "A device-specific overlay for com.android.settings on Xiaomi devices customizing the system UI. Likely not something that's safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.mediatek.datachannel.service": { + "list": "Misc", + "description": "Mediatek's DataChannel Service, manages data channels used by IMS for VoLTE, VoWiFi and RCS.\nThe communication bridge between modem and android telephony framework. Will most likely break RCS, VoLTE and VoWiFi. Not worth deleting.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.wifi.resources.xiaomi": { + "list": "Oem", + "description": "An overlay-xiaomi addition for com.android.wifi.resources, presumably xiaomi bloat. No issues with Wi-Fi found after removal.\nThere's no such package as com.google.android.wifi.resources, but only com.android.wifi.resources, so it's likely a part of a google addition for Wi-Fi services, so likely bloat. Safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.wifi.resources.overlay.common": { + "list": "Aosp", + "description": "An overlay-google addition for `com.android.wifi.resources`, presumably Google bloat.\nA user reported some issues with Hotspot", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.miui.settings.rro.device.config.overlay": { + "list": "Oem", + "description": "Presumably a MIUI/HyperOS overlay com.android.settings providing device-specific configurations for system settings.\nLikely not something you would want to remove. Will likely cause issues.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.miui.permissioncontroller.overlay": { + "list": "Oem", + "description": "Presumably a MIUI/HyperOS overlay for com.gooogle.android.permissioncontroller. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.qualcomm.qti.uceShimService": { + "list": "Misc", + "description": "The Qualcomm telephony support service that acts as a shim layer between IMS and qualcomm modem stack.\nWill likely break RCS, VoLTE, VoWiFi and some carrier preference customizations. Not worth deleting.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "android.autoinstalls.config.Xiaomi.whyred": { + "list": "Oem", + "description": "App that configures preinstalled apps and initial preferences on Xiaomi Redmi Note 5 / Xiaomi Redmi Note 5 Pro (as their both's codename is whyred).\nOnly needed on device setup, dormant and useless afterwards. It's restored automatically in case of a factory reset. Safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.gallery.player": { + "list": "Oem", + "description": "Old MIUI Gallery app's media player, a separate package from com.miui.gallery. Will likely break playing and presumably viewing media in the MIUI Gallery app.\nNot seen on HyperOS but present on some old MIUI versions. Safe to remove if com.miui.gallery is already removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "android.ui.overlay.ct": { + "list": "Aosp", + "description": "An overlay that customizes Android UI for the China Telecom operator (3rd largest operator in China).\nSafe to remove if you don't live in china or don't use/plan to use this carrier. Often present on ROMs and devices outside of China.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.xiaomi.aiservice": { + "list": "Oem", + "description": "Xiaomi on-device AI inference engine (HyperOS/MIUI). Runs many ML models (OCR, translation, etc.) in isolated per-model processes. \nEmbeds Xiaomi's OneTrack SDK, which collects OAID, android_id, device fingerprint, region, network type, and per-event usage data, then uploads it encrypted to tracking.*.miui.com. \nAlso embeds XCrash for crash reporting. Downloads AI model updates silently via Android DownloadManager (probably has to do with AI Core). \nRemoving probably breaks HyperOS AI features (I haven't tested) but does not affect core phone, SMS, or data functions.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.xiaomi.phone.overlay": { + "list": "Oem", + "description": "An overlay needed for com.xiaomi.phone. Safe to remove if com.xiaomi.phone has been removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.xiaomi.phone": { + "list": "Oem", + "description": "A MIUI/HyperOS extension for telephony services. Called HyperPhone (at least on HyperOS), I don't know how is it named in MIUI, if you know, please edit this package and add it's MIUI name here. (in GitHub)\nIt's similar to com.xiaomi.bluetooth by it's purpose, but here it's a Xiaomi extension for telephony services. Deleting it caused no data loss or issues with telephony, calls, mobile data, and other on HyperOS 2.0.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.dti.telefonica": { + "list": "Carrier", + "description": "O2 & Telefonica carrier bloat. Runs in background, updates, maintains and installs Telefonica carrier apps and services, and is totally useless if you don't use this carrier.\nO2 and Telefonica are only available in Latin America, Brazil, Spain, Germany and UK, but it's often preinstalled on EU, Global and possibly other ROMs, as countries where this carrier is present use these ROMs. Safe to delete.\nPresumably works together with com.xiaomi.entitlement.o2. It's also a package safe to remove if you don't use the carriers mentioned earlier.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "android.miui.overlay.telephony": { + "list": "Oem", + "description": "Likely an important overlay for telephony services and com.android.providers.telephony, specific for devices running HyperOS/MIUI. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "android.aosp.overlay.telephony": { + "list": "Aosp", + "description": "Likely an important overlay for telephony services and com.android.providers.telephony. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.miui.misightservice": { + "list": "Oem", + "description": "Telemetry and diagnostics collector app that sends analytics to Xiaomi servers and has almost no use for user.\nSomething on the level of com.miui.msa or com.miui.daemon. Worth deleting.\nConstantly connects somewhere and sends/receives up to 100KB of data per day to/from an unknown source. This also means it often runs in background.\nIt's labeled as Blur and has orange-white MI icon, but it just hides under it. No blur/ui/any other issues seen after around a month of use of HyperOS 2.0 with this removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.overlay.modules.healthfitness.forframework": { + "list": "Aosp", + "description": "Another part of health fitness system, useless for most users along with all other health fitness packages.\nSafe to delete, obviously, unless if you use health fitness services.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xiaomi.cameramind": { + "list": "Oem", + "description": "The core of all AI features for Xiaomi's camera app. Won't impact other camera apps' AI features.\nSafe to delete if you use another camera app, otherwise, removal may cause background connection issues.", + "dependencies": [], + "neededBy": [ + "com.android.camera" + ], + "labels": [], + "removal": "Advanced" + }, + "com.xiaomi.bluetooth.rro.device.config.overlay": { + "list": "Oem", + "description": "A device-specific overlay for com.xiaomi.bluetooth. Safe to remove if com.xiaomi.bluetooth is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.miui.euicc": { + "list": "Oem", + "description": "The LPA app that is constantly running in background, consuming RAM and battery. This app is the core of all the eSIM services on Xiaomi devices, runs and drains resources even if you have no eSIM.\nConstantly being found in running processes list. No issues appeared after removing it on HyperOS 2.0 and using it for over a month.\nTelephony and all settings stayed intact, worth deleting this if you don't use an eSIM.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.miui.cotaservice": { + "list": "Oem", + "description": "MIUI's COTA (Configuration Over-The-Air) service. Pretty much the same as com.google.configupdater but for miui services.\nUnlike google's config updater, it constantly connects to the web and sends/receives data from an unknown source. Might cause obscure issues with telephony and Xiaomi services.\nSafe to delete if you've deleted all Xiaomi services like Xiaomi Cloud, GetApps, xmsf, etc... and !!! have logged out of your Xiaomi Account !!! Pretty much all is same as with com.google.configupdater. Deleting it on HyperOS 2.0 causes no issues.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.telephony.overlay.miui": { + "list": "Oem", + "description": "Required for com.android.providers.telephony on devices running HyperOS/MIUI. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.providers.settings.overlay": { + "list": "Aosp", + "description": "Required for com.android.providers.settings. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.phone.cust.overlay.miui": { + "list": "Oem", + "description": "An overlay customizing default behavior and preferences for com.android.phone on devices running HyperOS/MIUI. Safe to remove if com.android.phone is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.networkstack.overlay.miui": { + "list": "Oem", + "description": "Required for com.android.networkstack on devices running HyperOS/MIUI. Not safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.carrierconfig.overlay.miui": { + "list": "Oem", + "description": "Required for com.android.carrierconfig on devices running HyperOS/MIUI. Safe to remove if com.android.carrierconfig is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.thememanager.customizethemeconfig.config.overlay": { + "list": "Oem", + "description": "An overlay for Xiaomi's com.android.thememanager providing theme config customization default preferences and configs. Safe to remove if com.android.thememanager is removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.overlay.circletosearch": { + "list": "Aosp", + "description": "An overlay likely deeply tied with system ui, because it causes a soft brick (all system apps suddenly crashing and inability to launch any app or process after that) on HyperOS 2.0.\nWill most likely also bootloop your device. Totally NOT safe to delete.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.aura.oobe.deutsche": { + "list": "Carrier", + "description": "Provides an Out Of The Box experience. You can disable it via Settings > Apps > Three dots > Show system > App selector. It has a T-Mobile icon", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "android.res.overlay_305": { + "list": "Oem", + "description": "An overlay that draws over android. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "android.res.overlay_310_311": { + "list": "Oem", + "description": "An overlay that draws over android. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.browser.res.overlay_305": { + "list": "Oem", + "description": "An overlay that draws over the browser, probably safe to disable if you use another browser. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.carrierconfig.res.overlay_305": { + "list": "Oem", + "description": "An overlay that draws over the android.carrierconfig package, probably safe if you do not use calls/SMS. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.carrierconfig.res.overlay_310_311": { + "list": "Oem", + "description": "An overlay that draws over the android.carrierconfig package, probably safe if you do not use calls/SMS. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.advancedwidget.photo": { + "list": "Oem", + "description": "Videos and photos, safe to remove: https://www.apkmirror.com/apk/sony-mobile-communications/photos-and-videos/photos-and-videos-2-2-a-0-8-release/photos-and-videos-2-2-a-0-8-android-apk-download", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sonyericsson.android.camera": { + "list": "Oem", + "description": "Sony's default camera app, can be replaced but you will lose camera features", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.partnerbrowsercustomizations.chromeHomepage.res.overlay_310_311": { + "list": "Oem", + "description": "Adds a customised homepage to Google Chrome provided by either OEM or carrier. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.fingerprints.fido.asm": { + "list": "Oem", + "description": "Fido Alliance fingerprint. It is possible that ASM stands for Authentication Service Module/Application Security Module", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.phone.product.res.overlay": { + "list": "Oem", + "description": "Overlays the phone app, needed if you use the device for calls/SMS/contact management. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.phone.product.res.overlay.no_imei_emergency_call": { + "list": "Oem", + "description": "Unsure but I would just leave it as you need to stay safe. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.phone.res.overlay_305": { + "list": "Oem", + "description": "Overlays the phone app, keep if you want calls/SMS/contact management to work. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.providers.icccust": { + "list": "Oem", + "description": "Looks to be linked to SIM management. I would advise keeping it", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.partnerbookmarks.res.overlay_305": { + "list": "Oem", + "description": "Overlays Bookmark customisation, probably not needed. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.partnerbookmarks.res.overlay_310_311": { + "list": "Oem", + "description": "Overlays Bookmark customisation, probably not needed. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.settings.res.overlay_305": { + "list": "Oem", + "description": "Overlays system settings, probably needed. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.settings.res.overlay_305": { + "list": "Oem", + "description": "Overlays system settings, probably needed. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.settings.res.overlay_310_311": { + "list": "Oem", + "description": "Overlays system settings, probably needed. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.stk.product.res.overlay.common": { + "list": "Oem", + "description": "SIM Tool Kit overlay, best kept. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.systemui.res.overlay_305": { + "list": "Oem", + "description": "Overlays SystemUI, best kept. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.android.systemui.res.overlay_310_311": { + "list": "Oem", + "description": "Overlays SystemUI, best kept. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.noknok.android.mfac.service": { + "list": "Oem", + "description": "Part of the FIDO authentication for fingerprint", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.qti.vzw.ims.internal.tests": { + "list": "Oem", + "description": "Seems to be linked with Verizon internal tests but many sources including XDA developers suggest getting rid", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sony.nfx.app.sfrc": { + "list": "Oem", + "description": "Tied to Sony's recommendations and can be safely got rid of, maybe break suggestions/recommendations", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.android.bootinfo": { + "list": "Oem", + "description": "May break boot, bootloader checks. No removal tested", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonyericsson.android.camera.product.res.overlay.enable.information.entry": { + "list": "Oem", + "description": "Overlays default camera app, removing could break camera features. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.android.camera.product.res.overlay.enable.scene.setting": { + "list": "Oem", + "description": "Overlays default camera app, removing could break camera features. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.android.servicemenu": { + "list": "Oem", + "description": "Provides access to service menus for testing", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.android.servicemenu.product.res.overlay.suzu": { + "list": "Oem", + "description": "Overlays service com.sonyericsson.android.servicemenu. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.autopoweroffservice": { + "list": "Oem", + "description": "This service helps safe shutdown, could cause negative effect by removing but system settings > apps > autopoweroff > lets you disable it", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.cameraextension.permission": { + "list": "Oem", + "description": "Provides third party apps access to AR effect and other plugins, removing will break camera functionality", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.crashmonitor": { + "list": "Oem", + "description": "Sony's crash monitor", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.credentialmanagerservice": { + "list": "Oem", + "description": "Said to be Sony's custom credential storage and obsolete these days due to Google's storage manager", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sonyericsson.customizedsettings": { + "list": "Oem", + "description": "Settings that are customised by carriers for region specifics", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.devicemonitor": { + "list": "Oem", + "description": "Safe to remove if you don't use PC to manage device", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.fmradio": { + "list": "Oem", + "description": "Sony's FM radio app, safe to remove if you don't use it", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sonyericsson.home": { + "list": "Oem", + "description": "Sony's default launcher, do not remove unless you have another launcher or you will brick your device", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.home.product.res.overlay": { + "list": "Oem", + "description": "Launcher overlay, best left enabled. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.home.res.overlay_305": { + "list": "Oem", + "description": "Launcher overlay, best left enabled. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.lockscreen.uxpnxt": { + "list": "Oem", + "description": "Sony lockscreen settings", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.mtp.extension.factoryreset": { + "list": "Oem", + "description": "Sony phone says 'lock screen settings'. Removing it can cause bootloop", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonyericsson.omadl": { + "list": "Oem", + "description": "Provides carrier/APN updates and OTA in some cases. Sony phone says 'OMA download client', best left enabled", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.organizer": { + "list": "Oem", + "description": "Tied to Sony calendar, deprecated by Google and other calendars", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sonyericsson.photoeditor": { + "list": "Oem", + "description": "Sony's photo editor: https://www.apkmirror.com/apk/sony-mobile-communications/photo-editor", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sonyericsson.providers.cnap": { + "list": "Oem", + "description": "Allows carriers to show incoming caller name instead of just the number via CNAP, best left enabled to see who is calling", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.psm.sysmonservice": { + "list": "Oem", + "description": "Power management, Stamina mode. Best left enabled", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.settings": { + "list": "Oem", + "description": "This is the system settings app, do not remove it", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonyericsson.settings.res.overlay_310_311": { + "list": "Oem", + "description": "System settings overlay, do not remove. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonyericsson.setupwizard": { + "list": "Oem", + "description": "Onboarding that occurs after factory reset or first boot, safe to remove", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.setupwizard.res.overlay_305": { + "list": "Oem", + "description": "Overlays setup wizard during first boot or after factory reset, safe to remove. Find out more by running: adb shell cmd overlay list, to see other packages", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.simdetection": { + "list": "Oem", + "description": "Detects SIM connection, best left enabled", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.soundenhancement": { + "list": "Oem", + "description": "Not essential for audio to work but provides sound effects/enhancements such as Clear Audio+", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonyericsson.suquashi.soundpicker": { + "list": "Oem", + "description": "Ringtone/notification/alarm time picker", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonyericsson.tetherentitlementcheck": { + "list": "Oem", + "description": "Needed for tethering checks such as carrier conditions and regional restrictions, safe to remove if you don't tether/hotspot", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.updatecenter": { + "list": "Oem", + "description": "The system updater found on settings > about > software update, safe to remove if your device no longer receives updates", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.updatecenter.res.overlay_305": { + "list": "Oem", + "description": "Overlay for updater found in Settings > about > system update, safe to remove if your device no longer gets updates", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonyericsson.usbux": { + "list": "Oem", + "description": "Provides the USB options such as MTP, PTP, charge only. Leave enabled", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonymobile.android.addoncamera.dual": { + "list": "Oem", + "description": "Provides an addon to enable dual camera functionality, safe to remove if you don’t need camera add-ons", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sonymobile.btidd": { + "list": "Oem", + "description": "Bluetooth stack identifier, may be tied to pairing/security. Best to keep enabled", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sonymobile.cameracommon": { + "list": "Oem", + "description": "Shared library for Sony’s camera app and add-ons. Removing breaks camera functionality", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sonymobile.coresettings": { + "list": "Oem", + "description": "Contains Sony-specific customisations and settings overlays. Needed for Xperia custom features", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.mi.appfinder": { + "list": "Oem", + "description": "HyperOS 2.0.202.0, it didn't break the system or ui search function or poco launcher search app function. Havent heard of it breaking stuff for others so dont think it's of much concern\n has 15 trackers\nNeeded for poco launcher search function in HyperOS 3.0", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.dti.tracfone": { "list": "Carrier", - "description": "Installs sponsored apps automatically on Tracfone and affiliated carriers (Straight Talk, Total Wireless, etc) \n", + "description": "Installs sponsored apps automatically on Tracfone and affiliated carriers (Straight Talk, Total Wireless, etc)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -9,7 +1043,7 @@ }, "com.sony.tvsideview.videoph": { "list": "Oem", - "description": "Video & TV SideView (replaced by https://play.google.com/store/apps/details?id=com.sony.tvsideview.phone)\nLets you use your smartphone or tablet as a TV remote control for the home. \n", + "description": "Video & TV SideView (replaced by https://play.google.com/store/apps/details?id=com.sony.tvsideview.phone)\nLets you use your smartphone or tablet as a TV remote control for the home.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -25,7 +1059,7 @@ }, "com.sonyericsson.android.addoncamera.artfilter": { "list": "Oem", - "description": "Sony Creative effect\nGives options for various photographic toning effects in the Sony camera app.\nI'm not 100% sure for this one. Can someone confirm ? \n", + "description": "Sony Creative effect\nGives options for various photographic toning effects in the Sony camera app.\nI'm not 100% sure for this one. Can someone confirm ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -33,7 +1067,7 @@ }, "com.sonyericsson.android.omacp": { "list": "Oem", - "description": "omacp = OMA Client Provisioning. It is a protocol specified by the Open Mobile Alliance (OMA).\nIt is used by carrier to send \"configuration SMS\" which can setup network settings (such as APN).\nIn my case, it was automatic and I never needed configuration messages. I'm pretty sure that in France this package is useless.\nMaybe it's useful if carriers change their APN... but you still can change it manually, it's not difficult.\nThese special \"configuration SMS\" can be abused : \nhttps://www.zdnet.fr/actualites/les-smartphones-samsung-huawei-lg-et-sony-vulnerables-a-des-attaques-par-provisioning-39890045.htm\nhttps://www.csoonline.com/article/3435729/sms-based-provisioning-messages-enable-advanced-phishing-on-android-phones.html\n", + "description": "omacp = OMA Client Provisioning. It is a protocol specified by the Open Mobile Alliance (OMA).\nIt is used by carrier to send\"configuration SMS\" which can setup network settings (such as APN).\nIn my case, it was automatic and I never needed configuration messages. I'm pretty sure that in France this package is useless.\nMaybe it's useful if carriers change their APN... but you still can change it manually, it's not difficult.\nThese special\"configuration SMS\" can be abused :\nhttps://www.zdnet.fr/actualites/les-smartphones-samsung-huawei-lg-et-sony-vulnerables-a-des-attaques-par-provisioning-39890045.htm\nhttps://www.csoonline.com/article/3435729/sms-based-provisioning-messages-enable-advanced-phishing-on-android-phones.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -49,7 +1083,7 @@ }, "com.sonyericsson.idd.agent": { "list": "Oem", - "description": "Anonymous Usage Stats\nUsed to send \"anonymous\" information about how you use your Sony Smartphone to Sony servers.\nIt remains unclear exactly how this information is anonymized.", + "description": "Anonymous Usage Stats\nUsed to send\"anonymous\" information about how you use your Sony Smartphone to Sony servers.\nIt remains unclear exactly how this information is anonymized.", "dependencies": [], "neededBy": [], "labels": [], @@ -97,7 +1131,7 @@ }, "com.sonyericsson.startupflagservice": { "list": "Oem", - "description": "Startup Flag Service\nUsed during the production of the phone to verify that the touch input works. \nIt can be triggered when a specific TA-parameter is not set. This should never be triggered and if it does well it doesn't have any use for you.\n\nTA means Timing Advance and its value correspond to the length of time a signal takes to reach the base station from a mobile phone.\nhttps://www.telecomhall.net/t/parameter-timing-advance-ta/6390\n", + "description": "Startup Flag Service\nUsed during the production of the phone to verify that the touch input works.\nIt can be triggered when a specific TA-parameter is not set. This should never be triggered and if it does well it doesn't have any use for you.\n\nTA means Timing Advance and its value correspond to the length of time a signal takes to reach the base station from a mobile phone.\nhttps://www.telecomhall.net/t/parameter-timing-advance-ta/6390\n", "dependencies": [], "neededBy": [], "labels": [], @@ -137,7 +1171,7 @@ }, "com.sonyericsson.wappush": { "list": "Oem", - "description": "WAP Push\nUsed to display annoying WAP push.\nWAP push is a type of text message that contains a direct link to a particular Web page. \nWhen a user is sent a WAP-push message, he receives an alert, once clicked, directs him to the Web page via his browser.\nPersonally, I don't like this. URLs are now recognized by the SMS instant messaging apps and you just have to click on it.\n", + "description": "WAP Push\nUsed to display annoying WAP push.\nWAP push is a type of text message that contains a direct link to a particular Web page.\nWhen a user is sent a WAP-push message, he receives an alert, once clicked, directs him to the Web page via his browser.\nPersonally, I don't like this. URLs are now recognized by the SMS instant messaging apps and you just have to click on it.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -145,7 +1179,7 @@ }, "com.sonyericsson.xhs": { "list": "Oem", - "description": "Sony Xperia Lounge (discontinued by Sony on August 2019)\nThe Xperia Lounge app was meant to provide loyal fans with various rewards for their Xperia smartphones, \nsuch as exclusive Xperia Themes and wallpapers, as well as competitions.\n", + "description": "Sony Xperia Lounge (discontinued by Sony on August 2019)\nThe Xperia Lounge app was meant to provide loyal fans with various rewards for their Xperia smartphones,\nsuch as exclusive Xperia Themes and wallpapers, as well as competitions.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -153,7 +1187,7 @@ }, "com.sonymobile.advancedlogging": { "list": "Oem", - "description": "Advanced Logging\nSends logs to Sony Mobile. These logs contain a wide range of personal information such as unique device IDs, your location, \ndetails regarding running applications, and events/input leading up to a crash.\nLogging is only active for a short time and automatically disabled once logging has been completed. \nLogs are uploaded when connected to Wi-Fi and automatically deleted when the upload is complete.\n", + "description": "Advanced Logging\nSends logs to Sony Mobile. These logs contain a wide range of personal information such as unique device IDs, your location,\ndetails regarding running applications, and events/input leading up to a crash.\nLogging is only active for a short time and automatically disabled once logging has been completed.\nLogs are uploaded when connected to Wi-Fi and automatically deleted when the upload is complete.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -209,7 +1243,7 @@ }, "com.sonymobile.anondata": { "list": "Oem", - "description": "Anonymous Usage Stats (yes just as com.sonyericsson.idd.agent but it's for other phones)\nUsed to send \"anonymous\" information about how you use your Sony Smartphone to Sony servers.\nIt remains unclear exactly how this information is anonymized.", + "description": "Anonymous Usage Stats (yes just as com.sonyericsson.idd.agent but it's for other phones)\nUsed to send\"anonymous\" information about how you use your Sony Smartphone to Sony servers.\nIt remains unclear exactly how this information is anonymized.", "dependencies": [], "neededBy": [], "labels": [], @@ -329,7 +1363,7 @@ }, "com.sonymobile.getset": { "list": "Oem", - "description": "Xperia Actions (discontinued)\nLets you automate some actions (only a few) \nhttps://support.sonymobile.com/global-en/xperiaxz/userguide/xperia-actions/\n", + "description": "Xperia Actions (discontinued)\nLets you automate some actions (only a few)\nhttps://support.sonymobile.com/global-en/xperiaxz/userguide/xperia-actions/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -377,7 +1411,7 @@ }, "com.sonymobile.indeviceintelligence": { "list": "Oem", - "description": "Xperia Intelligence Engine\nThis app is supposed to understand how you use the phone, the apps you prefer, and will suggest tips \nand options based on app usage, how often you use an app, what time of day...\nFor me this just looks like a AI bullshit app who has a huge list of permissions and launch in background at boot\nThis app performs geofencing (check if your are located in a certain perimeter, near your home for instance) \nand this doesn't looks great privacy-wise (https://en.wikipedia.org/wiki/Geo-fence)\n", + "description": "Xperia Intelligence Engine\nThis app is supposed to understand how you use the phone, the apps you prefer, and will suggest tips\nand options based on app usage, how often you use an app, what time of day...\nFor me this just looks like a AI bullshit app who has a huge list of permissions and launch in background at boot\nThis app performs geofencing (check if your are located in a certain perimeter, near your home for instance)\nand this doesn't looks great privacy-wise (https://en.wikipedia.org/wiki/Geo-fence)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -425,7 +1459,7 @@ }, "com.sonymobile.mtp.extension.fotaupdate": { "list": "Oem", - "description": "fota update service\nFOTA = Firmware Over-The-Air\nFOTA allows manufacturers to remotely install new software updates, features and services.\nGiven there is \"mtp.extension\" in the package name, I think it lets you update your phone via your PC.\nWhat's weird is that it should be called SEUS then (https://www.mobilefun.co.uk/blog/2008/06/software-updates-sony-ericsson/)", + "description": "fota update service\nFOTA = Firmware Over-The-Air\nFOTA allows manufacturers to remotely install new software updates, features and services.\nGiven there is\"mtp.extension\" in the package name, I think it lets you update your phone via your PC.\nWhat's weird is that it should be called SEUS then (https://www.mobilefun.co.uk/blog/2008/06/software-updates-sony-ericsson/)", "dependencies": [], "neededBy": [], "labels": [], @@ -481,7 +1515,7 @@ }, "com.sonymobile.prediction": { "list": "Oem", - "description": "Sony text prediction (for Sony keyboard) \nIt's only a supposition. Can someone confirm ?\n", + "description": "Sony text prediction (for Sony keyboard)\nIt's only a supposition. Can someone confirm ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -513,7 +1547,7 @@ }, "com.sonymobile.smartcharger": { "list": "Oem", - "description": "Battery Care\nDetects your charging patterns and estimates the start and end time of your regular charging period. \nThe rate of charging is controlled so that your battery reaches 100% just before you disconnect the charger.\nhttps://support.sonymobile.com/gb/xperiaxz/userguide/battery-and-power-management/\n", + "description": "Battery Care\nDetects your charging patterns and estimates the start and end time of your regular charging period.\nThe rate of charging is controlled so that your battery reaches 100% just before you disconnect the charger.\nhttps://support.sonymobile.com/gb/xperiaxz/userguide/battery-and-power-management/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -521,7 +1555,7 @@ }, "com.sonymobile.support": { "list": "Oem", - "description": "Sony Support (https://play.google.com/store/apps/details?id=com.sonymobile.support)\nUseless support app. \n", + "description": "Sony Support (https://play.google.com/store/apps/details?id=com.sonymobile.support)\nUseless support app.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -545,7 +1579,7 @@ }, "com.sonymobile.xperialounge.services": { "list": "Oem", - "description": "Xperia™ Lounge Pass service (discontinued)\nThe Xperia Lounge app was meant to provide loyal fans with various rewards for their Xperia smartphones, \nsuch as exclusive Xperia Themes and wallpapers, as well as competitions.\nhttps://www.phonearena.com/news/Sony-Xperia-Lounge-shutting-down_id118252\n", + "description": "Xperia™ Lounge Pass service (discontinued)\nThe Xperia Lounge app was meant to provide loyal fans with various rewards for their Xperia smartphones,\nsuch as exclusive Xperia Themes and wallpapers, as well as competitions.\nhttps://www.phonearena.com/news/Sony-Xperia-Lounge-shutting-down_id118252\n", "dependencies": [], "neededBy": [], "labels": [], @@ -591,14 +1625,6 @@ "labels": [], "removal": "Advanced" }, - "com.sonymobile.camera": { - "list": "Oem", - "description": "Sony camera app\n", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Advanced" - }, "com.sonyericsson.android.camera3d": { "list": "Oem", "description": "Sony camera app (on older phones)\n", @@ -793,7 +1819,7 @@ }, "com.tmobile.pr.adapt": { "list": "Carrier", - "description": "Diagnostic tool. \nThis app can see all your installed apps, that you have allowed unknown sources on, that your rooted, \nand will deny your warranty saying your rooted. It constantly runs in the background.\n", + "description": "Diagnostic tool.\nThis app can see all your installed apps, that you have allowed unknown sources on, that your rooted,\nand will deny your warranty saying your rooted. It constantly runs in the background.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -825,7 +1851,7 @@ }, "com.tmobile.vvm.application": { "list": "Carrier", - "description": "T-Mobile Visual VoiceMail (https://play.google.com/store/apps/details?id=com.tmobile.vvm.application)\nLets you use your voice mail and manage your inbox without dialing into your voicemail. \n", + "description": "T-Mobile Visual VoiceMail (https://play.google.com/store/apps/details?id=com.tmobile.vvm.application)\nLets you use your voice mail and manage your inbox without dialing into your voicemail.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -841,11 +1867,11 @@ }, "com.xiaomi.aicr": { "list": "Oem", - "description": "Mi AI Engine\nAnother app to Mi AI from MIUI China. (https://hyperosupdates.com/apps/com.xiaomi.aicr/)", + "description": "Mi AI Engine\nAnother app to Mi AI from MIUI China. Might break the ability to set wallpapers\nSee https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/issues/1110\nhttps://hyperosupdates.com/apps/com.xiaomi.aicr/", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.xiaomi.aiasst.service": { "list": "Oem", @@ -1071,6 +2097,78 @@ "labels": [], "removal": "Recommended" }, + "com.motorola.livewallpaper3.prebuilt.chroma_plume": { + "list": "Oem", + "description": "Motorola Prebuilt themes Chroma Plume", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.cool_bamboo": { + "list": "Oem", + "description": "Motorola Prebuilt themes Cool Bamboo", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.titan": { + "list": "Oem", + "description": "Motorola Prebuilt themes Cosmic journey", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.lovely_peach": { + "list": "Oem", + "description": "Motorola Prebuilt themes Lovely Peach", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.mysterious_amber": { + "list": "Oem", + "description": "Motorola Prebuilt themes Mysterious Amber", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.romantic_wisteria": { + "list": "Oem", + "description": "Motorola Prebuilt themes Romantic Wisteria", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.tranquil_whale": { + "list": "Oem", + "description": "Motorola Prebuilt themes Tranquil Whale", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.twilight_twist": { + "list": "Oem", + "description": "Motorola Prebuilt themes Twilight twist", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.motorola.livewallpaper3.prebuilt.vibrant_sapling": { + "list": "Oem", + "description": "Motorola Prebuilt themes Vibrant Sapling", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.android.connectivity.resources": { "list": "Aosp", "description": "Network connectivity resources.\nCause BOOTLOOP.", @@ -1105,7 +2203,7 @@ }, "us.com.dt.iq.appsource.tmobile": { "list": "Carrier", - "description": "App Source (discontinued)\nThis app aimed at organizing all of your existing apps on the phone by category and helping you discover \nnew apps through search and recommendations.\n", + "description": "App Source (discontinued)\nThis app aimed at organizing all of your existing apps on the phone by category and helping you discover\nnew apps through search and recommendations.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1177,7 +2275,7 @@ }, "com.LogiaGroup.LogiaDeck": { "list": "Carrier", - "description": "Mobile Services Manager\nSeems to be a spyware. \nGood explanation from someone who worked for carrier : \nhttps://www.reddit.com/r/lgv20/comments/6u0wnf/what_is_mobile_services_manager_did_i_catch_a/\n", + "description": "Mobile Services Manager\nSeems to be a spyware.\nGood explanation from someone who worked for carrier :\nhttps://www.reddit.com/r/lgv20/comments/6u0wnf/what_is_mobile_services_manager_did_i_catch_a/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1257,7 +2355,7 @@ }, "com.verizon.mips.services": { "list": "Carrier", - "description": "My Verizon Services \nRelated to My Verizon app.\nRequired for hotspot", + "description": "My Verizon Services\nRelated to My Verizon app.\nRequired for hotspot", "dependencies": [], "neededBy": [], "labels": [], @@ -1361,7 +2459,7 @@ }, "com.motorola.service.vzw.entitlement": { "list": "Carrier", - "description": "Deleting this package whill disable Hotspot functionality if you're a Verizon client. \nWhat you can do is preventing the phone from notifying the carrier about when you use hotspot :\nhttps://android.stackexchange.com/questions/226580/how-is-verizon-suddenly-tracking-my-hot-spot-usage-on-android-and-how-do-i-disab\n", + "description": "Deleting this package whill disable Hotspot functionality if you're a Verizon client.\nWhat you can do is preventing the phone from notifying the carrier about when you use hotspot :\nhttps://android.stackexchange.com/questions/226580/how-is-verizon-suddenly-tracking-my-hot-spot-usage-on-android-and-how-do-i-disab\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1393,7 +2491,7 @@ }, "com.motorola.omadm.vzw": { "list": "Carrier", - "description": "OMA Device Management for Verizon \nHandles configuration of the device (including first time use), enabling and disabling features provided by carriers.\nhttps://en.wikipedia.org/wiki/OMA_Device_Management\nI believe it's only useful if you want to use a Verizon service with a non branded phone (not sure at all)\nhttps://www.androidpolice.com/2015/03/10/android-5-1-includes-new-carrier-provisioning-api-allows-carriers-easier-methods-of-setting-up-services-on-devices-they-dont-control/\nDisplays annoying notifications if you unlocked your bootloader\n", + "description": "OMA Device Management for Verizon\nHandles configuration of the device (including first time use), enabling and disabling features provided by carriers.\nhttps://en.wikipedia.org/wiki/OMA_Device_Management\nI believe it's only useful if you want to use a Verizon service with a non branded phone (not sure at all)\nhttps://www.androidpolice.com/2015/03/10/android-5-1-includes-new-carrier-provisioning-api-allows-carriers-easier-methods-of-setting-up-services-on-devices-they-dont-control/\nDisplays annoying notifications if you unlocked your bootloader\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1409,7 +2507,7 @@ }, "com.motorola.visualvoicemail": { "list": "Carrier", - "description": "Verizon Visual Voicemail (https://play.google.com/store/apps/details?id=com.motorola.visualvoicemail)\nOn non-Verizon phones it has a generic \"Voicemail\" name and icon, and doesn't seem to active.\n", + "description": "Verizon Visual Voicemail (https://play.google.com/store/apps/details?id=com.motorola.visualvoicemail)\nOn non-Verizon phones it has a generic\"Voicemail\" name and icon, and doesn't seem to active.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1425,7 +2523,7 @@ }, "com.asurion.home.sprint.vpl": { "list": "Carrier", - "description": "Tech Expert (for VPL devices/employees) ?\nNow \"Sprint Complete\" (see below).\nNote : This app is developed by Asurion, a US company whose business is to sell insurances.\nAll US carriers use Asurion for the phone insurances.\n", + "description": "Tech Expert (for VPL devices/employees) ?\nNow\"Sprint Complete\" (see below).\nNote : This app is developed by Asurion, a US company whose business is to sell insurances.\nAll US carriers use Asurion for the phone insurances.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1433,7 +2531,7 @@ }, "com.asurion.home.sprint": { "list": "Carrier", - "description": "Sprint Protect\nSupport app (see com.asurion.android.protech.att)\n\nSprint Complete (https://play.google.com/store/apps/details?id=com.asurion.home.sprint)\nLets you call or chat with live tech experts ! Maybe you will find the love of your life ! \nNote : See note above.\n", + "description": "Sprint Protect\nSupport app (see com.asurion.android.protech.att)\n\nSprint Complete (https://play.google.com/store/apps/details?id=com.asurion.home.sprint)\nLets you call or chat with live tech experts ! Maybe you will find the love of your life !\nNote : See note above.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1441,7 +2539,7 @@ }, "com.hyperlync.Sprint.Backup": { "list": "Carrier", - "description": "Sprint Backup\" (https://play.google.com/store/apps/details?id=com.hyperlync.Sprint.Backup)\nLets you backup your phone’s content to your Sprint Backup account.\nFYI : This app is developped by Hyperlync Technologies an Israel-based company which provide cyber-security solutions. \nIt is now owned by Edition Ltd a big Singapour based company (https://www.reuters.com/companies/EDITol.SI)\n", + "description": "Sprint Backup\" (https://play.google.com/store/apps/details?id=com.hyperlync.Sprint.Backup)\nLets you backup your phone’s content to your Sprint Backup account.\nFYI : This app is developped by Hyperlync Technologies an Israel-based company which provide cyber-security solutions.\nIt is now owned by Edition Ltd a big Singapour based company (https://www.reuters.com/companies/EDITol.SI)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1537,7 +2635,7 @@ }, "com.sprint.international.message": { "list": "Carrier", - "description": "Sprint Worldwide \nJust an help page for international travelers.\n", + "description": "Sprint Worldwide\nJust an help page for international travelers.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1553,7 +2651,7 @@ }, "com.sprint.ms.cdm": { "list": "Carrier", - "description": "Sprint Device Manager\nMobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure \nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nYou should NEVER install a MDM tool on your phone. Never.\nhttps://onezero.medium.com/dont-put-your-work-email-on-your-personal-phone-ef7fef956c2f\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\n", + "description": "Sprint Device Manager\nMobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure\nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nYou should NEVER install a MDM tool on your phone. Never.\nhttps://onezero.medium.com/dont-put-your-work-email-on-your-personal-phone-ef7fef956c2f\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1561,7 +2659,7 @@ }, "com.sprint.ms.cnap": { "list": "Carrier", - "description": "Caller ID\ncnap = Caller Name Presentation (https://en.wikipedia.org/wiki/Calling_Name_Presentation)\nLets you change the name that is displayed on caller ID when making a call.\nStrange is it the same thing than \"com.sprint.ecid\" ?\n", + "description": "Caller ID\ncnap = Caller Name Presentation (https://en.wikipedia.org/wiki/Calling_Name_Presentation)\nLets you change the name that is displayed on caller ID when making a call.\nStrange is it the same thing than\"com.sprint.ecid\" ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1577,7 +2675,7 @@ }, "com.sprint.safefound.vpl": { "list": "Carrier", - "description": "Safe & Found (https://play.google.com/store/apps/details?id=com.sprint.safefound)\nMobile safety and security application that helps protect and locate your \"loved ones\". \nYou have the ability to track and manage smartphones, tablets and Tracker all in one app.\nhttps://www.sprint.com/en/support/solutions/services/safe-and-found.html\n", + "description": "Safe & Found (https://play.google.com/store/apps/details?id=com.sprint.safefound)\nMobile safety and security application that helps protect and locate your\"loved ones\".\nYou have the ability to track and manage smartphones, tablets and Tracker all in one app.\nhttps://www.sprint.com/en/support/solutions/services/safe-and-found.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1649,7 +2747,7 @@ }, "com.asurion.android.protech.att": { "list": "Carrier", - "description": "AT&T ProTech (https://play.google.com/store/apps/details?id=com.asurion.android.protech.att)\nHelp and support app. Lets you call or chat with a live U.S.-based AT&T ProTech support \"expert\".\nNote : This app is developed by Asurion, a US company whose business is to sell insurances.\nAll US carriers use Asurion for the phone insurances.\n", + "description": "AT&T ProTech (https://play.google.com/store/apps/details?id=com.asurion.android.protech.att)\nHelp and support app. Lets you call or chat with a live U.S.-based AT&T ProTech support\"expert\".\nNote : This app is developed by Asurion, a US company whose business is to sell insurances.\nAll US carriers use Asurion for the phone insurances.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1657,7 +2755,7 @@ }, "com.att.android.attsmartwifi": { "list": "Carrier", - "description": "AT&T Smart Wi-Fi (https://play.google.com/store/apps/details?id=com.att.android.attsmartwifi)\nFinds and auto-connects to available hotspots to minimize cellular data consumption.\nAuto-connects is not a good idea.\nWorth reading : \nhttps://www.europol.europa.eu/activities-services/public-awareness-and-prevention-guides/risks-of-using-public-wi-fi\nhttps://www.eff.org/deeplinks/2020/01/why-public-wi-fi-lot-safer-you-think\nYou are ok if you go on HTTPS websites.\nUse a VPN if you want to hide the domain names you visit, avoid usage restriction (no P2P, blacklisted websites...) and encrypt HTTP traffic.\n==> https://thatoneprivacysite.net/choosing-the-best-vpn-for-you/\n", + "description": "AT&T Smart Wi-Fi (https://play.google.com/store/apps/details?id=com.att.android.attsmartwifi)\nFinds and auto-connects to available hotspots to minimize cellular data consumption.\nAuto-connects is not a good idea.\nWorth reading :\nhttps://www.europol.europa.eu/activities-services/public-awareness-and-prevention-guides/risks-of-using-public-wi-fi\nhttps://www.eff.org/deeplinks/2020/01/why-public-wi-fi-lot-safer-you-think\nYou are ok if you go on HTTPS websites.\nUse a VPN if you want to hide the domain names you visit, avoid usage restriction (no P2P, blacklisted websites...) and encrypt HTTP traffic.\n==> https://thatoneprivacysite.net/choosing-the-best-vpn-for-you/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1665,7 +2763,7 @@ }, "com.att.callprotect": { "list": "Carrier", - "description": "AT&T Call Protect (https://play.google.com/store/apps/details?id=com.att.callprotect)\nSpam call blocking app provided by Hiya \nNOTE : You should never trust spam blocking apps (https://itmunch.com/robocall-caught-sending-customers-confidential-data-without-consent/)\n", + "description": "AT&T Call Protect (https://play.google.com/store/apps/details?id=com.att.callprotect)\nSpam call blocking app provided by Hiya\nNOTE : You should never trust spam blocking apps (https://itmunch.com/robocall-caught-sending-customers-confidential-data-without-consent/)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1689,7 +2787,7 @@ }, "com.att.dtv.shaderemote": { "list": "Carrier", - "description": "DIRECTV Remote App (https://play.google.com/store/apps/details?id=com.att.dtv.shaderemote)\nLets you control DIRECTV HD receivers in your home that are connected to Internet, from your phone.\nFYI : DIRECTV is a subsidiary of AT&T \nWorth reading : https://en.wikipedia.org/wiki/DirecTV#Consumer_protection_lawsuits_and_violations\n", + "description": "DIRECTV Remote App (https://play.google.com/store/apps/details?id=com.att.dtv.shaderemote)\nLets you control DIRECTV HD receivers in your home that are connected to Internet, from your phone.\nFYI : DIRECTV is a subsidiary of AT&T\nWorth reading : https://en.wikipedia.org/wiki/DirecTV#Consumer_protection_lawsuits_and_violations\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1697,7 +2795,7 @@ }, "com.att.iqi": { "list": "Carrier", - "description": "Carrier IQ / Device Health \nGathers, stores and forwards diagnostic measurements on its behalf (see https://en.wikipedia.org/wiki/Carrier_IQ)\nGreat ! A rootkit : https://en.wikipedia.org/wiki/Carrier_IQ#Rootkit_discovery_and_media_attention\n", + "description": "Carrier IQ / Device Health\nGathers, stores and forwards diagnostic measurements on its behalf (see https://en.wikipedia.org/wiki/Carrier_IQ)\nGreat ! A rootkit : https://en.wikipedia.org/wiki/Carrier_IQ#Rootkit_discovery_and_media_attention\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1753,7 +2851,7 @@ }, "com.att.tv.watchtv": { "list": "Carrier", - "description": "AT&T WatchTV (https://play.google.com/store/apps/details?id=com.att.tv.watchtv)\nLets you stream TV live and VOD form your phone.\nNo it's not the same thing than AT&T TV. Yes it's a mess. \nDifferences with AT&T TV : https://www.cordcuttersnews.com/att-tv-vs-att-tv-now-whats-the-difference/\n", + "description": "AT&T WatchTV (https://play.google.com/store/apps/details?id=com.att.tv.watchtv)\nLets you stream TV live and VOD form your phone.\nNo it's not the same thing than AT&T TV. Yes it's a mess.\nDifferences with AT&T TV : https://www.cordcuttersnews.com/att-tv-vs-att-tv-now-whats-the-difference/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1761,7 +2859,7 @@ }, "com.matchboxmobile.wisp": { "list": "Carrier", - "description": "AT&T Hot Spots\nRun in background. Automatically connects you to a free AT&T wifi hotspot at one of their participating partner locations \nsuch as Starbucks.\n", + "description": "AT&T Hot Spots\nRun in background. Automatically connects you to a free AT&T wifi hotspot at one of their participating partner locations\nsuch as Starbucks.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1769,7 +2867,7 @@ }, "com.dti.att": { "list": "Carrier", - "description": "AT&T App Select\nI guess it lets you choose AT&T apps to install.\nIt has a LOT of permissions : https://knowledge.protektoid.com/apps/com.dti.att/7a36d4f5f00bae044566221400719c75ea2f4f33bc2578a7f8210f36d718a8d6\nSomeone knows what \"dti\" is/means ?\n", + "description": "AT&T App Select\nI guess it lets you choose AT&T apps to install.\nIt has a LOT of permissions : https://knowledge.protektoid.com/apps/com.dti.att/7a36d4f5f00bae044566221400719c75ea2f4f33bc2578a7f8210f36d718a8d6\nSomeone knows what\"dti\" is/means ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -1993,7 +3091,7 @@ }, "fr.orange.cineday": { "list": "Carrier", - "description": "Orange cineday (https://play.google.com/store/apps/details?id=fr.orange.cineday)\nUseless app but cineday is pretty nice. \nEvery tuesday you can invite the person of your choice in movies (within the limit of available seats).\nYou can just use https://cineday.orange.fr/cineday/\n", + "description": "Orange cineday (https://play.google.com/store/apps/details?id=fr.orange.cineday)\nUseless app but cineday is pretty nice.\nEvery tuesday you can invite the person of your choice in movies (within the limit of available seats).\nYou can just use https://cineday.orange.fr/cineday/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2053,7 +3151,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.hwmirror": { "list": "Oem", @@ -2065,7 +3163,7 @@ }, "com.baidu.input_huawei": { "list": "Oem", - "description": "Woh! 51 permissions! \nHuawei chinese stock input keyboard. You probably shouldn't trust this closed-source keyboard with this much permissions...NOTE: Make sure to have another keyboard installed before removing this package!\n", + "description": "Woh! 51 permissions!\nHuawei chinese stock input keyboard. You probably shouldn't trust this closed-source keyboard with this much permissions...NOTE: Make sure to have another keyboard installed before removing this package!\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2097,7 +3195,7 @@ }, "com.huawei.android.chr": { "list": "Oem", - "description": "HwChrService\nHuawei Call History Record. \n", + "description": "HwChrService\nHuawei Call History Record.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2209,7 +3307,7 @@ }, "com.huawei.android.remotecontroller": { "list": "Oem", - "description": "Huawei Smart Controller app.\nLets you you add, customize, and set up remote controls, allowing control of your electronic appliances through your phone. \n", + "description": "Huawei Smart Controller app.\nLets you you add, customize, and set up remote controls, allowing control of your electronic appliances through your phone.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2233,7 +3331,7 @@ }, "com.huawei.android.wfdirect": { "list": "Oem", - "description": "Wi-Fi Direct feature.\nNote: Wifi direct enables devices to establish a direct Wi-Fi connection (without a router) over which the two can send and receive files. \n", + "description": "Wi-Fi Direct feature.\nNote: Wifi direct enables devices to establish a direct Wi-Fi connection (without a router) over which the two can send and receive files.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2329,7 +3427,7 @@ }, "com.huawei.desktop.explorer": { "list": "Oem", - "description": "From XDA thread : \"Service that is been used when you wanna use your phone as an operative system on a PC.\"\nI don't understand what does it mean.\n", + "description": "From XDA thread :\"Service that is been used when you wanna use your phone as an operative system on a PC.\"\nI don't understand what does it mean.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2377,7 +3475,7 @@ }, "com.huawei.geofence": { "list": "Oem", - "description": "GeofenceService.\nAllows you to do something when a user enters an area that has been defined as a trigger.\nA geofence is a virtual perimeter set on a real geographic area. Combining a user position with a geofence perimeter, \nit is possible to know if the user is inside or outside the geofence or even if he is exiting or entering the area.\n", + "description": "GeofenceService.\nAllows you to do something when a user enters an area that has been defined as a trigger.\nA geofence is a virtual perimeter set on a real geographic area. Combining a user position with a geofence perimeter,\nit is possible to know if the user is inside or outside the geofence or even if he is exiting or entering the area.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2427,7 +3525,7 @@ }, "com.huawei.hiassistantoversea": { "list": "Oem", - "description": "HiVoice. Huawei's voice assistant to replace \"Hey Google\"\n", + "description": "HiVoice. Huawei's voice assistant to replace\"Hey Google\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2579,7 +3677,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.huawei.mycenter": { "list": "Oem", @@ -2631,7 +3729,7 @@ }, "com.huawei.imedia.sws": { "list": "Oem", - "description": "Huawei Histen\nAudio 3D effects found in the settings. Safe to remove if you don't use these settings.", + "description": "Huawei Histen\nAudio 3D effects found in the settings. Safe to remove if you don't use these settings.\nCauses an audio glitch after the first reboot following the uninstallation or disabling of this package.\nWhen you start or resume playing any audio content in any media application, the sound volume initially sets to maximum for half a second, then normalizes.\nAffects only external audio devices with any connection type.", "dependencies": [], "neededBy": [], "labels": [], @@ -2672,7 +3770,9 @@ "com.huawei.health": { "list": "Oem", "description": "Huawei Health (discontinued?)\nConnect Huawei wearables to your phone and all sorts of stats like all fitness tracking apps.\nRequire HMS.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -2687,7 +3787,7 @@ }, "com.huawei.mirrorlink": { "list": "Oem", - "description": "Huawei Mirror app. \nMirror like \"Glass\"\n\nHuawei mirrorlink implementation\nUsed to connect your phone to a car (with https://mirrorlink.com/ support) in order to provide audio streaming, GPS navigation...\n", + "description": "Huawei Mirror app.\nMirror like\"Glass\"\n\nHuawei mirrorlink implementation\nUsed to connect your phone to a car (with https://mirrorlink.com/ support) in order to provide audio streaming, GPS navigation...\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2743,7 +3843,7 @@ }, "com.huawei.stylus.floatmenu": { "list": "Oem", - "description": "AI Lens. Shop for objects that you take a picture of. This de-clutters the camera interface by removing the AI Lens button on the top left corner and does not break the AR Measure app.\n \nFloating menu with M-Pen feature.\n", + "description": "AI Lens. Shop for objects that you take a picture of. This de-clutters the camera interface by removing the AI Lens button on the top left corner and does not break the AR Measure app.\n\nFloating menu with M-Pen feature.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2767,7 +3867,7 @@ }, "com.huawei.trustagent": { "list": "Oem", - "description": "Smart unlock feature.\nEnables you to unlock your phone with a Bluetooth device, like a smart band. \nWhen a compatible Bluetooth device is detected, you can unlock your phone with a simple swipe (without a password).\n", + "description": "Smart unlock feature.\nEnables you to unlock your phone with a Bluetooth device, like a smart band.\nWhen a compatible Bluetooth device is detected, you can unlock your phone with a simple swipe (without a password).\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2815,7 +3915,7 @@ }, "com.iflytek.speechsuite": { "list": "Oem", - "description": "Default voice input method from iflytek, a big chinese company (https://en.wikipedia.org/wiki/IFlytek)\nIFLytek was implicated in human rights violations : \nhttps://asia.nikkei.com/Economy/Trade-war/US-sanctions-8-China-tech-companies-over-role-in-Xinjiang-abuses\nArchive: https://web.archive.org/save/https://asia.nikkei.com/Economy/Trade-war/US-sanctions-8-China-tech-companies-over-role-in-Xinjiang-abuses\n", + "description": "Default voice input method from iflytek, a big chinese company (https://en.wikipedia.org/wiki/IFlytek)\nIFLytek was implicated in human rights violations :\nhttps://asia.nikkei.com/Economy/Trade-war/US-sanctions-8-China-tech-companies-over-role-in-Xinjiang-abuses\nArchive: https://web.archive.org/save/https://asia.nikkei.com/Economy/Trade-war/US-sanctions-8-China-tech-companies-over-role-in-Xinjiang-abuses\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2823,7 +3923,7 @@ }, "com.nuance.swype.emui": { "list": "Oem", - "description": "Huawei Swype functions.\nIs it the full Swype keyboard or only the Swype function on Huawei keyboard ? \nNOTE : Nuance company said it would discontinue support of the Swype keyboard app.\n", + "description": "Huawei Swype functions.\nIs it the full Swype keyboard or only the Swype function on Huawei keyboard ?\nNOTE : Nuance company said it would discontinue support of the Swype keyboard app.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2839,7 +3939,7 @@ }, "com.huawei.KoBackup": { "list": "Oem", - "description": "As of writing this, Huawei phones cannot be rooted. \nThis Backup application is probably able to backup more than any other 3rd party backup app.\n", + "description": "As of writing this, Huawei phones cannot be rooted.\nThis Backup application is probably able to backup more than any other 3rd party backup app.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -2975,7 +4075,7 @@ }, "com.huawei.securitymgr": { "list": "Oem", - "description": "PrivateSpace\nLets you store private information in a hidden space within your device that can only be accessed \nwith your fingerprint or password.\nTODO: Data at rest encryption? If not, this is useless\nhttps://consumer.huawei.com/en/support/content/en-us00754246/)\nThis is the password vault or password manager too.", + "description": "PrivateSpace\nLets you store private information in a hidden space within your device that can only be accessed\nwith your fingerprint or password.\nTODO: Data at rest encryption? If not, this is useless\nhttps://consumer.huawei.com/en/support/content/en-us00754246/)\nThis is the password vault or password manager too.", "dependencies": [], "neededBy": [], "labels": [], @@ -2991,7 +4091,7 @@ }, "com.lenovo.lsf.user": { "list": "Oem", - "description": "Lenovo ID adds an option in Settings>Accounts where you can login to a Lenovo ID account.\nFeatures include \"exclusive features directly from Lenovo and our partners\" and \"syncing users information across devices\"\nlsf = Lenovo Service Framework\n", + "description": "Lenovo ID adds an option in Settings>Accounts where you can login to a Lenovo ID account.\nFeatures include\"exclusive features directly from Lenovo and our partners\" and\"syncing users information across devices\"\nlsf = Lenovo Service Framework\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3007,7 +4107,7 @@ }, "com.motorola.android.fmradio": { "list": "Oem", - "description": "FMRadioService \nRequired by \"com.motorola.fmplayer\"\n", + "description": "FMRadioService\nRequired by\"com.motorola.fmplayer\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3031,7 +4131,7 @@ }, "com.motorola.android.providers.chromehomepage": { "list": "Oem", - "description": "Seems to provide the \"Home\"-button functionality in Chrome.\nhttps://forum.xda-developers.com/android/apps-games/app-chrome-homepage-t3695804", + "description": "Seems to provide the\"Home\"-button functionality in Chrome.\nhttps://forum.xda-developers.com/android/apps-games/app-chrome-homepage-t3695804", "dependencies": [], "neededBy": [], "labels": [], @@ -3039,7 +4139,7 @@ }, "com.motorola.android.provisioning": { "list": "Oem", - "description": "OMA Client Provisioning\nIt is a protocol specified by the Open Mobile Alliance (OMA).\nIt is used by carrier to send \"configuration SMS\" which can setup network settings (such as APN).\nIn my case, it was automatic and I never needed configuration messages. I'm pretty sure that in France this package is useless.\nMaybe it's useful if carriers change their APN... but you still can change it manually, it's not difficult.\n#\nNote : These special \"confirguration SMS\" can be abused : \nhttps://www.zdnet.fr/actualites/les-smartphones-samsung-huawei-lg-et-sony-vulnerables-a-des-attaques-par-provisioning-39890045.htm\nhttps://www.csoonline.com/article/3435729/sms-based-provisioning-messages-enable-advanced-phishing-on-android-phones.html\n", + "description": "OMA Client Provisioning\nIt is a protocol specified by the Open Mobile Alliance (OMA).\nIt is used by carrier to send\"configuration SMS\" which can setup network settings (such as APN).\nIn my case, it was automatic and I never needed configuration messages. I'm pretty sure that in France this package is useless.\nMaybe it's useful if carriers change their APN... but you still can change it manually, it's not difficult.\n#\nNote : These special\"confirguration SMS\" can be abused :\nhttps://www.zdnet.fr/actualites/les-smartphones-samsung-huawei-lg-et-sony-vulnerables-a-des-attaques-par-provisioning-39890045.htm\nhttps://www.csoonline.com/article/3435729/sms-based-provisioning-messages-enable-advanced-phishing-on-android-phones.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3063,7 +4163,7 @@ }, "com.motorola.appdirectedsmsproxy": { "list": "Oem", - "description": "An Application directed SMS (or rather a Port directed SMS) is an SMS directed to a specific port. \nApps need to listen to this port to get the SMS message.\nI don't know if this package allows port directed SMS or if it just provide a proxy feature.\n", + "description": "An Application directed SMS (or rather a Port directed SMS) is an SMS directed to a specific port.\nApps need to listen to this port to get the SMS message.\nI don't know if this package allows port directed SMS or if it just provide a proxy feature.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3103,7 +4203,7 @@ }, "com.motorola.ccc.devicemanagement": { "list": "Oem", - "description": "Mobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure \nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nYou should NEVER install a MDM tool on your phone. Never.\nhttps://onezero.medium.com/dont-put-your-work-email-on-your-personal-phone-ef7fef956c2f\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\n", + "description": "Mobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure\nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nYou should NEVER install a MDM tool on your phone. Never.\nhttps://onezero.medium.com/dont-put-your-work-email-on-your-personal-phone-ef7fef956c2f\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3207,7 +4307,7 @@ }, "com.motorola.lifetimedata": { "list": "Oem", - "description": "It's most likely the Total Call Timer or more generally it handles info like the date of manufacture of your device,\nusage time since first boot etc... \nTotal Call Timer gives you the time you spent calling.\nIt's surely a hidden menu.", + "description": "It's most likely the Total Call Timer or more generally it handles info like the date of manufacture of your device,\nusage time since first boot etc...\nTotal Call Timer gives you the time you spent calling.\nIt's surely a hidden menu.", "dependencies": [], "neededBy": [], "labels": [], @@ -3223,7 +4323,7 @@ }, "com.motorola.moto": { "list": "Oem", - "description": "Moto (https://play.google.com/store/apps/details?id=com.motorola.moto)\nApp providing Moto Actions, Moto Display, and other feature families that let you customize the way you interact with your device. \nMoto Actions is another app (https://play.google.com/store/apps/details?id=com.motorola.actions). Gestures set with \"Moto\" prior will continue to work provided \"Moto Actions\" remains installed.\n", + "description": "Moto (https://play.google.com/store/apps/details?id=com.motorola.moto)\nApp providing Moto Actions, Moto Display, and other feature families that let you customize the way you interact with your device.\nMoto Actions is another app (https://play.google.com/store/apps/details?id=com.motorola.actions). Gestures set with\"Moto\" prior will continue to work provided\"Moto Actions\" remains installed.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3231,7 +4331,7 @@ }, "com.motorola.motocare": { "list": "Oem", - "description": "Moto Care was renamed in \"Moto Help\" and then in \"Device Help\"\nProvide support features.\nhttps://mobile.softpedia.com/blog/Moto-Care-App-Gets-Updated-Now-Called-Motorola-Help-432827.shtml\nHowever you can both have com.motorola.genie (Device Help) and this package so it's strange.\n", + "description": "Moto Care was renamed in\"Moto Help\" and then in\"Device Help\"\nProvide support features.\nhttps://mobile.softpedia.com/blog/Moto-Care-App-Gets-Updated-Now-Called-Motorola-Help-432827.shtml\nHowever you can both have com.motorola.genie (Device Help) and this package so it's strange.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3263,7 +4363,7 @@ }, "com.motorola.paks": { "list": "Oem", - "description": "ADB: Package Protected.\nMy Q Paks \nThird-party application bundles\nhttps://www.financialmirror.com/2007/10/31/motorola-packs-moto-q-9h-global-smart-device-with-third-party-applications/\n", + "description": "ADB: Package Protected.\nMy Q Paks\nThird-party application bundles\nhttps://www.financialmirror.com/2007/10/31/motorola-packs-moto-q-9h-global-smart-device-with-third-party-applications/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3279,7 +4379,7 @@ }, "com.motorola.ptt.prip": { "list": "Oem", - "description": "Prip (https://play.google.com/store/apps/details?id=com.motorola.ptt.prip)\nPush-To-Talk app. Allows to you send calls over any wireless carrier’s 3G or 4G networks or a WiFi connection.\nIt offers unlimited calling between other users and Nextel phone owners, rather than universal calling credit, \nand works on a monthly subscription basis.\nhttps://prip.me/#get\nNo longer in Android 10 image\n", + "description": "Prip (https://play.google.com/store/apps/details?id=com.motorola.ptt.prip)\nPush-To-Talk app. Allows to you send calls over any wireless carrier’s 3G or 4G networks or a WiFi connection.\nIt offers unlimited calling between other users and Nextel phone owners, rather than universal calling credit,\nand works on a monthly subscription basis.\nhttps://prip.me/#get\nNo longer in Android 10 image\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3287,11 +4387,11 @@ }, "com.motorola.setup": { "list": "Oem", - "description": "Related to Motorola Account setup (only during first boot ?)\nSafe to remove according to xda users.\n", + "description": "Related to Motorola Account setup (only during first boot?) DO NOT REMOVE unless you don't care about security patches. Freezing this package completely halts Google Play System Updates (Project Mainline), preventing the device from receiving security fixes.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.motorola.slpc_sys": { "list": "Oem", @@ -3319,7 +4419,7 @@ }, "com.motorola.actions": { "list": "Oem", - "description": "Moto Actions (https://play.google.com/store/apps/details?id=com.motorola.actions)\nAllows you to perform specific gestures to perform certain tasks. Frontend to change settings provided by \"com.motorola.moto\".\n", + "description": "Moto Actions (https://play.google.com/store/apps/details?id=com.motorola.actions)\nAllows you to perform specific gestures to perform certain tasks. Frontend to change settings provided by\"com.motorola.moto\".\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3359,7 +4459,7 @@ }, "com.motorola.entitlement": { "list": "Oem", - "description": "Enable WiFi tethering/hotspot functionality. \nWhat you can do is preventing the phone from notifying the carrier about when you use hotspot. It will bypass mobile carriers tethering restrictions.\nFrom an ADB shell : settings put global tether_dun_required 0\n", + "description": "Enable WiFi tethering/hotspot functionality.\nWhat you can do is preventing the phone from notifying the carrier about when you use hotspot. It will bypass mobile carriers tethering restrictions.\nFrom an ADB shell : settings put global tether_dun_required 0\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3415,7 +4515,7 @@ }, "com.motorola.launcher.secondarydisplay": { "list": "Oem", - "description": "Appears to enable support for a secondary display with Moto's launcher.\nTrying to remove this packages returns \"Failure: package is non-disable\".", + "description": "Appears to enable support for a secondary display with Moto's launcher.\nTrying to remove this packages returns\"Failure: package is non-disable\".", "dependencies": [], "neededBy": [], "labels": [], @@ -3455,7 +4555,7 @@ }, "com.motorola.pgmsystem2": { "list": "Oem", - "description": "Appears safe to remove\nPGM System\nI didn't find info about this package. \nFor Me PGM = Peak Gate Power (for MOSFET transistor) but I'm not convinced it has this meaning here.\n", + "description": "Appears safe to remove\nPGM System\nI didn't find info about this package.\nFor Me PGM = Peak Gate Power (for MOSFET transistor) but I'm not convinced it has this meaning here.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3463,7 +4563,7 @@ }, "com.motorola.systemserver": { "list": "Oem", - "description": "Moto Service Experience, debugging app.", + "description": "Moto Service Experience, debugging app.\nKeep this package for consistent Moto Fast Flashlight Gesture Functionality.", "dependencies": [], "neededBy": [], "labels": [], @@ -3535,7 +4635,7 @@ }, "com.aura.oobe.samsung.gl": { "list": "Carrier", - "description": "AppCloud\nIt offers the \"Aura Out-Of-the-Box Experience\" (OOBE)\nIt is some kind of post-install recommended apps setup from the carrier. Asks for your age and gender and then recommends you to install popular apps.\nDeveloped by IronSource, an Israeli advertising company.\nhttps://en.wikipedia.org/wiki/IronSource\nhttps://aura.ironsrc.com/tools/drive-app-downloads/\nhttps://arxiv.org/pdf/2010.10088.pdf\nHas way too many permissions.\nSee https://github.com/0x192/universal-android-debloater/issues/278", + "description": "AppCloud\nIt offers the\"Aura Out-Of-the-Box Experience\" (OOBE)\nIt is some kind of post-install recommended apps setup from the carrier. Asks for your age and gender and then recommends you to install popular apps.\nDeveloped by IronSource, an Israeli advertising company (now owned by the American company Unity).\nhttps://en.wikipedia.org/wiki/IronSource\nhttps://aura.ironsrc.com/tools/drive-app-downloads/\nhttps://arxiv.org/pdf/2010.10088.pdf\nHas way too many permissions.\nSee https://github.com/0x192/universal-android-debloater/issues/278\nhttps://docs.samsungknox.com/admin/knox-platform-for-enterprise/knox-service-plugin/kbas/kba-954-unable-to-access-home-screen/\nhttps://smex.org/invasive-israeli-software-is-harvesting-data-from-samsung-users-in-wana/\nhttps://investors.unity.com/news/news-details/2022/Unity-Announces-Merger-Agreement-with-ironSource/default.aspx", "dependencies": [], "neededBy": [], "labels": [], @@ -3543,20 +4643,12 @@ }, "com.aura.oobe.samsung": { "list": "Carrier", - "description": "AppCloud\nIt offers the \"Aura Out-Of-the-Box Experience\" (OOBE)\nIt is some kind of post-install recommended apps setup from the carrier. Asks for your age and gender and then recommends you to install popular apps.\nDeveloped by IronSource, an Israeli advertising company.\nhttps://en.wikipedia.org/wiki/IronSource\nhttps://aura.ironsrc.com/tools/drive-app-downloads/\nhttps://arxiv.org/pdf/2010.10088.pdf\nHas way too many permissions.\nSee https://github.com/0x192/universal-android-debloater/issues/278", + "description": "AppCloud\nIt offers the\"Aura Out-Of-the-Box Experience\" (OOBE)\nIt is some kind of post-install recommended apps setup from the carrier. Asks for your age and gender and then recommends you to install popular apps.\nDeveloped by IronSource, an Israeli advertising company (now owned by the American company Unity).\nhttps://en.wikipedia.org/wiki/IronSource\nhttps://aura.ironsrc.com/tools/drive-app-downloads/\nhttps://arxiv.org/pdf/2010.10088.pdf\nHas way too many permissions.\nSee https://github.com/0x192/universal-android-debloater/issues/278\nhttps://docs.samsungknox.com/admin/knox-platform-for-enterprise/knox-service-plugin/kbas/kba-954-unable-to-access-home-screen/\nhttps://smex.org/invasive-israeli-software-is-harvesting-data-from-samsung-users-in-wana/\nhttps://investors.unity.com/news/news-details/2022/Unity-Announces-Merger-Agreement-with-ironSource/default.aspx\nhttps://beta.pithus.org/report/9f8ff7db0924711be9a8a238beafecde84f42f3f249dfd9acfbe6cab390994b5\nhttps://www.virustotal.com/gui/file/9f8ff7db0924711be9a8a238beafecde84f42f3f249dfd9acfbe6cab390994b5", "dependencies": [], "neededBy": [], "labels": [], "removal": "Recommended" }, - "com.cnn.mobile.android.phone.edgepanel": { - "list": "Misc", - "description": "TCL version of Parental Center, a parental control app.", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Advanced" - }, "com.cnn.mobile.android.phone.edgepanel": { "list": "Oem", "description": "CNN Edge panel. Twitter trends, and news from CNN.\n", @@ -3567,7 +4659,7 @@ }, "com.enhance.gameservice": { "list": "Oem", - "description": "Legacy game Optimizing Service (was replaced by com.samsung.android.game.gos)\nIs supposed to \"improve\" game performance.\n", + "description": "Legacy game Optimizing Service (was replaced by com.samsung.android.game.gos)\nIs supposed to\"improve\" game performance.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3591,7 +4683,7 @@ }, "com.knox.vpn.proxyhandler": { "list": "Oem", - "description": "Samsung Knox allows business and personal content to \"securely\" coexist on the same handset.\nThis package handles proxies alongside KNOX.", + "description": "Samsung Knox allows business and personal content to\"securely\" coexist on the same handset.\nThis package handles proxies alongside KNOX.", "dependencies": [], "neededBy": [], "labels": [], @@ -3607,7 +4699,7 @@ }, "com.mobeam.barcodeService": { "list": "Oem", - "description": "The Beaming Service enables your device to beam (relay) barcodes, as found on digital coupons, event tickets, library cards, loyalty \ncards and membership cards to 1D red laser and Image based scanners prevalent at nearly every retail store and checkout stand around the world.\nMobeam is a 3-party (https://mobeam.com/)\n", + "description": "The Beaming Service enables your device to beam (relay) barcodes, as found on digital coupons, event tickets, library cards, loyalty\ncards and membership cards to 1D red laser and Image based scanners prevalent at nearly every retail store and checkout stand around the world.\nMobeam is a 3-party (https://mobeam.com/)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3631,7 +4723,7 @@ }, "com.samsung.accessory": { "list": "Oem", - "description": "Samsung Accessory Service (https://play.google.com/store/apps/details?id=com.samsung.accessory)\nLets you transfer data between your Samsung phone and Samsung accessories (GALAXY Gear/Watch...) \n", + "description": "Samsung Accessory Service (https://play.google.com/store/apps/details?id=com.samsung.accessory)\nLets you transfer data between your Samsung phone and Samsung accessories (GALAXY Gear/Watch...)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3695,7 +4787,7 @@ }, "com.samsung.android.app.advsounddetector": { "list": "Oem", - "description": "Samsung Sound detectors\nUses microphone to identify recognizable sounds. For example, if it recognizes a baby's cry, it can alert you with flashing lights so \nyou know to check on your baby. Or it can notify you if it hears the doorbell ring so you know to open the door.\n#\nadv maybe refers to 'Samsung Advanced Institute of Technology' (or simply means 'advanced')\n", + "description": "Samsung Sound detectors\nUses microphone to identify recognizable sounds. For example, if it recognizes a baby's cry, it can alert you with flashing lights so\nyou know to check on your baby. Or it can notify you if it hears the doorbell ring so you know to open the door.\n#\nadv maybe refers to 'Samsung Advanced Institute of Technology' (or simply means 'advanced')\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3711,7 +4803,7 @@ }, "com.samsung.android.app.assistantmenu": { "list": "Oem", - "description": "Assistant menu\nDesigned for individuals with motor control or other physical impairments. \nBy using Assistant menu, you can access hardware buttons and all parts of the screen by simply tapping or swiping.\nhttps://www.samsung.com/uk/accessibility/mobile-assistant-menu/\n", + "description": "Assistant menu\nDesigned for individuals with motor control or other physical impairments.\nBy using Assistant menu, you can access hardware buttons and all parts of the screen by simply tapping or swiping.\nhttps://www.samsung.com/uk/accessibility/mobile-assistant-menu/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3727,7 +4819,7 @@ }, "com.samsung.android.app.camera.sticker.facearframe.preload": { "list": "Oem", - "description": "Frames sticker? \nI don't know what this sticker is and I don't have this package.\n", + "description": "Frames sticker?\nI don't know what this sticker is and I don't have this package.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3743,7 +4835,7 @@ }, "com.samsung.android.app.cocktailbarservice": { "list": "Oem", - "description": "Edge screen/panels\nEnables you to open your five most used apps by simply swiping the edge of the screen.\nSwipe one of the edges of the screen to bring up information even when your device is locked (with the screen off). \nYou can also set it up to display the news or weather, for example.\n", + "description": "Edge screen/panels\nEnables you to open your five most used apps by simply swiping the edge of the screen.\nSwipe one of the edges of the screen to bring up information even when your device is locked (with the screen off).\nYou can also set it up to display the news or weather, for example.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3751,7 +4843,7 @@ }, "com.samsung.android.app.color": { "list": "Oem", - "description": "Color adjustment\nSamsung's adaptive super AMOLED screen optimizes the color range, saturation, and sharpness of the picture depending on what you're watching or doing. \nThis package lets you to manually customize the color settings to match your preferences.\n", + "description": "Color adjustment\nSamsung's adaptive super AMOLED screen optimizes the color range, saturation, and sharpness of the picture depending on what you're watching or doing.\nThis package lets you to manually customize the color settings to match your preferences.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3775,7 +4867,7 @@ }, "com.samsung.android.app.filterinstaller": { "list": "Oem", - "description": "Filter installer\nI have no clue about the usefulness of this package. Maybe it filters apps that are not compatible with the phone.\nThis package is only triggered when you install an app (private class PackageIntentReceiver) \n", + "description": "Filter installer\nI have no clue about the usefulness of this package. Maybe it filters apps that are not compatible with the phone.\nThis package is only triggered when you install an app (private class PackageIntentReceiver)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3783,7 +4875,7 @@ }, "com.samsung.app.highlightplayer": { "list": "Oem", - "description": "Samsung Story Video Editor\nLets you edit your videos stories \n", + "description": "Samsung Story Video Editor\nLets you edit your videos stories\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3807,7 +4899,7 @@ }, "com.samsung.android.app.omcagent": { "list": "Oem", - "description": "Open Market Customization Agent (AKA 'Recommended Apps')\nInstalls more Samsung \"Recommended Apps\" after device setup.", + "description": "Open Market Customization Agent (AKA 'Recommended Apps')\nInstalls more Samsung\"Recommended Apps\" after device setup. Similar to com.samsung.android.mapsagent", "dependencies": [], "neededBy": [], "labels": [], @@ -3839,7 +4931,7 @@ }, "com.samsung.android.app.news": { "list": "Oem", - "description": "News Samsung app\nDoesn't exist anymore? \n", + "description": "News Samsung app\nDoesn't exist anymore?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3887,7 +4979,7 @@ }, "com.samsung.android.app.sbrowseredge": { "list": "Oem", - "description": "Related to internet browser. For Galaxy Edge? \n", + "description": "Related to internet browser. For Galaxy Edge?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -3927,7 +5019,7 @@ }, "com.samsung.android.app.storyalbumwidget": { "list": "Oem", - "description": "The Story Album widget enables you to access the Story Album app and create digital picture albums that you can view and acess directly \nfrom the widget on a Home screen.\nOld feature (from Galaxy S4)\n", + "description": "The Story Album widget enables you to access the Story Album app and create digital picture albums that you can view and acess directly\nfrom the widget on a Home screen.\nOld feature (from Galaxy S4)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4007,7 +5099,7 @@ }, "com.samsung.android.aremoji": { "list": "Oem", - "description": "AR Emoji mode for Samsung camera \nhttps://www.samsung.com/global/galaxy/what-is/ar-emoji/\n", + "description": "AR Emoji mode for Samsung camera\nhttps://www.samsung.com/global/galaxy/what-is/ar-emoji/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4023,7 +5115,7 @@ }, "com.samsung.android.asksmanager": { "list": "Oem", - "description": "Samsung device protection manager.\nIt's anti-theft feature. I couldn't find exactly what does the samsung layer to the already existing android device protection : \nhttps://www.greenbot.com/article/2904397/everything-you-need-to-know-about-device-protection-in-android-51.html\n", + "description": "Samsung device protection manager.\nIt's anti-theft feature. I couldn't find exactly what does the samsung layer to the already existing android device protection :\nhttps://www.greenbot.com/article/2904397/everything-you-need-to-know-about-device-protection-in-android-51.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4071,7 +5163,7 @@ }, "com.samsung.android.beaconmanager": { "list": "Oem", - "description": "Replaced by Samsung Smart Things (com.samsung.android.ststub)\nAllows users to control, automate, and monitor their home environment via mobile device. \nhttps://en.wikipedia.org/wiki/SmartThings\n", + "description": "Replaced by Samsung Smart Things (com.samsung.android.ststub)\nAllows users to control, automate, and monitor their home environment via mobile device.\nhttps://en.wikipedia.org/wiki/SmartThings\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4103,7 +5195,7 @@ }, "com.samsung.android.coreapps": { "list": "Oem", - "description": "Samsung Enhanced features\nFiles and profiles sharing feature. It may be called \"Enhanced messaging\".\nUsing this service lets Samsung to automatically collect your phone number, contact list and messages\nhttps://forums.androidcentral.com/samsung-galaxy-s6-edge/523172-enhanced-features.html\nhttps://www.samsung.com/za/support/mobile-devices/what-is-enhanced-messaging/\n", + "description": "Samsung Enhanced features\nFiles and profiles sharing feature. It may be called\"Enhanced messaging\".\nUsing this service lets Samsung to automatically collect your phone number, contact list and messages\nhttps://forums.androidcentral.com/samsung-galaxy-s6-edge/523172-enhanced-features.html\nhttps://www.samsung.com/za/support/mobile-devices/what-is-enhanced-messaging/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4119,7 +5211,7 @@ }, "com.samsung.android.dlp.service": { "list": "Oem", - "description": "SamsungDLPService (KNOX). Old feature. Was replaced by SDP (Sensitive Data Protection)\nData Loss Prevention (DLP) feature\nSDP is good because it allows to have encrypted data at rest (= decryption keys not in RAM) even when your phone is on.\nhttps://docs.samsungknox.com/admin/whitepaper/kpe/sensitive-data-protection.htm \nhttps://docs.samsungknox.com/knox-platform-for-enterprise/admin-guide/sensitive-data-protection.htm\n", + "description": "SamsungDLPService (KNOX). Old feature. Was replaced by SDP (Sensitive Data Protection)\nData Loss Prevention (DLP) feature\nSDP is good because it allows to have encrypted data at rest (= decryption keys not in RAM) even when your phone is on.\nhttps://docs.samsungknox.com/admin/whitepaper/kpe/sensitive-data-protection.htm\nhttps://docs.samsungknox.com/knox-platform-for-enterprise/admin-guide/sensitive-data-protection.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4127,15 +5219,15 @@ }, "com.samsung.android.dqagent": { "list": "Oem", - "description": "Samsung Device Quality Agent\nMonitors how the device uses wifi. Has the ability to identify network operator related data.\nFound mention of some packages in the Java code:\n- com.samsung.android.app.mobiledoctor (https://play.google.com/store/apps/details?id=com.samsung.heartwiseVcr)\n- com.samsung.android.dhr (Device Health Report)\n- om.salab.act (https://play.google.com/store/apps/details?id=com.jquiz.act)\n- kr.co.avad.diagnostictool (unknown stuff from South Korea)\n\n2 hard-coded URLs:\nPRD = https://dc.dqa.samsung.com\nSTG = https://stg-dc.dqa.samsung.com\nPRD = Portable Recording Device, STG = Security Threat Group. 2 terms related to law enforcment.", + "description": "Samsung Device Quality Agent\nLogging agent for diagnostic device information.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.drivelink.stub": { "list": "Oem", - "description": "Stub for car mode \nREMINDER : Stub = https://stackoverflow.com/questions/10648280/what-is-stub-and-aidl-for-in-java\n", + "description": "Stub for car mode\nREMINDER : Stub = https://stackoverflow.com/questions/10648280/what-is-stub-and-aidl-for-in-java\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4145,7 +5237,9 @@ "list": "Oem", "description": "Samsung Wallpaper services (Dynamic Lock)\nNOTE: Breaks LockStar customization.\nAutomatically changes your Lock screen’s wallpaper every time your Galaxy phone wakes up (wallpapers update every 2 weeks).\nhttps://www.samsung.com/us/support/answer/ANS10001593\n", "dependencies": [], - "neededBy": ["com.samsung.systemui.lockstar"], + "neededBy": [ + "com.samsung.systemui.lockstar" + ], "labels": [], "removal": "Advanced" }, @@ -4159,7 +5253,7 @@ }, "com.samsung.android.easysetup": { "list": "Oem", - "description": "Samsung Nearby device scanning\nRequires \"com.samsung.android.beaconmanager\" to be useful.", + "description": "Samsung Nearby device scanning\nRequires\"com.samsung.android.beaconmanager\" to be useful.", "dependencies": [], "neededBy": [], "labels": [], @@ -4191,7 +5285,7 @@ }, "com.samsung.android.fmm": { "list": "Oem", - "description": "Find My Mobile\nTracks down your device when it gets lost. \nLets you remotely lock your device, block access to Samsung Pay and wipe data from the entire device.\nhttps://www.samsung.com/global/galaxy/what-is/find-my-mobile/\nhttps://findmymobile.samsung.com/\n", + "description": "Find My Mobile\nTracks down your device when it gets lost.\nLets you remotely lock your device, block access to Samsung Pay and wipe data from the entire device.\nhttps://www.samsung.com/global/galaxy/what-is/find-my-mobile/\nhttps://findmymobile.samsung.com/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4199,7 +5293,7 @@ }, "com.samsung.android.game.gamehome": { "list": "Oem", - "description": "Samsung Game Launcher \nhttps://www.samsung.com/global/galaxy/apps/game-launcher/\nAll in one hub for mobiles games\n", + "description": "Samsung Game Launcher\nhttps://www.samsung.com/global/galaxy/apps/game-launcher/\nAll in one hub for mobiles games\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4207,7 +5301,7 @@ }, "com.samsung.android.game.gametools": { "list": "Oem", - "description": "Samsung Game Tools/Booster (https://www.samsung.com/au/support/mobile-devices/how-to-use-game-tools/)\nLet you record and share screenshots of your game-play. \n", + "description": "Samsung Game Tools/Booster (https://www.samsung.com/au/support/mobile-devices/how-to-use-game-tools/)\nLet you record and share screenshots of your game-play.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4215,7 +5309,7 @@ }, "com.samsung.android.game.gos": { "list": "Oem", - "description": "Samsung Game Optimizing Service\nIs supposed to \"improve\" game performance.\nHas a \"Game Intent Service\" that runs occasionally. If uninstalling fails, try disabling. More info:\nhttps://pcgamer.com/samsungs-game-optimization-service-might-be-throttling-the-performance-of-over-10000-apps", + "description": "Samsung Game Optimizing Service\nIs supposed to\"improve\" game performance.\nHas a\"Game Intent Service\" that runs occasionally. If uninstalling fails, try disabling. More info:\nhttps://pcgamer.com/samsungs-game-optimization-service-might-be-throttling-the-performance-of-over-10000-apps", "dependencies": [], "neededBy": [], "labels": [], @@ -4239,7 +5333,7 @@ }, "com.samsung.android.hmt.vrshell": { "list": "Oem", - "description": "Gear VR Shell \nGear VR : https://360samsungvr.com/portal/content/about_samsung_vr\n", + "description": "Gear VR Shell\nGear VR : https://360samsungvr.com/portal/content/about_samsung_vr\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4263,7 +5357,7 @@ }, "com.samsung.android.intelligenceservice2": { "list": "Oem", - "description": "It seems that this package is a kind of spyware. Very difficult to find information about this.\nSome people say it's linked to Carrier IQ (which is a carrier rootkit for the NSA).\nhttps://en.wikipedia.org/wiki/Carrier_IQ\nhttps://forum.xda-developers.com/showpost.php?s=c85df628dfc39c3a971e6f9cfa98cbb8&p=54071328&postcount=6\nThis package also have very strange permissions : READ_PLACE / WRITE_PLACE. I couldn't find any explanation on the web. \nSo either it's a useless samsung package either it's a spyware. I delete it and I didn't notice anything bad.\n", + "description": "It seems that this package is a kind of spyware. Very difficult to find information about this.\nSome people say it's linked to Carrier IQ (which is a carrier rootkit for the NSA).\nhttps://en.wikipedia.org/wiki/Carrier_IQ\nhttps://forum.xda-developers.com/showpost.php?s=c85df628dfc39c3a971e6f9cfa98cbb8&p=54071328&postcount=6\nThis package also have very strange permissions : READ_PLACE / WRITE_PLACE. I couldn't find any explanation on the web.\nSo either it's a useless samsung package either it's a spyware. I delete it and I didn't notice anything bad.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4271,7 +5365,7 @@ }, "com.samsung.android.ipsgeofence": { "list": "Oem", - "description": "Samsung Visit In app\n\nIPSGeofence\nIPS = Indoor Positioning System.\nThe concept of Indoor Positioning System designates a network of connected devices within a building making it possible to trace the position of another device – and therefore potentially of a person – in environments where GPS systems are \nnot efficient .\nGeofencing is a technique which consists in activating preconfigured actions when a device enters a certain geographical area.\nFor example, a user can use it to automatically turn on Wi-Fi and home lights when their smartphone is detected nearby.\nIn short, if enabled, this app will track your location everywhere and all the time!\nhttps://www.comparitech.com/blog/vpn-privacy/what-is-geofencing-privacy/", + "description": "Samsung Visit In app\n\nIPSGeofence\nIPS = Indoor Positioning System.\nThe concept of Indoor Positioning System designates a network of connected devices within a building making it possible to trace the position of another device – and therefore potentially of a person – in environments where GPS systems are\nnot efficient .\nGeofencing is a technique which consists in activating preconfigured actions when a device enters a certain geographical area.\nFor example, a user can use it to automatically turn on Wi-Fi and home lights when their smartphone is detected nearby.\nIn short, if enabled, this app will track your location everywhere and all the time!\nhttps://www.comparitech.com/blog/vpn-privacy/what-is-geofencing-privacy/", "dependencies": [], "neededBy": [], "labels": [], @@ -4279,7 +5373,7 @@ }, "com.samsung.android.keyguardwallpaperupdator": { "list": "Oem", - "description": "Lets you customize your Samsung device with different images (provided by Samsung) on the lock screen. \n", + "description": "Lets you customize your Samsung device with different images (provided by Samsung) on the lock screen.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4287,7 +5381,7 @@ }, "com.samsung.android.kidsinstaller": { "list": "Oem", - "description": "Samsung Kids Home (https://www.samsung.com/global/galaxy/apps/samsung-kids-home/)\nLets you shape a \"safe environment\" for your child.\nNOTE : You shouldn't give your phone to a child. That bad ! \nhttps://ifstudies.org/blog/a-smartphone-will-change-your-child-in-ways-you-might-not-expect-or-want\n", + "description": "Samsung Kids Home (https://www.samsung.com/global/galaxy/apps/samsung-kids-home/)\nLets you shape a\"safe environment\" for your child.\nNOTE : You shouldn't give your phone to a child. That bad !\nhttps://ifstudies.org/blog/a-smartphone-will-change-your-child-in-ways-you-might-not-expect-or-want\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4311,7 +5405,7 @@ }, "com.samsung.android.knox.containerdesktop": { "list": "Oem", - "description": "Knox Container Desktop\nProvides UI for the work(space) container? \nSee \"com.samsung.android.knox.containeragent\"\n", + "description": "Knox Container Desktop\nProvides UI for the work(space) container?\nSee\"com.samsung.android.knox.containeragent\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4335,7 +5429,7 @@ }, "com.samsung.android.mateagent": { "list": "Oem", - "description": "Samsung Galaxy Friends is an accessory platform service that allows the user to enjoy a variety of content quickly \nand easily by simply connecting an accessory, without having to install additional applications.\nhttps://developer.samsung.com/codelab/SDC18-experiences/Galaxy-Friends\n", + "description": "Samsung Galaxy Friends is an accessory platform service that allows the user to enjoy a variety of content quickly\nand easily by simply connecting an accessory, without having to install additional applications.\nhttps://developer.samsung.com/codelab/SDC18-experiences/Galaxy-Friends\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4351,7 +5445,7 @@ }, "com.samsung.android.mdm": { "list": "Oem", - "description": "MDMApp (Mobile Device Management app)\nUsed to monitor and manage remotely mobile devices.\nFor example locking split-screen, blocking safe mode boot, enabling branding logo in the lock screen, remotely configuring IMAP email...\nMost likely related to KNOX \nhttps://www.samsungknox.com/en/solutions/it-solutions/knox-manage\nhttps://developer.samsung.com/tech-insights/knox/mobile-device-management\n", + "description": "MDMApp (Mobile Device Management app)\nUsed to monitor and manage remotely mobile devices.\nFor example locking split-screen, blocking safe mode boot, enabling branding logo in the lock screen, remotely configuring IMAP email...\nMost likely related to KNOX\nhttps://www.samsungknox.com/en/solutions/it-solutions/knox-manage\nhttps://developer.samsung.com/tech-insights/knox/mobile-device-management\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4375,7 +5469,7 @@ }, "com.samsung.android.mdx.kit": { "list": "Oem", - "description": "Quick Share Connectivity / MDE Service Framework\nMDX = Multi Devices Experience (https://www.samsung.com/levant/multi-device-experience/)\nFramework for IoT stuff.\nAsks for a LOT of dangerous permissions\nInteracts with \"com.samsung.android.mobileservice\" and \"com.osp.app.signin\"\n", + "description": "Quick Share Connectivity / MDE Service Framework\nMDX = Multi Devices Experience (https://www.samsung.com/levant/multi-device-experience/)\nFramework for IoT stuff.\nAsks for a LOT of dangerous permissions\nInteracts with\"com.samsung.android.mobileservice\" and\"com.osp.app.signin\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4399,11 +5493,11 @@ }, "com.samsung.android.net.wifi.wifiguider": { "list": "Oem", - "description": "Wi-Fi Tips\nShows a question-mark button next to Wi-Fi networks that failed to connect for any reason, providing info to fix the specific issue. It also has a dedicated Settings activity that lists all possible help-tips, accessible via the \"More tips\" button when reading a tip.\nUpon reinstalling a notification pops up saying \"Analyzing Wi-Fi\" for a few seconds, no idea what it's doing. WARNING: removing makes it impossible to connect to a Wi-Fi network without a detected internet connection!", + "description": "Wi-Fi Tips\nShows a question-mark button next to Wi-Fi networks that failed to connect for any reason, providing info to fix the specific issue. It also has a dedicated Settings activity that lists all possible help-tips, accessible via the\"More tips\" button when reading a tip.\nUpon reinstalling a notification pops up saying\"Analyzing Wi-Fi\" for a few seconds, no idea what it's doing. WARNING: removing makes it impossible to connect to a Wi-Fi network without a detected internet connection!", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.networkdiagnostic": { "list": "Oem", @@ -4447,7 +5541,7 @@ }, "com.samsung.android.rubin.app": { "list": "Oem", - "description": "Customization Service\nCollects a massive amount of data (https://www.samsung.com/us/account/customization-service/)\nBasically everything you do on your phone.\nFor \"a better user experience\"\nUsed to display customized advertisements about products and services that may be of interest to you\n", + "description": "Customization Service\nCollects a massive amount of data (https://www.samsung.com/us/account/customization-service/)\nBasically everything you do on your phone.\nFor\"a better user experience\"\nUsed to display customized advertisements about products and services that may be of interest to you\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4479,7 +5573,7 @@ }, "com.samsung.android.sdk.handwriting": { "list": "Oem", - "description": "Handwriting Service\nOnly for Samsung Note? \nhttps://www.samsung.com/sg/support/mobile-devices/how-do-you-convert-handwriting-to-text-and-other-formats-using-s-pen-and-samsung-notes/\n", + "description": "Handwriting Service\nOnly for Samsung Note?\nhttps://www.samsung.com/sg/support/mobile-devices/how-do-you-convert-handwriting-to-text-and-other-formats-using-s-pen-and-samsung-notes/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4503,7 +5597,7 @@ }, "com.samsung.android.shortcutbackupservice": { "list": "Oem", - "description": "ShortcutBNR \nRelated to smartSwitch Samsung Cloud features\n", + "description": "ShortcutBNR\nRelated to smartSwitch Samsung Cloud features\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4519,7 +5613,7 @@ }, "com.samsung.android.slinkcloud": { "list": "Oem", - "description": "Samsung Cloud Gateway\nNEEDED FOR Scloud app\nA cloud storage gateway is designed to provide interoperability between different data protocols used \nin a client (Scloud app)/server cloud architecture. \nMORE INFO : https://searchstorage.techtarget.com/definition/cloud-storage-gateway\n#\nNeeds a lot of permission (including the dangerous one : READ_PHONE_STATE)\nIt means the app has the ability to read the device ID (e.g. IMEI or ESN) and phone number.\nhttps://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE\n#\nHardcoded Alibaba (chinese) server IP (42.120.153.17) \nhttps://www.hybrid-analysis.com/sample/2ef5367f700d2644fc51d2cdd8dd0ce97e9a6594cb5b89052537037c5a7aac56?environmentId=200\nhttps://web.archive.org/web/20200604093347/https://www.hybrid-analysis.com/sample/2ef5367f700d2644fc51d2cdd8dd0ce97e9a6594cb5b89052537037c5a7aac56?environmentId=200\n", + "description": "Samsung Cloud Gateway\nNEEDED FOR Scloud app\nA cloud storage gateway is designed to provide interoperability between different data protocols used\nin a client (Scloud app)/server cloud architecture.\nMORE INFO : https://searchstorage.techtarget.com/definition/cloud-storage-gateway\n#\nNeeds a lot of permission (including the dangerous one : READ_PHONE_STATE)\nIt means the app has the ability to read the device ID (e.g. IMEI or ESN) and phone number.\nhttps://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE\n#\nHardcoded Alibaba (chinese) server IP (42.120.153.17)\nhttps://www.hybrid-analysis.com/sample/2ef5367f700d2644fc51d2cdd8dd0ce97e9a6594cb5b89052537037c5a7aac56?environmentId=200\nhttps://web.archive.org/web/20200604093347/https://www.hybrid-analysis.com/sample/2ef5367f700d2644fc51d2cdd8dd0ce97e9a6594cb5b89052537037c5a7aac56?environmentId=200\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4527,7 +5621,7 @@ }, "com.samsung.android.smartface": { "list": "Oem", - "description": "SmartFaceService\nUsed to automatically detects faces when using the Samsung camera\nIt might be related to \"Keep screen on while viewing\" under Motions and gestures in Settings.\nNOTE: This package has nothing to do with face unlock (com.samsung.android.bio.face.service)\n", + "description": "SmartFaceService\nUsed to automatically detects faces when using the Samsung camera\nIt might be related to\"Keep screen on while viewing\" under Motions and gestures in Settings.\nNOTE: This package has nothing to do with face unlock (com.samsung.android.bio.face.service)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4583,11 +5677,11 @@ }, "com.samsung.android.scpm": { "list": "Oem", - "description": "Samsung Cloud Platform Manager\nRelated to Samsung Cloud. Safe to remove if you don't use it.", + "description": "Samsung Cloud Platform Manager\nRelated to Samsung Cloud.\nNOTE: Uninstalling or disabling this app causes the \"Sound Quality and Effects\" app (com.sec.android.app.soundalive) to crash regularly, resulting in a crash dialog that might become annoying. (However, the sound seems to work fine)", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.sconnect": { "list": "Oem", @@ -4629,6 +5723,14 @@ "labels": [], "removal": "Recommended" }, + "com.samsung.android.service.pentastic": { + "list": "Oem", + "description": "Glance\nSamsung S-Pen Gestures.\nSafe to remove?\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.samsung.android.service.travel": { "list": "Oem", "description": "Samsung Travel Wallpaper (discontinued)\n", @@ -4647,7 +5749,7 @@ }, "com.samsung.android.smartmirroring": { "list": "Oem", - "description": "Samsung Smart View\nEnable you to mirror screen your phone to a TV (https://www.samsung.com/us/apps/smart-view-2/)\nDependency for com.samsung.android.video", + "description": "Samsung Smart View\nEnable you to mirror screen your phone to a TV (https://www.samsung.com/us/apps/smart-view-2/)\nDependency for com.samsung.android.video\nUninstalling this breaks edge panels feature; edge panel won't work and will also crash OneUI Home when trying to switch edge panels on from settings > display.\nThe edge panels package (com.samsung.android.app.cocktailbarservice and com.samsung.android.app.appsedge) doesn't exist on my phone so maybe on newer devices Samsung moved that functionality to this package instead. Tested on Galaxy S25 FE Android 16", "dependencies": [], "neededBy": [ "com.samsung.android.video" @@ -4726,7 +5828,7 @@ }, "com.samsung.android.svoiceime": { "list": "Oem", - "description": "Samsung voice input \nVoice input powered by Bixby. See above.\n", + "description": "Samsung voice input\nVoice input powered by Bixby. See above.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4750,7 +5852,7 @@ }, "com.samsung.android.themestore": { "list": "Oem", - "description": "Galaxy Themes.\nForces you to login to a Samsung Account if you want to download ANY content (icons, wallpapers, themes...). If you already downloaded something, you can apply it \"freely\".\nNot needed for Wallpaper API, so any app (Samsung or not) can set Home & Lock wallpapers. However, on some devices, this app is required to view/apply built-in wallpapers (in that case, it requires `themecenter` service)\n\nhttps://www.samsung.com/global/galaxy/apps/galaxy-themes/", + "description": "Galaxy Themes.\nForces you to login to a Samsung Account if you want to download ANY content (icons, wallpapers, themes...). If you already downloaded something, you can apply it\"freely\".\nNot needed for Wallpaper API, so any app (Samsung or not) can set Home & Lock wallpapers. However, on some devices, this app is required to view/apply built-in wallpapers (in that case, it requires `themecenter` service)\n\nhttps://www.samsung.com/global/galaxy/apps/galaxy-themes/", "dependencies": [], "neededBy": [], "labels": [], @@ -4774,7 +5876,7 @@ }, "com.samsung.android.universalswitch": { "list": "Oem", - "description": "Universal Switch lets you designate certain touches or gestures to control specific actions on your phone. \nhttps://www.samsung.com/uk/accessibility/mobile-universal-switch/\n", + "description": "Universal Switch lets you designate certain touches or gestures to control specific actions on your phone.\nhttps://www.samsung.com/uk/accessibility/mobile-universal-switch/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4790,7 +5892,7 @@ }, "com.samsung.android.visioncloudagent": { "list": "Oem", - "description": "VisionCloudAgent\nCloud Agent is a service which automatically upload on the cloud the photos you take on your phone. It connects to your \"Samsung account\".\nIt is related to Dropbox.\nGiven the Vision in the package name there is a link with Bixby.\n", + "description": "VisionCloudAgent\nCloud Agent is a service which automatically upload on the cloud the photos you take on your phone. It connects to your\"Samsung account\".\nIt is related to Dropbox.\nGiven the Vision in the package name there is a link with Bixby.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4798,7 +5900,7 @@ }, "com.samsung.android.visionintelligence": { "list": "Oem", - "description": "Bixby Vision\nAugmented reality camera that can identify objects in real-time and potentially offer the user\nto purchase them online, translate text, read QR codes, and recognize landmarks. \nhttps://www.samsung.com/global/galaxy/apps/bixby/vision/\n", + "description": "Bixby Vision\nAugmented reality camera that can identify objects in real-time and potentially offer the user\nto purchase them online, translate text, read QR codes, and recognize landmarks.\nhttps://www.samsung.com/global/galaxy/apps/bixby/vision/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4806,7 +5908,7 @@ }, "com.samsung.android.voc": { "list": "Oem", - "description": "Samsung Members (https://play.google.com/store/apps/details?id=com.samsung.android.voc)\nThe other version is \"com.samsung.oh\".", + "description": "Samsung Members (https://play.google.com/store/apps/details?id=com.samsung.android.voc)\nThe other version is\"com.samsung.oh\".", "dependencies": [], "neededBy": [], "labels": [], @@ -4822,7 +5924,7 @@ }, "com.samsung.android.weather": { "list": "Oem", - "description": "Unified Daemon app. Named \"Weather\" on some Samsung Galaxy devices.\nProvides support for a number of different apps on your device. These include the Weather, Yahoo Finance and Yahoo News apps amongst others. The data is used by apps such as the Alarm, Calendar app and the Camera (including the \"Scan QR code\" Quick-Panel tile). If the display-name is \"Weather\", it doubles as the Samsung Weather app, which provides weather widgets.", + "description": "Unified Daemon app. Named\"Weather\" on some Samsung Galaxy devices.\nProvides support for a number of different apps on your device. These include the Weather, Yahoo Finance and Yahoo News apps amongst others. The data is used by apps such as the Alarm, Calendar app and the Camera (including the\"Scan QR code\" Quick-Panel tile). If the display-name is\"Weather\", it doubles as the Samsung Weather app, which provides weather widgets.", "dependencies": [], "neededBy": [], "labels": [], @@ -4834,7 +5936,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.wellbeing": { "list": "Oem", @@ -4842,7 +5944,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.widgetapp.yahooedge.finance": { "list": "Oem", @@ -4860,6 +5962,14 @@ "labels": [], "removal": "Recommended" }, + "com.samsung.android.widgetapp.yahooedge.news": { + "list": "Oem", + "description": "Special edge panel widget for Yahoo News\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.samsung.android.widget.pictureframe": { "list": "Oem", "description": "Samsung gallery widget, shows your selected photos as widget", @@ -4894,7 +6004,7 @@ }, "com.samsung.desktopsystemui": { "list": "Oem", - "description": "Samsung DeX UI\nExtends your smartphone into a \"desktop computing experience\".\nhttps://developer.samsung.com/samsung-dex/how-it-works\n", + "description": "Samsung DeX UI\nExtends your smartphone into a\"desktop computing experience\".\nhttps://developer.samsung.com/samsung-dex/how-it-works\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4938,7 +6048,7 @@ }, "com.samsung.enhanceservice": { "list": "Oem", - "description": "Enhanced service is the process for Samsung cloud messaging (equivalent to iMessage on iOS).\nMessages on Samsung phones can be transmitted through either the network carrier or the non-archived Samsung service \n(which is transmitted over wireless data).\nThis features is available in stock samsung SMS app settings.\n", + "description": "Enhanced service is the process for Samsung cloud messaging (equivalent to iMessage on iOS).\nMessages on Samsung phones can be transmitted through either the network carrier or the non-archived Samsung service\n(which is transmitted over wireless data).\nThis features is available in stock samsung SMS app settings.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4962,7 +6072,7 @@ }, "com.samsung.groupcast": { "list": "Oem", - "description": "Samsung Group Play (discontinued)\nAllows you to share pictures , documents and music files with many people at same time if everyone is connected to a Wi-Fi network. \nhttps://www.samsung.com/in/support/mobile-devices/what-is-group-play-in-samsung-smartphones/\n", + "description": "Samsung Group Play (discontinued)\nAllows you to share pictures , documents and music files with many people at same time if everyone is connected to a Wi-Fi network.\nhttps://www.samsung.com/in/support/mobile-devices/what-is-group-play-in-samsung-smartphones/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4970,7 +6080,7 @@ }, "com.samsung.helphub": { "list": "Oem", - "description": "Not sure if this package still exist.\nProvide help \n", + "description": "Not sure if this package still exist.\nProvide help\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4978,7 +6088,7 @@ }, "com.samsung.ipservice": { "list": "Oem", - "description": "Set of hidden network settings (inlcuding frequency bands choice)\nHow to see these settings : https://forum.xda-developers.com/galaxy-note-8/help/q-hidden-network-settings-pie-t3914421/page4\n\nSame shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.cmh\nUsed by Galaxy Finder & Galaxy Vision to access web data\nDo removing this package break face/content recognition? \n#\nName and permissions of this package suggest that it is used by Galaxy Finder to seek stuff on the web.\nSame shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.cmh\n", + "description": "Set of hidden network settings (including frequency bands choice)\nHow to see these settings : https://forum.xda-developers.com/galaxy-note-8/help/q-hidden-network-settings-pie-t3914421/page4\n\nSame shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.cmh\nUsed by Galaxy Finder & Galaxy Vision to access web data\nDo removing this package break face/content recognition? \n#\nName and permissions of this package suggest that it is used by Galaxy Finder to seek stuff on the web.\nSame shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.cmh\n", "dependencies": [], "neededBy": [], "labels": [], @@ -4990,7 +6100,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.android.knox.analytics.uploader": { "list": "Oem", @@ -5002,7 +6112,7 @@ }, "com.samsung.knox.keychain": { "list": "Oem", - "description": "Knox Key Chain\nAllows apps to sign data using system-wide private key/certificate pairs. \nSo, even though the Android Keystore provides per-app access to credentials, the Android KeyChain runs as a system user, \nand hence, credentials stored through the Android KeyChain are associated with the system ID instead of a user ID.\nhttps://docs.samsungknox.com/dev/knox-sdk/about-keystores.htm\nThis is only useful for apps using the TIMA Keystore. The big question I'm trying to answer is:\nWhich are using this except Samsung apps? Can an android dev help on this?\n", + "description": "Knox Key Chain\nAllows apps to sign data using system-wide private key/certificate pairs.\nSo, even though the Android Keystore provides per-app access to credentials, the Android KeyChain runs as a system user,\nand hence, credentials stored through the Android KeyChain are associated with the system ID instead of a user ID.\nhttps://docs.samsungknox.com/dev/knox-sdk/about-keystores.htm\nThis is only useful for apps using the TIMA Keystore. The big question I'm trying to answer is:\nWhich are using this except Samsung apps? Can an android dev help on this?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5058,7 +6168,7 @@ }, "com.samsung.logwriter": { "list": "Oem", - "description": "LogWriter\nWrites data in a logs SQL database.\nRuns at boot and is triggered when an download from an Iron Source (Iron Source is an Israeli advertising company)\napp is completed (probably \"com.aura.oobe.samsung\")\n", + "description": "LogWriter\nWrites data in a logs SQL database.\nRuns at boot and is triggered when an download from an Iron Source (Iron Source is an Israeli advertising company)\napp is completed (probably\"com.aura.oobe.samsung\")\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5090,7 +6200,7 @@ }, "com.samsung.oh": { "list": "Oem", - "description": "Samsung Members (https://play.google.com/store/apps/details?id=com.samsung.oh)\nSamsung community. It's a kind of social media app for Samsung users.\nhttps://www.samsung.com/global/galaxy/apps/samsung-members/\nOOOPS ! https://bgr.com/2019/10/31/samsung-members-dong-pic-oops/\nThe other version is \"com.samsung.android.voc\".\n", + "description": "Samsung Members (https://play.google.com/store/apps/details?id=com.samsung.oh)\nSamsung community. It's a kind of social media app for Samsung users.\nhttps://www.samsung.com/global/galaxy/apps/samsung-members/\nOOOPS ! https://bgr.com/2019/10/31/samsung-members-dong-pic-oops/\nThe other version is\"com.samsung.android.voc\".\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5122,11 +6232,11 @@ }, "com.samsung.storyservice": { "list": "Oem", - "description": "Samsung StoryService\nCreate stories in the Gallery from your pictures and videos.\nhttps://www.samsung.com/uk/support/mobile-devices/what-is-video-collage-and-how-do-i-use-it/\nUse of content recognition (so may be related)\n", + "description": "Samsung StoryService\nCreate stories in the Gallery from your pictures and videos.\nhttps://www.samsung.com/uk/support/mobile-devices/what-is-video-collage-and-how-do-i-use-it/\nUse of content recognition (so may be related)\nDisabling breaks edge panels on my s9+ with OneUI 8.0/Android 16\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.svoice.sync": { "list": "Oem", @@ -5162,7 +6272,7 @@ }, "com.samsung.ucs.agent.ese": { "list": "Oem", - "description": "eSE UCS Plugin is another package from UCS. It makes possible for apps to access eSE of Samsung mobile devices by using the UCM \n(Universal Credential Management) APIs and framework.\nhttps://docs.samsungknox.com/dev/knox-sdk/faqs/general/what-is-universal-credential-management_-ucm.htm\nhttps://www.samsung.com/semiconductor/security/ese/\nSee above\n", + "description": "eSE UCS Plugin is another package from UCS. It makes possible for apps to access eSE of Samsung mobile devices by using the UCM\n(Universal Credential Management) APIs and framework.\nhttps://docs.samsungknox.com/dev/knox-sdk/faqs/general/what-is-universal-credential-management_-ucm.htm\nhttps://www.samsung.com/semiconductor/security/ese/\nSee above\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5186,7 +6296,7 @@ }, "com.samsung.vvm.se": { "list": "Oem", - "description": "Samsung Verizon Voicemail \nAllows you to review and manage your voicemail directly from your smartphone, eliminating the need to dial into your mailbox.\nYou can scroll through your messages, pick the ones you want to listen to, and erase them right from your device's screen.\nhttps://mobile.spectrum.com/support/article/360001296667/samsung-visual-voicemail\n", + "description": "Samsung Verizon Voicemail\nAllows you to review and manage your voicemail directly from your smartphone, eliminating the need to dial into your mailbox.\nYou can scroll through your messages, pick the ones you want to listen to, and erase them right from your device's screen.\nhttps://mobile.spectrum.com/support/article/360001296667/samsung-visual-voicemail\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5218,7 +6328,7 @@ }, "com.sec.android.app.billing": { "list": "Oem", - "description": "Samsung billing/Checkout\nUsed to purchase apps through Samsung Store application that is delivered with Samsung phones. \nActs as bridge between Samsung Store and payment servers.\n", + "description": "Samsung billing/Checkout\nUsed to purchase apps through Samsung Store application that is delivered with Samsung phones.\nActs as bridge between Samsung Store and payment servers.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5250,7 +6360,7 @@ }, "com.sec.android.app.DataCreate": { "list": "Oem", - "description": "Automation Test\nAnother hidden test app. A lot of mention of samsung note (memo). Has access to basically everything on the phone\nRelated to these hidden menus (accessible by typing these codes in the samsung dialer) :\n- *#3282*727336*# (Status of data usage) \n- *#273283*255*3282*# (Data create menu) \n- *#*#273283*255*663282*#*#* (Backup all media files)\n", + "description": "Automation Test\nAnother hidden test app. A lot of mention of samsung note (memo). Has access to basically everything on the phone\nRelated to these hidden menus (accessible by typing these codes in the samsung dialer) :\n- *#3282*727336*# (Status of data usage)\n- *#273283*255*3282*# (Data create menu)\n- *#*#273283*255*663282*#*#* (Backup all media files)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5258,7 +6368,7 @@ }, "com.sec.android.app.desktoplauncher": { "list": "Oem", - "description": "Samsung DeX Home (launcher)\nDex enables users to extend their device into a desktop-like experience by connecting a keyboard, mouse, and monitor.\n\"DeX\" is a contraction of \"Desktop eXperience\".\nhttps://en.wikipedia.org/wiki/Samsung_DeX\n", + "description": "Samsung DeX Home (launcher)\nDex enables users to extend their device into a desktop-like experience by connecting a keyboard, mouse, and monitor.\n\"DeX\" is a contraction of\"Desktop eXperience\".\nhttps://en.wikipedia.org/wiki/Samsung_DeX\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5298,7 +6408,7 @@ }, "com.sec.android.app.gamehub": { "list": "Oem", - "description": "Samsung Game Hub\nWas replaced by \"com.samsung.android.game.gamehome\"\nhttps://www.techradar.com/news/phone-and-communications/mobile-phones/the-samsung-game-hub-explained-1143450\n", + "description": "Samsung Game Hub\nWas replaced by\"com.samsung.android.game.gamehome\"\nhttps://www.techradar.com/news/phone-and-communications/mobile-phones/the-samsung-game-hub-explained-1143450\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5322,7 +6432,7 @@ }, "com.sec.android.app.mt": { "list": "Oem", - "description": "Mobile tracker security feature. If someone inserts a new SIM card in your device the device will automatically \nsends the SIM contact number to specified recipients to help you locate and recover you device.\nhttps://www.samsung.com/nz/support/mobile-devices/what-is-mobile-tracker/\n", + "description": "Mobile tracker security feature. If someone inserts a new SIM card in your device the device will automatically\nsends the SIM contact number to specified recipients to help you locate and recover you device.\nhttps://www.samsung.com/nz/support/mobile-devices/what-is-mobile-tracker/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5362,7 +6472,7 @@ }, "com.sec.android.app.samsungapps": { "list": "Oem", - "description": "Samsung Galaxy Store\nSamsung app store.\nRequired for Samsung Pay feature to work.\n\nhttps://en.wikipedia.org/wiki/Samsung_Galaxy_Store\n", + "description": "Samsung Galaxy Store\nSamsung's app store, required for the Samsung Pay feature to work.\nYou probably don't want this app, it's just a worse version of the Play Store with a few proprietary exclusives from Samsung. Uninstalling it will not cause a bootloop, so its priority shouldn't be any higher than Advanced.\nhttps://en.wikipedia.org/wiki/Samsung_Galaxy_Store", "dependencies": [], "neededBy": [ "com.samsung.android.spay" @@ -5380,7 +6490,7 @@ }, "com.sec.android.app.sbrowser": { "list": "Oem", - "description": "Samsung Internet (https://play.google.com/store/apps/details?id=com.sec.android.app.sbrowser)\n\nDon't use this browser. In their privacy policy: \"The information we obtain [...] include, identifiers associated with your devices, types of devices, web browser characteristics, device and operating system type and characteristics, language preferences, clickstream data, your interactions with Samsung Internet (such as the web pages you visit, links you click and features you use), dates and times of your use of Samsung Internet, and other information about your use of Samsung Internet\"\nhttps://developer.samsung.com/internet/privacy-policy-us.html", + "description": "Samsung Internet (https://play.google.com/store/apps/details?id=com.sec.android.app.sbrowser)\n\nDon't use this browser. In their privacy policy:\"The information we obtain [...] include, identifiers associated with your devices, types of devices, web browser characteristics, device and operating system type and characteristics, language preferences, clickstream data, your interactions with Samsung Internet (such as the web pages you visit, links you click and features you use), dates and times of your use of Samsung Internet, and other information about your use of Samsung Internet\"\nhttps://developer.samsung.com/internet/privacy-policy-us.html", "dependencies": [], "neededBy": [], "labels": [], @@ -5388,7 +6498,7 @@ }, "com.sec.android.app.sbrowser.lite": { "list": "Oem", - "description": "Samsung Internet Lite/Go\nLite version of the Samsung browser (hah! Because the base one was too bloated?)\nDon't use this browser. In their privacy policy: \"The information we obtain [...] include, identifiers associated with your devices, types of devices, web browser characteristics, device and operating system type and characteristics, language preferences, clickstream data, your interactions with Samsung Internet (such as the web pages you visit, links you click and features you use), dates and times of your use of Samsung Internet, and other information about your use of Samsung Internet\"\nhttps://developer.samsung.com/internet/privacy-policy-us.html", + "description": "Samsung Internet Lite/Go\nLite version of the Samsung browser (hah! Because the base one was too bloated?)\nDon't use this browser. In their privacy policy:\"The information we obtain [...] include, identifiers associated with your devices, types of devices, web browser characteristics, device and operating system type and characteristics, language preferences, clickstream data, your interactions with Samsung Internet (such as the web pages you visit, links you click and features you use), dates and times of your use of Samsung Internet, and other information about your use of Samsung Internet\"\nhttps://developer.samsung.com/internet/privacy-policy-us.html", "dependencies": [], "neededBy": [], "labels": [], @@ -5420,7 +6530,7 @@ }, "com.sec.android.app.setupwizardlegalprovider": { "list": "Oem", - "description": "SetupWizardLegalProvider\nAll the legal terms you need to accept when you boot your phone for the first time. \nThe Welcome screen which guides you through the basics of setting up your device is the android setup wizard.\n", + "description": "SetupWizardLegalProvider\nAll the legal terms you need to accept when you boot your phone for the first time.\nThe Welcome screen which guides you through the basics of setting up your device is the android setup wizard.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5444,7 +6554,7 @@ }, "com.sec.android.app.setupwizard": { "list": "Oem", - "description": "Samsung Setupwizard\nThe Welcome screen which guides you through the basics of setting up your device when you boot it for the first time (or after a factory reset). On some Verizon-carried devices, it can show an annoying \"SIM card not from Verizon Wireless\" notification, for each boot, and it can't be blocked unless you disable the app\n", + "description": "Samsung Setupwizard\nThe Welcome screen which guides you through the basics of setting up your device when you boot it for the first time (or after a factory reset). On some Verizon-carried devices, it can show an annoying\"SIM card not from Verizon Wireless\" notification, for each boot, and it can't be blocked unless you disable the app\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5452,7 +6562,7 @@ }, "com.sec.android.app.suwscriptplayer": { "list": "Oem", - "description": "SuwScriptPlayer\nSeems to be another test app which test some \"scripts\"\n", + "description": "SuwScriptPlayer\nSeems to be another test app which test some\"scripts\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5492,7 +6602,7 @@ }, "com.sec.android.app.wlantest": { "list": "Oem", - "description": "wlan test\nHidden test app responding to the #232339*# and *#232338*# secret codes\nFYI : wlan = wireless LAN (https://en.wikipedia.org/wiki/Wireless_LAN)\nNOTE: Disabling this test will rise the exclamation mark on the WI-Fi icon and will show the message \"Unable to connect to the host\" in Settings -> Connections -> More connections settings - Private DNS - provider hostname.\nThe connection seems to work despite those esthetic errors.", + "description": "wlan test\nHidden test app responding to the #232339*# and *#232338*# secret codes\nFYI : wlan = wireless LAN (https://en.wikipedia.org/wiki/Wireless_LAN)\nNOTE: Disabling this test will rise the exclamation mark on the WI-Fi icon and will show the message\"Unable to connect to the host\" in Settings -> Connections -> More connections settings - Private DNS - provider hostname.\nThe connection seems to work despite those esthetic errors.", "dependencies": [], "neededBy": [], "labels": [], @@ -5516,7 +6626,7 @@ }, "com.sec.android.daemonapp": { "list": "Oem", - "description": "Unified Daemon app \nprovides support for a number of different apps on your device. These include the Weather, Yahoo Finance and Yahoo News apps amongst others. \nThe data is used by apps such as the Alarm, Calendar app and the camera.\n", + "description": "Unified Daemon app\nprovides support for a number of different apps on your device. These include the Weather, Yahoo Finance and Yahoo News apps amongst others.\nThe data is used by apps such as the Alarm, Calendar app and the camera.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5532,7 +6642,7 @@ }, "com.sec.android.desktopmode.uiservice": { "list": "Oem", - "description": "Samsung DeX\nExtends your smartphone into a \"desktop computing experience\".\nConcretely this lets you access all your mobile apps and content from a computer.\nOnly works on Windows/MacOS. You will need to install the Samsung DeX app on your computer.\nhttps://en.wikipedia.org/wiki/Samsung_DeX\nhttps://www.samsung.com/global/galaxy/apps/samsung-dex/\n", + "description": "Samsung DeX\nExtends your smartphone into a\"desktop computing experience\".\nConcretely this lets you access all your mobile apps and content from a computer.\nOnly works on Windows/MacOS. You will need to install the Samsung DeX app on your computer.\nhttps://en.wikipedia.org/wiki/Samsung_DeX\nhttps://www.samsung.com/global/galaxy/apps/samsung-dex/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5540,7 +6650,7 @@ }, "com.sec.android.app.dexonpc": { "list": "Oem", - "description": "Samsung DeX\nExtends your smartphone into a \"desktop computing experience\".\nConcretely this lets you access all your mobile apps and content from a computer.\nOnly works on Windows/MacOS. You will need to install the Samsung DeX app on your computer.\nhttps://en.wikipedia.org/wiki/Samsung_DeX\nhttps://www.samsung.com/global/galaxy/apps/samsung-dex/\n", + "description": "Samsung DeX\nExtends your smartphone into a\"desktop computing experience\".\nConcretely this lets you access all your mobile apps and content from a computer.\nOnly works on Windows/MacOS. You will need to install the Samsung DeX app on your computer.\nhttps://en.wikipedia.org/wiki/Samsung_DeX\nhttps://www.samsung.com/global/galaxy/apps/samsung-dex/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5548,7 +6658,7 @@ }, "com.sec.android.easyMover": { "list": "Oem", - "description": "Samsung Smart Switch Mobile (https://play.google.com/store/apps/details?id=com.sec.android.easyMover)\nAllows you to easily transfer content (contacts, photos, music, notes, etc.) to a new Samsung Galaxy device. \nhttps://www.samsung.com/global/galaxy/apps/smart-switch/\nhttps://fr.wikipedia.org/wiki/Smart_Switch\n", + "description": "Samsung Smart Switch Mobile (https://play.google.com/store/apps/details?id=com.sec.android.easyMover)\nAllows you to easily transfer content (contacts, photos, music, notes, etc.) to a new Samsung Galaxy device.\nhttps://www.samsung.com/global/galaxy/apps/smart-switch/\nhttps://fr.wikipedia.org/wiki/Smart_Switch\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5556,7 +6666,7 @@ }, "com.sec.android.easyMover.Agent": { "list": "Oem", - "description": "Smart Switch Agent\nNeeded to use Smart Switch. See \"com.sec.android.easyMover\".", + "description": "Smart Switch Agent\nNeeded to use Smart Switch. See\"com.sec.android.easyMover\".", "dependencies": [], "neededBy": [], "labels": [], @@ -5580,7 +6690,7 @@ }, "com.sec.android.fido.uaf.client": { "list": "Oem", - "description": "Fido UAF client. It's a layer that connects authenticator and RP (the application owner) and ensures validity of the connection. \nSo it can be browser, desktop application, mobile application, platform(i.e. android/ios).\nSee above\n\nSafe to remove if you don't use password-less authentication to access online services\n", + "description": "Fido UAF client. It's a layer that connects authenticator and RP (the application owner) and ensures validity of the connection.\nSo it can be browser, desktop application, mobile application, platform(i.e. android/ios).\nSee above\n\nSafe to remove if you don't use password-less authentication to access online services\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5588,7 +6698,7 @@ }, "com.sec.android.game.gamehome": { "list": "Oem", - "description": "Samsung Game launcher\nCentralizes all your android games. This app can track all your games, how many hours you've spent playing each one, and which genres you play the most.\nRecommends games based on your profile.\nhttps://galaxystore.samsung.com/prepost/000004906980?appId=com.samsung.android.game.gamehome \n", + "description": "Samsung Game launcher\nCentralizes all your android games. This app can track all your games, how many hours you've spent playing each one, and which genres you play the most.\nRecommends games based on your profile.\nhttps://galaxystore.samsung.com/prepost/000004906980?appId=com.samsung.android.game.gamehome\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5660,7 +6770,7 @@ }, "com.sec.android.sidesync30": { "list": "Oem", - "description": "SideSync (discontinued)\nLets you share the screen and data between your PC and mobile device. \nReceive alarms of your phone through PC and use various features of your phone on the computer.\nhttps://www.samsung.com/levant/support/side-sync/\n", + "description": "SideSync (discontinued)\nLets you share the screen and data between your PC and mobile device.\nReceive alarms of your phone through PC and use various features of your phone on the computer.\nhttps://www.samsung.com/levant/support/side-sync/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5676,7 +6786,7 @@ }, "com.sec.android.uibcvirtualsoftkey": { "list": "Oem", - "description": "UIBC (User input back channel) \nAllows users to experience the dual monitor function, with the keyboard and mouse having the ability to control your smartphone device.\nEither discontinued (for the benefit of Smart View : com.samsung.android.smartmirroring) or related to Smart View. \n", + "description": "UIBC (User input back channel)\nAllows users to experience the dual monitor function, with the keyboard and mouse having the ability to control your smartphone device.\nEither discontinued (for the benefit of Smart View : com.samsung.android.smartmirroring) or related to Smart View.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5692,7 +6802,7 @@ }, "com.sec.android.widgetapp.easymodecontactswidget": { "list": "Oem", - "description": "Favourite Contacts widget\nLets you add favorite contacts to home screen\nhttps://www.samsung.com/au/getstarted/advanced/create-favourite-contacts-on-your-home-screen/\nIs it only usable when enabling the \"simple use\" senior mode?\n", + "description": "Favourite Contacts widget\nLets you add favorite contacts to home screen\nhttps://www.samsung.com/au/getstarted/advanced/create-favourite-contacts-on-your-home-screen/\nIs it only usable when enabling the\"simple use\" senior mode?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5700,7 +6810,7 @@ }, "com.sec.android.widgetapp.samsungapps": { "list": "Oem", - "description": "Galaxy Essential widget\nGalaxy Essentials is a collection of specially chosen applications available through Samsung Apps. \nFrom the Galaxy Essentials widget you can access and download a collection of premium content, free of charge.\nhttps://www.samsung.com/my/support/mobile-devices/what-is-galaxy-essentials-and-how-can-i-add-or-remove-it-from-my-smartphone-home-screen/\n", + "description": "Galaxy Essential widget\nGalaxy Essentials is a collection of specially chosen applications available through Samsung Apps.\nFrom the Galaxy Essentials widget you can access and download a collection of premium content, free of charge.\nhttps://www.samsung.com/my/support/mobile-devices/what-is-galaxy-essentials-and-how-can-i-add-or-remove-it-from-my-smartphone-home-screen/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5716,7 +6826,7 @@ }, "com.sec.app.RilErrorNotifier": { "list": "Oem", - "description": "RilNotifier\nDebug app for the RIL\nSee \"com.sec.android.RilServiceModeApp\"\n", + "description": "RilNotifier\nDebug app for the RIL\nSee\"com.sec.android.RilServiceModeApp\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5740,7 +6850,7 @@ }, "com.sec.downloadablekeystore": { "list": "Oem", - "description": "Keystore is a secure place provided by Android to store cryptographic keys and make it more difficult to extract from the device.\nThis package is used by enterprise to update certificates on the device.\nNOTE : It allows IT admins to install certificates while the device is still locked. \nThis means certificates can be silently installed into a keystore without any interaction from the device-user.\nIt uses the KNOX TIMA (Named Trust-zone-based Integrity Measurement Architecture) that allows storage of keys in the container for certificate signing using the TrustZone hardware platform.[16] \nhttps://docs.samsungknox.com/dev/knox-sdk/about-keystores.htm\nhttps://docs.samsungknox.com/dev/knox-sdk/faqs/general/what-is-the-knox-tima-ccm.htm\nhttps://docs.samsungknox.com/admin/whitepaper/kpe/client-certificate-manager.htm\n", + "description": "Keystore is a secure place provided by Android to store cryptographic keys and make it more difficult to extract from the device.\nThis package is used by enterprise to update certificates on the device.\nNOTE : It allows IT admins to install certificates while the device is still locked.\nThis means certificates can be silently installed into a keystore without any interaction from the device-user.\nIt uses the KNOX TIMA (Named Trust-zone-based Integrity Measurement Architecture) that allows storage of keys in the container for certificate signing using the TrustZone hardware platform.[16]\nhttps://docs.samsungknox.com/dev/knox-sdk/about-keystores.htm\nhttps://docs.samsungknox.com/dev/knox-sdk/faqs/general/what-is-the-knox-tima-ccm.htm\nhttps://docs.samsungknox.com/admin/whitepaper/kpe/client-certificate-manager.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5852,7 +6962,7 @@ }, "com.sec.kidsplat.installer": { "list": "Oem", - "description": "Kids Mode (replaced by Kids Home : com.samsung.android.kidsinstaller)\nSamsung Kids Home (https://www.samsung.com/global/galaxy/apps/kids-mode/)\nLets you shape a safe environment for your child to happily explore and connect with the world.\nNOTE : You shouldn't give your phone to a child. That's bad ! \nhttps://ifstudies.org/blog/a-smartphone-will-change-your-child-in-ways-you-might-not-expect-or-want\n", + "description": "Kids Mode (replaced by Kids Home : com.samsung.android.kidsinstaller)\nSamsung Kids Home (https://www.samsung.com/global/galaxy/apps/kids-mode/)\nLets you shape a safe environment for your child to happily explore and connect with the world.\nNOTE : You shouldn't give your phone to a child. That's bad !\nhttps://ifstudies.org/blog/a-smartphone-will-change-your-child-in-ways-you-might-not-expect-or-want\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5868,7 +6978,7 @@ }, "com.sec.knox.bridge": { "list": "Oem", - "description": "Debug Bridge ? \n", + "description": "Debug Bridge ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5908,7 +7018,7 @@ }, "com.sec.knox.shortcutsms": { "list": "Oem", - "description": "Knox shortcut to switch to workspace \nhttps://docs.samsungknox.com/knox-platform-for-enterprise/admin-guide/workspace-shortcuts.htm\n", + "description": "Knox shortcut to switch to workspace\nhttps://docs.samsungknox.com/knox-platform-for-enterprise/admin-guide/workspace-shortcuts.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5916,7 +7026,7 @@ }, "com.sec.knox.switchknoxII": { "list": "Oem", - "description": "Handles switches between KNOW/Work container and personal profile. \nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", + "description": "Handles switches between KNOW/Work container and personal profile.\nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5924,7 +7034,7 @@ }, "com.sec.knox.switchknoxI": { "list": "Oem", - "description": "Handles switches between KNOW/Work container and personal profile. \nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", + "description": "Handles switches between KNOW/Work container and personal profile.\nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5932,7 +7042,7 @@ }, "com.sec.knox.switchknox": { "list": "Oem", - "description": "Handles switches between KNOW/Work container and personal profile. \nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", + "description": "Handles switches between KNOW/Work container and personal profile.\nIt also manages data sharing between them.\nhttps://docs.samsungknox.com/dev/knox-sdk/container-data-sharing-policies.htm\n", "dependencies": [], "neededBy": [], "labels": [], @@ -5956,7 +7066,7 @@ }, "com.sec.mldapchecker": { "list": "Oem", - "description": "MLDAP log\nLDAP (Lightweight Directory Access Protocol; I don't know what the M means. Mobile?) is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services over an IP network.\nDirectory service refers to the collection of software, hardware, and processes that store and organize everyday items and network resources(folders, files, printers, users, groups, devices, telephone numbers...)\nIt looks like a database but it's different.\nDirectory services excel at fast lookups for rarely changing data (email, username etc...)\nDifferences between database and Directory Service : https://www.c-sharpcorner.com/article/directory-services-vs-rdbms/\nLDAP uses a relatively simple, string-based query to extract information from Active Directory. LDAP can store and extract objects such as usernames and passwords in Active Directory, and share that object data throughout a network. \nExample of LDAP usage : https://stackoverflow.com/questions/239385/what-is-ldap-used-for/592339\n\nI don't know why and how Samsung uses LDAP. This package, according to its name only does logging.", + "description": "MLDAP log\nLDAP (Lightweight Directory Access Protocol; I don't know what the M means. Mobile?) is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services over an IP network.\nDirectory service refers to the collection of software, hardware, and processes that store and organize everyday items and network resources(folders, files, printers, users, groups, devices, telephone numbers...)\nIt looks like a database but it's different.\nDirectory services excel at fast lookups for rarely changing data (email, username etc...)\nDifferences between database and Directory Service : https://www.c-sharpcorner.com/article/directory-services-vs-rdbms/\nLDAP uses a relatively simple, string-based query to extract information from Active Directory. LDAP can store and extract objects such as usernames and passwords in Active Directory, and share that object data throughout a network.\nExample of LDAP usage : https://stackoverflow.com/questions/239385/what-is-ldap-used-for/592339\n\nI don't know why and how Samsung uses LDAP. This package, according to its name only does logging.", "dependencies": [], "neededBy": [], "labels": [], @@ -6052,7 +7162,7 @@ }, "com.wsomacp": { "list": "Oem", - "description": "omacp = OMA Client Provisioning. It is a protocol specified by the Open Mobile Alliance (OMA).\nConfiguration messages parser. Used for provisioning APN settings to Samsung devices via SMS \nIn my case, it was automatic and I never needed configuration messages.\nMaybe it's useful if carriers change their APN. But you still can change the config manually, it's not difficult.\nKeep in mind these special types of SMS can be abused (though you would need to select to apply the APN in the popup): \nhttps://research.checkpoint.com/2019/advanced-sms-phishing-attacks-against-modern-android-based-smartphones/\nhttps://www.zdnet.com/article/samsung-huawei-lg-and-sony-phones-vulnerable-to-rogue-provisioning-messages/\n", + "description": "omacp = OMA Client Provisioning. It is a protocol specified by the Open Mobile Alliance (OMA).\nConfiguration messages parser. Used for provisioning APN settings to Samsung devices via SMS\nIn my case, it was automatic and I never needed configuration messages.\nMaybe it's useful if carriers change their APN. But you still can change the config manually, it's not difficult.\nKeep in mind these special types of SMS can be abused (though you would need to select to apply the APN in the popup):\nhttps://research.checkpoint.com/2019/advanced-sms-phishing-attacks-against-modern-android-based-smartphones/\nhttps://www.zdnet.com/article/samsung-huawei-lg-and-sony-phones-vulnerable-to-rogue-provisioning-messages/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6060,7 +7170,7 @@ }, "com.wssnps": { "list": "Oem", - "description": "Samsung Backup and restore Manager (on Samsung Galaxy S7)\nWas replaced by \"com.sec.android.easyMover\" (Samsung Smart Switch Mover)\n", + "description": "Samsung Backup and restore Manager (on Samsung Galaxy S7)\nWas replaced by\"com.sec.android.easyMover\" (Samsung Smart Switch Mover)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6068,7 +7178,7 @@ }, "tv.peel.samsung.app": { "list": "Oem", - "description": "Peel Smart Remote (WatchON)\nIt's an application that turns your smart phone or tablet into a TV remote. \nThe app uses the IR Blaster of your device, so devices not equipped with that feature will not be able to use all of Peel Smart Remote's functions. \nhttps://www.samsung.com/za/support/mobile-devices/what-is-the-peel-smart-remote-application/\n", + "description": "Peel Smart Remote (WatchON)\nIt's an application that turns your smart phone or tablet into a TV remote.\nThe app uses the IR Blaster of your device, so devices not equipped with that feature will not be able to use all of Peel Smart Remote's functions.\nhttps://www.samsung.com/za/support/mobile-devices/what-is-the-peel-smart-remote-application/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6084,7 +7194,7 @@ }, "com.policydm": { "list": "Oem", - "description": "Samsung security policy update (https://play.google.com/store/apps/details?id=com.policydm)\nUpdatable policy files designed to increase android security and detect malicious behaviour.\nHas nothing to do with OTA updates or Android Security patches.\nCan be removed without issue (https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/15)\nSee \"com.samsung.android.spdclient\" for more information.\n", + "description": "Samsung security policy update (https://play.google.com/store/apps/details?id=com.policydm)\nUpdatable policy files designed to increase android security and detect malicious behaviour.\nHas nothing to do with OTA updates or Android Security patches.\nCan be removed without issue (https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/15)\nSee\"com.samsung.android.spdclient\" for more information.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6172,7 +7282,7 @@ }, "com.sec.android.app.soundalive": { "list": "Oem", - "description": "Responsible for Dolby Atmos and other equalizer stuff (accessible from the Settings app).\nNeeded by Adapt Sound (com.sec.hearingadjust) which is a pretty useful feature.", + "description": "Responsible for Dolby Atmos and other equalizer stuff (accessible from the Settings app).\nNeeded by Adapt Sound (com.sec.hearingadjust) which is a pretty useful feature.\nNOTE: If the app crashes regularly, even when you don't use Dolby or other features, check to see if you have \"com.samsung.android.scpm\" installed & enabled. If not, try installing/enabling it.", "dependencies": [], "neededBy": [], "labels": [], @@ -6212,7 +7322,7 @@ }, "com.samsung.android.bio.face.service": { "list": "Oem", - "description": "Handles Face recognition unlock \nhttps://kp-cdn.samsungknox.com/b60a7f0f59df8f466e8054f783fbbfe2.pdf\nNOTE: removing this package causes biometric prompts in apps to be delayed by 5-8 seconds before appearing. Selecting 'Biometrics and security' in the settings app also locks up the Settings app for about 5-8 seconds but eventually loads and functions as normal.", + "description": "Handles Face recognition unlock\nhttps://kp-cdn.samsungknox.com/b60a7f0f59df8f466e8054f783fbbfe2.pdf\nNOTE: removing this package causes biometric prompts in apps to be delayed by 5-8 seconds before appearing. Selecting 'Biometrics and security' in the settings app also locks up the Settings app for about 5-8 seconds but eventually loads and functions as normal.", "dependencies": [], "neededBy": [], "labels": [], @@ -6276,7 +7386,7 @@ }, "com.samsung.android.provider.stickerprovider": { "list": "Oem", - "description": "One more package related to camera stickers.\nDO NOT REMOVE THIS IF YOU USE STOCK CAMERA (Samsung camera-app closes after about 4s!) \nadb shell 'pm disable-user com.samsung.android.provider.stickerprovider' can be used as a workaround if you want to stop this running in the background.\n", + "description": "One more package related to camera stickers.\nDO NOT REMOVE THIS IF YOU USE STOCK CAMERA (Samsung camera-app closes after about 4s!)\nadb shell 'pm disable-user com.samsung.android.provider.stickerprovider' can be used as a workaround if you want to stop this running in the background.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6316,7 +7426,7 @@ }, "com.samsung.android.tadownloader": { "list": "Oem", - "description": "Seems to check if a trusted application needs an update and downloads it. \nThis package probably does more than that. There is a LOT of lines of code (obfuscated obviously)\nIt was used to push an update to fix a security issue with the fingerprint sensor in 2019.\nhttps://libredd.it/r/galaxys10/comments/bcy93f/adb_how_to_get_the_fingerprint_update_pushed_to/\nSeems to be only used for biometrics stuff\nThere is Samsung analytics inside. You may want to remove it if you don't use biometrics authentication.\n", + "description": "Seems to check if a trusted application needs an update and downloads it.\nThis package probably does more than that. There is a LOT of lines of code (obfuscated obviously)\nIt was used to push an update to fix a security issue with the fingerprint sensor in 2019.\nhttps://libredd.it/r/galaxys10/comments/bcy93f/adb_how_to_get_the_fingerprint_update_pushed_to/\nSeems to be only used for biometrics stuff\nThere is Samsung analytics inside. You may want to remove it if you don't use biometrics authentication.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6374,7 +7484,7 @@ }, "com.samsung.cmh": { "list": "Oem", - "description": "CMH Provider is a dependency for the the samsung gallery app. This package asks for a lot of permissions. \nIt seems to be be used for cloud and story stuff in the gallery and also seems needed for content recognition.\nHas the same shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.mpl\n \nNOTE : On some phone models, deleting this package can also prevent to preview photos from the camera app.\nSeems to trigger com.samsung.faceservice, com.samsung.mlp, com.samsung.mpl when needed.\n", + "description": "CMH Provider is a dependency for the the samsung gallery app. This package asks for a lot of permissions.\nIt seems to be be used for cloud and story stuff in the gallery and also seems needed for content recognition.\nHas the same shared user id as com.samsung.faceservice, com.samsung.mlp, com.samsung.mpl\n\nNOTE : On some phone models, deleting this package can also prevent to preview photos from the camera app.\nSeems to trigger com.samsung.faceservice, com.samsung.mlp, com.samsung.mpl when needed.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6478,7 +7588,7 @@ }, "com.sec.android.app.vepreload": { "list": "Oem", - "description": "Samsung video editor\nLets you add add transitions, music, stickers and text to your videos. You can also change the speed of the action, \nor even add filters to switch up the mood of your videos.\n", + "description": "Samsung video editor\nLets you add add transitions, music, stickers and text to your videos. You can also change the speed of the action,\nor even add filters to switch up the mood of your videos.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6526,7 +7636,7 @@ }, "com.samsung.android.honeyboard": { "list": "Oem", - "description": "Samsung keyboard\nWARNING: do NOT disable if you don't have another keyboard with direct boot mode support, or you'll be stuck at boot (no keyboard to unlock the phone).\nhttps://developer.android.com/training/articles/direct-boot\nWARNING: Do NOT remove this package with root if it wasn't first uninstalled with the non-root method.\nWARNING: Removing this packages breaks the Accessibility settings on Android 11.", + "description": "Samsung keyboard\nWARNING: do NOT disable if you don't have another keyboard with direct boot mode support, or you'll be stuck at boot (no keyboard to unlock the phone).\nhttps://developer.android.com/training/articles/direct-boot\nWARNING: Do NOT remove this package with root if it wasn't first uninstalled with the non-root method.\nWARNING: Removing this packages breaks the Accessibility settings on Android 11.\nWARNING: Removing this packages breaks the edge panel clipboard.", "dependencies": [], "neededBy": [], "labels": [], @@ -6566,7 +7676,7 @@ }, "com.sec.android.sdhms": { "list": "Oem", - "description": "Samsung Device Health Manager Service\nBattery estimation service for Samsung Care/Device maintenance (com.samsung.android.lool)\nThere is some weird stuff in the java code. I don't understand why there is a need to parse torrent files for instance\nor why there is a string \"googleapis.com/drive\"\nhttps://developers.google.com/drive/api/v3/reference\n", + "description": "Samsung Device Health Manager Service\nBattery estimation service for Samsung Care/Device maintenance (com.samsung.android.lool)\nThere is some weird stuff in the java code. I don't understand why there is a need to parse torrent files for instance\nor why there is a string\"googleapis.com/drive\"\nhttps://developers.google.com/drive/api/v3/reference\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6622,7 +7732,7 @@ }, "com.sec.vsimservice": { "list": "Oem", - "description": "VSim Service \nLets you use a virtual sim\nhttps://www.quora.com/What-is-VSIM-virtual-SIM-technology\nHas a LOT of permissions (and involving IMS service)\nRun at startup.\nFYI : https://security.stackexchange.com/questions/223290/esim-vs-sim-card-what-is-more-secure\n", + "description": "VSim Service\nLets you use a virtual sim\nhttps://www.quora.com/What-is-VSIM-virtual-SIM-technology\nHas a LOT of permissions (and involving IMS service)\nRun at startup.\nFYI : https://security.stackexchange.com/questions/223290/esim-vs-sim-card-what-is-more-secure\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6630,7 +7740,7 @@ }, "com.sec.vsim.ericssonnsds.webapp": { "list": "Oem", - "description": "NSDSWebApp.\nVirtual SIM is an application-enabled service that requires you to install an app to use a number. \nWith this technology, it is possible for one to have numbers of different countries. \nNon Sim Device Solution (NSDS) is needed for VoLTE and VoWifi (Wifi Calling) if you have a virtual SIM. \nNSDS allows connecting non sim devices to IMS core: https://uk.linkedin.com/in/hemant-kumar-dewnarain-2b779679\n", + "description": "NSDSWebApp.\nVirtual SIM is an application-enabled service that requires you to install an app to use a number.\nWith this technology, it is possible for one to have numbers of different countries.\nNon Sim Device Solution (NSDS) is needed for VoLTE and VoWifi (Wifi Calling) if you have a virtual SIM.\nNSDS allows connecting non sim devices to IMS core: https://uk.linkedin.com/in/hemant-kumar-dewnarain-2b779679\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6726,7 +7836,7 @@ }, "com.samsung.android.incallui": { "list": "Oem", - "description": "UI when \"being called/in call\". It's basically the screen that shows you who is calling, lets you answer and hang up, switch to speaker, etc\n", + "description": "UI when\"being called/in call\". It's basically the screen that shows you who is calling, lets you answer and hang up, switch to speaker, etc\n", "dependencies": [], "neededBy": [], "labels": [], @@ -6786,7 +7896,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.bookmarkprovider": { "list": "Aosp", @@ -7010,7 +8120,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.providers.partnerbookmarks": { "list": "Aosp", @@ -7021,8 +8131,8 @@ "removal": "Recommended" }, "com.android.runintest.ddrtest": { - "list": "Aosp", - "description": "DDR Test\nRAM Stress tester\nCan be run from the bootloader\nNOTE: I'm not sure it's really from AOSP (seen in TCL Plex phone)\n", + "list": "Oem", + "description": "DDR Test\nRAM Stress tester\nCan be run from the bootloader\n(seen in TCL Plex phone)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -7030,11 +8140,11 @@ }, "com.android.safetycenter.resources": { "list": "Aosp", - "description": "Google Safety Center.\nProbably affects malware detection in new app installs, Gmail, and Chrome. This will also revert back the \"Security & privacy\" look to the old style.\nYou can use a libre spam-blocking and DNS-blocking solution instead of this.\nhttps://safety.google", + "description": "Google/AOSP Safety Center resources.\n. Uninstalling this will change the configuration to revert back the\"Security & privacy\" look to the old style.\nDoes not contain code, just the configuration for code that lives in another package.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.sdksandbox": { "list": "Aosp", @@ -7058,11 +8168,11 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.stk2": { "list": "Aosp", - "description": "SIM toolkit\nSpecial package for dual-sim devices?\nEnables carriers to initiate \"value-added services\". Basically, some operators provide SIM-cards with applications installed on them.\nhttps://en.wikipedia.org/wiki/SIM_Application_Toolkit#cite_note-CellularZA-1\nHas been abused:\n- SimJacker: https://thehackernews.com/2019/09/simjacker-mobile-hacking.html\n- WIBattack: https://www.zdnet.com/article/new-sim-card-attack-disclosed-similar-to-simjacker/\nWARNING: do mind that disabling/uninstalling this package will break mobile identity management which could be used by apps (for example your Bank) to authenticate you. See https://en.wikipedia.org/wiki/Mobile_identity_management\nNOTE: removing this package removes the launcher icon. `com.android.stk2` relies on `com.android.stk` and vice-versa.", + "description": "SIM toolkit\nSpecial package for dual-sim devices?\nEnables carriers to initiate\"value-added services\". Basically, some operators provide SIM-cards with applications installed on them.\nhttps://en.wikipedia.org/wiki/SIM_Application_Toolkit#cite_note-CellularZA-1\nHas been abused:\n- SimJacker: https://thehackernews.com/2019/09/simjacker-mobile-hacking.html\n- WIBattack: https://www.zdnet.com/article/new-sim-card-attack-disclosed-similar-to-simjacker/\nWARNING: do mind that disabling/uninstalling this package will break mobile identity management which could be used by apps (for example your Bank) to authenticate you. See https://en.wikipedia.org/wiki/Mobile_identity_management\nNOTE: removing this package removes the launcher icon. `com.android.stk2` relies on `com.android.stk` and vice-versa.", "dependencies": [], "neededBy": [], "labels": [ @@ -7072,7 +8182,7 @@ }, "com.android.stk": { "list": "Aosp", - "description": "SIM toolkit\nEnables carriers to initiate \"value-added services\". Basically, some operators provide SIM-cards with applications installed on them.\nhttps://en.wikipedia.org/wiki/SIM_Application_Toolkit#cite_note-CellularZA-1\nHas been abused:\n- SimJacker: https://thehackernews.com/2019/09/simjacker-mobile-hacking.html\n- WIBattack: https://www.zdnet.com/article/new-sim-card-attack-disclosed-similar-to-simjacker/\nWARNING: do mind that disabling/uninstalling this package will break mobile identity management which could be used by apps (for example your Bank) to authenticate you. See https://en.wikipedia.org/wiki/Mobile_identity_management\nNOTE: removing this package removes the launcher icon. `com.android.stk` relies on `com.android.stk2` and vice-versa.", + "description": "SIM toolkit\nEnables carriers to initiate\"value-added services\". Basically, some operators provide SIM-cards with applications installed on them.\nhttps://en.wikipedia.org/wiki/SIM_Application_Toolkit#cite_note-CellularZA-1\nHas been abused:\n- SimJacker: https://thehackernews.com/2019/09/simjacker-mobile-hacking.html\n- WIBattack: https://www.zdnet.com/article/new-sim-card-attack-disclosed-similar-to-simjacker/\nWARNING: do mind that disabling/uninstalling this package will break mobile identity management which could be used by apps (for example your Bank) to authenticate you. See https://en.wikipedia.org/wiki/Mobile_identity_management\nNOTE: removing this package removes the launcher icon. `com.android.stk` relies on `com.android.stk2` and vice-versa.", "dependencies": [], "neededBy": [], "labels": [ @@ -7130,7 +8240,7 @@ }, "android.auto_generated_rro__": { "list": "Aosp", - "description": "rro = Runtime Resources Overlay.\nChanges values of a package config, based in the overlay definitions (heavily used by OEMs to customize the look and feel of Android) \nLink: https://source.android.com/devices/architecture/rros and https://code.tutsplus.com/tutorials/quick-tip-theme-android-with-the-runtime-resource-overlay-framework--cms-29708\n", + "description": "rro = Runtime Resources Overlay.\nChanges values of a package config, based in the overlay definitions (heavily used by OEMs to customize the look and feel of Android)\nLink: https://source.android.com/devices/architecture/rros and https://code.tutsplus.com/tutorials/quick-tip-theme-android-with-the-runtime-resource-overlay-framework--cms-29708\n", "dependencies": [], "neededBy": [], "labels": [], @@ -7162,7 +8272,7 @@ }, "com.android.bluetooth": { "list": "Aosp", - "description": "Bluetooth service\n", + "description": "Bluetooth service\nHandles all Bluetooth functionality including device discovery, pairing, and data transfer.\nRemoving this will completely break Bluetooth functionality on the device.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -7206,7 +8316,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.captiveportallogin": { "list": "Aosp", @@ -7292,7 +8402,7 @@ }, "com.android.emergency": { "list": "Aosp", - "description": "Emergency rescue\nShows emergency info on lockscreen and power menu. Safe to disable if you don't want it.\nLoads on device unlock/lockscreen and power menu, so it's basically always cached in RAM, but shouldn't use much/any battery, so the main thing gained from disabling this package is the ~9MB RAM it uses.", + "description": "Emergency rescue\nShows emergency info on lockscreen and power menu. Safe to disable if you don't want it.\nLoads on device unlock/lockscreen and power menu, so it's basically always cached in RAM, but shouldn't use much/any battery, so the main thing gained from disabling this package is the ~9MB RAM it uses.\nRemoving this will break Safety and Emergency in Settings and you will miss SOS alerts.", "dependencies": [], "neededBy": [], "labels": [], @@ -7332,7 +8442,7 @@ }, "com.android.inputdevices": { "list": "Aosp", - "description": "Only contains a receiver named \"Android keyboard\", possibly for an external keyboard.\nLocates available keyboard layouts. Apps can offer additional keyboard layouts to the user by declaring a suitable broadcast receiver in their manifest.\nWARNING: If you are using the default Samsung keyboard, then deleting this package on some phones may cause the keyboard to completely stop working. You may get locked out of your phone if the only method to authenticate yourself is using password.", + "description": "Only contains a receiver named\"Android keyboard\", possibly for an external keyboard.\nLocates available keyboard layouts. Apps can offer additional keyboard layouts to the user by declaring a suitable broadcast receiver in their manifest.\nWARNING: If you are using the default Samsung keyboard, then deleting this package on some phones may cause the keyboard to completely stop working. You may get locked out of your phone if the only method to authenticate yourself is using password.", "dependencies": [], "neededBy": [], "labels": [], @@ -7340,7 +8450,7 @@ }, "com.android.inputmethod.latin": { "list": "Aosp", - "description": "The AOSP keyboard app\nMame sure you have another installed before you disable.", + "description": "The AOSP keyboard app\nMake sure you have another installed before you disable.", "dependencies": [], "neededBy": [], "labels": [], @@ -7626,6 +8736,14 @@ "labels": [], "removal": "Expert" }, + "com.android.server.deviceconfig.resources": { + "list": "Oem", + "description": "DeviceConfigServiceResources (Server*?). Part of com.android.configinfrastructure. Resources for the device's default server config.\nhttps://cs.android.com/android/platform/superproject/main/+/main:packages/modules/ConfigInfrastructure/service/ServiceResources/Android.bp", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.android.server.NetworkPermissionConfig": { "list": "Aosp", "description": "Network configurations.", @@ -7636,7 +8754,7 @@ }, "com.android.settings.intelligence": { "list": "Aosp", - "description": "Settings Suggestions\nHandles the search and suggestions features in the settings app.\nDisabling this package makes the Settings app crash when you tap on search.\nDoesn't run in the background, so there's little benefit in disabling.\nhttps://gitlab.com/W1nst0n/universal-android-debloater/-/issues/51", + "description": "Settings Suggestions\nHandles the search and suggestions features in the settings app.\nDisabling this package makes the Settings app crash when you tap on search.\nDoesn't run in the background, so there's little benefit in disabling.\nUses location, nearby devices, notifications permissions by default\nhttps://gitlab.com/W1nst0n/universal-android-debloater/-/issues/51", "dependencies": [], "neededBy": [], "labels": [], @@ -7664,7 +8782,15 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" + }, + "com.google.android.contactkeys": { + "list": "Google", + "description": "Android System Key Verifier is a system service for verifying interlocutors using messengers with end-to-end encryption.\nIts job is to verify end-to-end encryption keys across chat apps.\nIt has no internet permissions and performs local key comparisons only.\nIt doesn’t access your chats, contacts, or files.\nIt doesn’t run in the background unless called by another apps\nhttps://grouphowto.com/com-google-android-contactkeys/\nhttps://developers.google.com/android/binary_transparency/google1p/overview", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" }, "com.android.systemui.theme.dark": { "list": "Aosp", @@ -7692,7 +8818,7 @@ }, "com.android.timezone.updater": { "list": "Aosp", - "description": "Time Zone Updater\nAutomatically updates the clock to correspond to your current time zone\nThis *may* cause a bootloop if removed. Timezone packages often causes that. \n", + "description": "Time Zone Updater\nAutomatically updates the clock to correspond to your current time zone\nThis *may* cause a bootloop if removed. Timezone packages often causes that.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -7716,7 +8842,7 @@ }, "com.android.wallpaperbackup": { "list": "Aosp", - "description": "Wallpaper Backup\nBacks up and restores wallpaper and metadata related to it.\nThis agent has its own package because it does full backup as opposed to SystemBackupAgent which does key/value backup.\nThis class stages wallpaper files for backup by copying them into its own directory because of the following reasons:\nNon-system users don't have permission to read the directory that the system stores the wallpaper files in\nBackupAgent enforces that backed up files must live inside the package's getFilesDir()\nThere are 3 files to back up:\nThe \"wallpaper info\" file which contains metadata like the crop applied to the wallpaper or the live wallpaper component name.\nThe \"system\" wallpaper file.\nAn optional \"lock\" wallpaper, which is shown on the lockscreen instead of the system wallpaper if set.\nOn restore, the metadata file is parsed and WallpaperManager APIs are used to set the wallpaper.\nNote that if there's a live wallpaper, the live wallpaper package name will be part of the metadata file and the wallpaper will be applied when the package it's installed.\nhttps://android.googlesource.com/platform/frameworks/base/+/master/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java", + "description": "Wallpaper Backup\nBacks up and restores wallpaper and metadata related to it.\nThis agent has its own package because it does full backup as opposed to SystemBackupAgent which does key/value backup.\nThis class stages wallpaper files for backup by copying them into its own directory because of the following reasons:\nNon-system users don't have permission to read the directory that the system stores the wallpaper files in\nBackupAgent enforces that backed up files must live inside the package's getFilesDir()\nThere are 3 files to back up:\nThe\"wallpaper info\" file which contains metadata like the crop applied to the wallpaper or the live wallpaper component name.\nThe\"system\" wallpaper file.\nAn optional\"lock\" wallpaper, which is shown on the lockscreen instead of the system wallpaper if set.\nOn restore, the metadata file is parsed and WallpaperManager APIs are used to set the wallpaper.\nNote that if there's a live wallpaper, the live wallpaper package name will be part of the metadata file and the wallpaper will be applied when the package it's installed.\nhttps://android.googlesource.com/platform/frameworks/base/+/master/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java", "dependencies": [], "neededBy": [], "labels": [], @@ -7756,7 +8882,7 @@ }, "com.android.documentsui.a_overlay": { "list": "Aosp", - "description": "Some overlay for for \"Files\"?", + "description": "Some overlay for for\"Files\"?", "dependencies": [], "neededBy": [], "labels": [], @@ -7796,11 +8922,11 @@ }, "com.android.location.fused": { "list": "Aosp", - "description": "Manages underlying location technologies, such as GPS and Wi-Fi.", + "description": "Manages underlying location technologies, such as GPS and Wi-Fi.\nUninstalling it may unlikely cause a bootloop, although, you probably shouldn't uninstall it unless you deleted Google Play Services, and don't have a GPS sensor.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.android.mms.service": { "list": "Aosp", @@ -7828,7 +8954,7 @@ }, "com.android.provision": { "list": "Aosp", - "description": "Provisioning is the process of setting up a network connection that will allow new users. \nThis service is for example needed when the user's phone moves from one cell-tower to another.\n", + "description": "Provisioning is the process of setting up a network connection that will allow new users.\nThis service is for example needed when the user's phone moves from one cell-tower to another.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -7852,7 +8978,7 @@ }, "com.android.providers.contacts": { "list": "Aosp", - "description": "Contacts Storage\nProvider for contact data.\nContent providers encapsulate data, providing centralized management of data shared between apps.\nhttps://developer.android.com/guide/topics/providers/content-providers.html\nBreaks contact functionality if disabled. Not recommended to disable if you plan to use your device as a phone.", + "description": "Contacts Storage\nProvider for contact data.\nContent providers encapsulate data, providing centralized management of data shared between apps.\nhttps://developer.android.com/guide/topics/providers/content-providers.html\nBreaks contact functionality if disabled. Not recommended to disable if you plan to use your device as a phone.\nOn POCO Pad M1, disabling this will cause Bluetooth to malfunction, turning on and off continuously.", "dependencies": [], "neededBy": [], "labels": [], @@ -7924,7 +9050,7 @@ }, "com.android.shell": { "list": "Aosp", - "description": "Shell\nUnix shell that receives ADB commands sent from a PC.\nThis is what UAD-ng uses to execute commands on Android devices. Proobably a bad idea to disable ;)", + "description": "Shell\nUnix shell that receives ADB commands sent from a PC.\nThis is what UAD-ng uses to execute commands on Android devices. Probably a bad idea to disable ;)", "dependencies": [], "neededBy": [], "labels": [], @@ -8036,7 +9162,7 @@ }, "com.oem.oemlogkit": { "list": "Oem", - "description": "OnePlus LogKit\nShady logging app that system apps can use to log WiFi traffic, Bluetooth traffic, NFC activity, GPS coordinates over time, power consumption, modem signal/data details, \"lag issues,\" and more.\nhttps://thehackernews.com/2017/11/oneplus-logkit-app.html\nhttps://www.bleepingcomputer.com/news/security/second-oneplus-factory-app-discovered-this-one-dumps-photos-wifi-and-gps-logs/\nhttps://web.archive.org/web/20210611122551/https://twitter.com/fs0c131y/status/930773795656396801", + "description": "OnePlus LogKit\nShady logging app that system apps can use to log WiFi traffic, Bluetooth traffic, NFC activity, GPS coordinates over time, power consumption, modem signal/data details,\"lag issues,\" and more.\nhttps://thehackernews.com/2017/11/oneplus-logkit-app.html\nhttps://www.bleepingcomputer.com/news/security/second-oneplus-factory-app-discovered-this-one-dumps-photos-wifi-and-gps-logs/\nhttps://web.archive.org/web/20210611122551/https://twitter.com/fs0c131y/status/930773795656396801", "dependencies": [], "neededBy": [], "labels": [], @@ -8100,7 +9226,7 @@ }, "com.oneplus.engmode": { "list": "Oem", - "description": "Some kind of Engineer mode? I've no clue.\nContains a bunch of activities with \"info\" in their names.\nContains an \"OpFloatViewService\", but I've never seen it run.", + "description": "Some kind of Engineer mode? I've no clue.\nContains a bunch of activities with\"info\" in their names.\nContains an\"OpFloatViewService\", but I've never seen it run.", "dependencies": [], "neededBy": [], "labels": [], @@ -8182,7 +9308,7 @@ }, "com.oneplus.skin": { "list": "Oem", - "description": "", + "description": "Icon styles/themes/animations and visual effects", "dependencies": [], "neededBy": [], "labels": [], @@ -8190,7 +9316,7 @@ }, "com.oneplus.soundrecorder": { "list": "Oem", - "description": "Recorder\nOnePlus sound recording app.\nRequires turning on \"Allow modifying system settings\" to use for some reason? Probably tied to recording phone-calls.", + "description": "Recorder\nOnePlus sound recording app. Requires turning on\"Allow modifying system settings\" to use for some reason? Probably tied to recording phone-calls.", "dependencies": [], "neededBy": [], "labels": [], @@ -8238,7 +9364,7 @@ }, "com.oneplus.orm": { "list": "Oem", - "description": "Seems to be Oneplus' Memory Management System according to a press-kit/-release they made for Android 11 (multiple sites wrote \"ORM Memory Management System\" word-for-word).\nRuns in the background as part of the system. Runs even if disabled? Doesn't use any RAM when disabled tho, vs ~50MB when enabled.\nSeems safe to disable, haven't noticed any negative effects in weeks of use, but I assume it breaks the \"RAM Boost\" feature (which is pointless anyway IMO).\nApk file name: OPOmm, mm = Memory Management?\nHas 2 permissions: KILL_BACKGROUND_PROCESSES and SET_TIME_ZONE.\nContains 2 services: OPManagerService and BackgroundCollectorService.", + "description": "Seems to be Oneplus' Memory Management System according to a press-kit/-release they made for Android 11 (multiple sites wrote\"ORM Memory Management System\" word-for-word).\nRuns in the background as part of the system. Runs even if disabled? Doesn't use any RAM when disabled tho, vs ~50MB when enabled.\nSeems safe to disable, haven't noticed any negative effects in weeks of use, but I assume it breaks the\"RAM Boost\" feature (which is pointless anyway IMO).\nApk file name: OPOmm, mm = Memory Management?\nHas 2 permissions: KILL_BACKGROUND_PROCESSES and SET_TIME_ZONE.\nContains 2 services: OPManagerService and BackgroundCollectorService.", "dependencies": [], "neededBy": [], "labels": [], @@ -8270,7 +9396,7 @@ }, "net.oneplus.push": { "list": "Oem", - "description": "Push\nOnePlus push notifications.\nOnly used by OnePlus' pre-installed apps. Pushes \"surveys and other junk\" according to a user.\nhttps://forums.oneplus.com/threads/psa-non-root-root-stop-oneplus-push-notifications.580058/\nOnePlus can remotely send push notifications:\nhttps://www.androidpolice.com/2019/07/01/oneplus-accidentally-pushed-a-cryptic-notification-to-all-7-pro-users/", + "description": "Push\nOnePlus push notifications.\nOnly used by OnePlus' pre-installed apps. Pushes\"surveys and other junk\" according to a user.\nhttps://forums.oneplus.com/threads/psa-non-root-root-stop-oneplus-push-notifications.580058/\nOnePlus can remotely send push notifications:\nhttps://www.androidpolice.com/2019/07/01/oneplus-accidentally-pushed-a-cryptic-notification-to-all-7-pro-users/", "dependencies": [], "neededBy": [], "labels": [], @@ -8278,7 +9404,7 @@ }, "net.oneplus.wallpaperresources": { "list": "Oem", - "description": "Resources for some live wall papers? Not sure.\nOnly contains a \"WallpaperResourceProvider\", no services, activities or receivers.", + "description": "Resources for some live wall papers? Not sure.\nOnly contains a\"WallpaperResourceProvider\", no services, activities or receivers.", "dependencies": [], "neededBy": [], "labels": [], @@ -8334,7 +9460,7 @@ }, "cn.oneplus.oemtcma": { "list": "Oem", - "description": "TCMA = Tiered Contention Multiple Access\nRuns on boot.\nA form of CSMA/CA, a cellular traffic management protocol. TCMA schedules transmission of different types of traffic based on urgency.\nChina-only? (the \"cn\" in cn.oneplus is China's country code)\nhttps://en.wikipedia.org/wiki/Carrier-sense_multiple_access_with_collision_avoidance\nhttps://patents.google.com/patent/US20020163933A1", + "description": "TCMA = Tiered Contention Multiple Access\nRuns on boot.\nA form of CSMA/CA, a cellular traffic management protocol. TCMA schedules transmission of different types of traffic based on urgency.\nChina-only? (the\"cn\" in cn.oneplus is China's country code)\nhttps://en.wikipedia.org/wiki/Carrier-sense_multiple_access_with_collision_avoidance\nhttps://patents.google.com/patent/US20020163933A1", "dependencies": [], "neededBy": [], "labels": [], @@ -8342,7 +9468,7 @@ }, "cn.oneplus.oem_tcma": { "list": "Oem", - "description": "TCMA = Tiered Contention Multiple Access\nRuns on boot.\nA form of CSMA/CA, a cellular traffic management protocol. TCMA schedules transmission of different types of traffic based on urgency.\nChina-only? (the \"cn\" in cn.oneplus is China's country code)\nhttps://en.wikipedia.org/wiki/Carrier-sense_multiple_access_with_collision_avoidance\nhttps://patents.google.com/patent/US20020163933A1", + "description": "TCMA = Tiered Contention Multiple Access\nRuns on boot.\nA form of CSMA/CA, a cellular traffic management protocol. TCMA schedules transmission of different types of traffic based on urgency.\nChina-only? (the\"cn\" in cn.oneplus is China's country code)\nhttps://en.wikipedia.org/wiki/Carrier-sense_multiple_access_with_collision_avoidance\nhttps://patents.google.com/patent/US20020163933A1", "dependencies": [], "neededBy": [], "labels": [], @@ -8430,7 +9556,7 @@ }, "com.android.mmi": { "list": "Oem", - "description": "Not an AOSP package at all\nHidden MMI test app \nMMI = Man Machine Interface ?\n", + "description": "Not an AOSP package at all\nHidden MMI test app\nMMI = Man Machine Interface ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -8558,11 +9684,11 @@ }, "com.android.dialer": { "list": "Aosp", - "description": "AOSP Dialer/Phone app\nDefault phone app on some older phones(like Oneplus 3).", + "description": "AOSP Dialer/Phone app\nDefault phone app on some older phones(like Oneplus 3). WARNING: Uninstalling it may break the entire phone app; emergency calls; SIM card detection, and the software update screen on Samsung.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.mediatek.calendarimporter": { "list": "Misc", @@ -8612,6 +9738,14 @@ "labels": [], "removal": "Expert" }, + "com.mediatek.datatransfer": { + "list": "Misc", + "description": "The com.mediatek.datatransfer package is part of MediaTek's suite of utilities and is typically used for managing data transfer between devices or during device setup. This app often supports functions like transferring files, contacts, and other data from one device to another. Removing this package might impair the ability to use MediaTek-specific data transfer tools and could impact some setup or migration processes.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.mediatek.dataprotection": { "list": "Misc", "description": "Possibly related to user partition encryption/decryption.\nA device should works flawlessly without it.", @@ -8650,7 +9784,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.nearby.halfsheet": { "list": "Aosp", @@ -8718,7 +9852,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.cellbroadcastservice": { "list": "Aosp", @@ -8878,7 +10012,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.theme.icon.circle": { "list": "Aosp", @@ -9402,7 +10536,7 @@ }, "com.oneplus.screenrecord": { "list": "Oem", - "description": "Screen Recorder\nThe Android 11 screen recorder with some Oneplus modifications.\nRuns the \"SystemUITileService\" when you have it as one of the quicksettings tiles, but doesn't seem to run in the background outside of that.\nDoesn't have an app icon, but you can create a shortcut to it with the Activity Launcher app (to avoid the background service).\nhttps://f-droid.org/en/packages/de.szalkowski.activitylauncher/", + "description": "Screen Recorder\nThe Android 11 screen recorder with some Oneplus modifications.\nRuns the\"SystemUITileService\" when you have it as one of the quicksettings tiles, but doesn't seem to run in the background outside of that.\nDoesn't have an app icon, but you can create a shortcut to it with the Activity Launcher app (to avoid the background service).\nhttps://f-droid.org/en/packages/de.szalkowski.activitylauncher/", "dependencies": [], "neededBy": [], "labels": [], @@ -9442,7 +10576,7 @@ }, "com.oneplus.security": { "list": "Oem", - "description": "Dashboard\nRuns \"WidgetViewService\" and \"SecureService\" in the background.\nManages widget data access? Noticed no apparent ill effects on disable in Android 9.", + "description": "Dashboard\nRuns\"WidgetViewService\" and\"SecureService\" in the background.\nManages widget data access? Noticed no apparent ill effects on disable in Android 9.", "dependencies": [], "neededBy": [], "labels": [], @@ -9466,7 +10600,7 @@ }, "com.oneplus.ses": { "list": "Oem", - "description": "OPSes\nApk file name: OPSesAuthentication.\nContains a \"SesService\", but I've never seen it run.\nRelated to Amazon SES?(Simple Email Service) https://aws.amazon.com/ses/", + "description": "OPSes\nApk file name: OPSesAuthentication.\nContains a\"SesService\", but I've never seen it run.\nRelated to Amazon SES?(Simple Email Service) https://aws.amazon.com/ses/", "dependencies": [], "neededBy": [], "labels": [], @@ -9662,7 +10796,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.qualcomm.qtil.aptxui": { "list": "Misc", @@ -9722,7 +10856,7 @@ }, "com.roaming.android.gsimbase": { "list": "Misc", - "description": "gsim = Global SIM? (SIM = Subscriber Identity Module, as in SIM-card)\nConsidering the \"roaming\" context that's my best guess.", + "description": "gsim = Global SIM? (SIM = Subscriber Identity Module, as in SIM-card)\nConsidering the\"roaming\" context that's my best guess.", "dependencies": [], "neededBy": [], "labels": [], @@ -9730,7 +10864,7 @@ }, "com.roaming.android.gsimcontentprovider": { "list": "Misc", - "description": "gsim = Global SIM? (SIM = Subscriber Identity Module, as in SIM-card)\nConsidering the \"roaming\" context that's my best guess.", + "description": "gsim = Global SIM? (SIM = Subscriber Identity Module, as in SIM-card)\nConsidering the\"roaming\" context that's my best guess.", "dependencies": [], "neededBy": [], "labels": [], @@ -9874,7 +11008,7 @@ }, "com.android.theme.icon_pack.rounded.themepicker": { "list": "Aosp", - "description": "Obviously related to the \"rounded\" icon pack but the full package is strange. A themepicker class only for a specific icon package?\nSafe to remove if you don't use them, but there's no point in doing so.", + "description": "Obviously related to the\"rounded\" icon pack but the full package is strange. A themepicker class only for a specific icon package?\nSafe to remove if you don't use them, but there's no point in doing so.", "dependencies": [], "neededBy": [], "labels": [], @@ -9944,7 +11078,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.cellbroadcastservice.overlay.miui": { "list": "Oem", @@ -9952,7 +11086,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.cellbroadcastservice": { "list": "Aosp", @@ -9974,7 +11108,7 @@ }, "com.google.android.networkstack.tethering": { "list": "Aosp", - "description": "Used for USB and/or Wi-Fi tethering?", + "description": "Uninstalling/Disabling this app will break Hotspot and Bluetooth/USB Tethering.\nOn some devices, when you enable hotspot or Bluetooth/USB Tethering it will show the boot animation (not bootloop) (not on HyperOS 2.0) And will bring you back to your device\nIt's safe to uninstall it if you aren't going to use Hotspot or Bluetooth/USB Tethering.\n On HyperOS 2.0, you'll need to remove it twice and reboot each time for it to fully vanish. It restores itself after first removal and reboot.\nOn HyperOS 2.0, after removing this package fully, it makes the whole settings app crash when clicking the Developer Settings button, making the Developer Settings inaccessible.\nEven when calling Developer Settings from another app, or calling usb debugging settings from another app, it all still refuses to launch, just crashes.\nIt basically puts you into a trap if you've disabled USB Debugging, as you'll no longer be able to turn USB Debugging back on, and so won't be able to restore this nor other removed packages. Access to ADB will be permanently lost.\nAfter restoring it, a reboot is required for the developer settings and hotspot to become accessible. Similar behavior to as described here might be also observed on other devices.", "dependencies": [], "neededBy": [], "labels": [], @@ -9986,7 +11120,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.google.android.ondevicepersonalization.services": { "list": "Aosp", @@ -10010,7 +11144,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.overlay.gmsconfig": { "list": "Google", @@ -10026,7 +11160,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.overlay.gmsconfig.common": { "list": "Google", @@ -10038,7 +11172,7 @@ }, "com.google.android.overlay.gmsconfig.comms": { "list": "Google", - "description": "Useless configurations dialer, sms, contacts Google(GApps)\neverything works without it.", + "description": "Useless configurations dialer, sms, contacts Google(GApps)\nIt may break PackageInstaller.", "dependencies": [], "neededBy": [], "labels": [], @@ -10070,27 +11204,27 @@ }, "com.google.android.overlay.gmsconfig.photos": { "list": "Google", - "description": "overlay to\nconfig_systemGallery to com.google.android.apps.photos in Motorola. It's also installed on some Samsung Galaxy devices. Useless.", + "description": "WARNING: Uninstalling it makes it impossible to unlock Android 15, Blackview Tab 60 WiFi!", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Unsafe" }, "com.google.android.overlay.gmsconfig.searchlauncherqs": { "list": "Google", - "description": "Useless gmsconfig. it's config default launcher but not needed.", + "description": "WARNING: Uninstalling it breaks the Settings app for Android 15, Blackview Tab 60 WiFi!", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.overlay.gmsconfig.searchselector": { "list": "Google", - "description": "Not needed for (com.google.android.apps.setupwizard.searchselector).", + "description": "Removal will crash most apps like settings, clock, firefox, github, termux etc.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.overlay.gmsconfig.ww": { "list": "Google", @@ -10098,7 +11232,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.overlay.modules.cellbroadcastservice": { "list": "Aosp", @@ -10110,11 +11244,11 @@ }, "com.google.android.overlay.modules.documentsui": { "list": "Aosp", - "description": "In code only found: `is_launcher_enabled` false\nOn pixel phones this app overlay not exist.\nit's only made to hide app icon (com.google.android.documentsui)\nNo effects after remove(so icon will be not back), it's useless.", + "description": "WARNING: Uninstalling it breaks the Scheduled power on/off page of the Settings app for Android 15, Blackview Tab 60 WiFi!", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.overlay.modules.modulemetadata.forframework": { "list": "Oem", @@ -10146,7 +11280,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.systemui.notch.overlay": { "list": "Oem", @@ -10162,7 +11296,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.photopicker": { "list": "Aosp", @@ -10174,7 +11308,7 @@ }, "com.google.android.providers.media.module": { "list": "Aosp", - "description": "Media Storage\nIn Android 11 this is literally what provides access to files.\nSafe to disable, but NOT recommended; breaks file browsers and other forms of file access.\nContent providers encapsulate data, providing centralized management of data shared between apps.\nhttps://developer.android.com/guide/topics/providers/content-providers.html", + "description": "Media Storage\nIn Android 11+ this provides file access to apps without\"Manage All Files\" permission. In previous versions it's just an index of all audio-visual (no text) files in the user's file-system (`/sdcard/`, `/storage/emulated/0/`, etc...). This allows music-players and photo-galleries to list files quickly, without caching their own indices.\nSafe to disable, but NOT recommended; breaks file browsers and other forms of file access.\nContent providers encapsulate data, providing centralized management of data shared between apps.\nhttps://developer.android.com/guide/topics/providers/content-providers.html", "dependencies": [], "neededBy": [], "labels": [], @@ -10198,7 +11332,7 @@ }, "com.qualcomm.qti.xrcb": { "list": "Misc", - "description": "Receive xrcb network signals for radio side. \nit's about emergency alerts, weather alerts, public announcements, and other information.", + "description": "Receive xrcb network signals for radio side.\nit's about emergency alerts, weather alerts, public announcements, and other information.", "dependencies": [], "neededBy": [], "labels": [], @@ -10206,7 +11340,7 @@ }, "com.qti.slaservice": { "list": "Misc", - "description": "Service Level Agreement (SLA) protocol that analyzes network performance, quality of service, \nand provides users with various parameters of network quality of service, \nsuch as: jitter delay, file transfer rate, TCP latency. BUT it's placebo.\nuses permission com.miui.analytics.onetrack.TRACK_EVENT also have a lot chinese stuff.", + "description": "Service Level Agreement (SLA) protocol that analyzes network performance, quality of service,\nand provides users with various parameters of network quality of service,\nsuch as: jitter delay, file transfer rate, TCP latency. BUT it's placebo.\nuses permission com.miui.analytics.onetrack.TRACK_EVENT also have a lot chinese stuff.", "dependencies": [], "neededBy": [], "labels": [], @@ -10230,7 +11364,7 @@ }, "com.qualcomm.qti.cne": { "list": "Misc", - "description": "CneApp (Connectivity Engine)\nRuns in the background as part of the System.\nEnables seamless hand-off between mobile data and Wi-Fi networks. Can also dynamically measure network performance to prioritize using the best one (I think that's part of \"Intelligently select the best Wi-Fi\" in settings).\nProbably worth keeping on; I noticed connection reliability getting worse when I disabled it.\nhttps://www.qualcomm.com/news/onq/2013/07/02/qualcomms-cne-bringing-smarts-3g4g-wi-fi-seamless-interworking\nhttps://programmersought.com/article/35091829299/", + "description": "CneApp (Connectivity Engine)\nRuns in the background as part of the System.\nEnables seamless hand-off between mobile data and Wi-Fi networks. Can also dynamically measure network performance to prioritize using the best one (I think that's part of\"Intelligently select the best Wi-Fi\" in settings).\nProbably worth keeping on; I noticed connection reliability getting worse when I disabled it.\nhttps://www.qualcomm.com/news/onq/2013/07/02/qualcomms-cne-bringing-smarts-3g4g-wi-fi-seamless-interworking\nhttps://programmersought.com/article/35091829299/", "dependencies": [], "neededBy": [], "labels": [], @@ -10318,7 +11452,7 @@ }, "com.qualcomm.qti.services.systemhelper": { "list": "Misc", - "description": "System Helper Service\nRuns \"SysHelperService\" in the background as part of the system.\nPermissions: DEVICE_POWER, READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, RECEIVE_BOOT_COMPLETED, WRITE_SETTINGS, WAKE_LOCK and ACCESS_SURFACE_FLINGER.\nAndroid simple network firewall utility service. On a RedMi Note 13 running HyperOS 2.6.0, no application is running after uninstalling this package.", + "description": "System Helper Service\nRuns\"SysHelperService\" in the background as part of the system.\nPermissions: DEVICE_POWER, READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, RECEIVE_BOOT_COMPLETED, WRITE_SETTINGS, WAKE_LOCK and ACCESS_SURFACE_FLINGER.\nAndroid simple network firewall utility service. On a RedMi Note 13 running HyperOS 2.6.0, no application is running after uninstalling this package.", "dependencies": [], "neededBy": [], "labels": [], @@ -10342,11 +11476,11 @@ }, "com.mediatek.miravision.ui": { "list": "Misc", - "description": "it's for SmartScreen and display effects.\nBUT I think it's not available and it's so bloated.", + "description": "Mediatek MiraVision\nProvides extensive hardware and software optimizations that improve the viewing quality.\nBUT I think it's not available and it's so bloated.\nhttps://www.mediatek.com/technology/miravision-for-smartphones", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.qualcomm.qti.simcontacts": { "list": "Misc", @@ -10358,7 +11492,7 @@ }, "com.qualcomm.qti.smq": { "list": "Misc", - "description": "QTR (Qualcomm Technology Reporting)\nRuns on boot.\nSeems like a telemetry package, supposedly sending hardware & software type, configuration and performance data.\nContains a \"QtiFeedbackActivity\" called \"Hardware Feedback\". When that hidden activity is launched through Activity Launcher you get a screen showing just a checkbox and this text:\n\"Collecting hardware and software type, configuration, and performance data helps Qualcomm improve next generation device battery life, security, and performance. Untick to disable.\"\nUnticking isn't remembered; it's ticked again next time you enter. There's also a \"Learn More\" link that leads to: http://reporting.qti.qualcomm.com/learnmore_en.html which doesn't load for me.", + "description": "QTR (Qualcomm Technology Reporting)\nRuns on boot.\nSeems like a telemetry package, supposedly sending hardware & software type, configuration and performance data.\nContains a\"QtiFeedbackActivity\" called\"Hardware Feedback\". When that hidden activity is launched through Activity Launcher you get a screen showing just a checkbox and this text:\n\"Collecting hardware and software type, configuration, and performance data helps Qualcomm improve next generation device battery life, security, and performance. Untick to disable.\"\nUnticking isn't remembered; it's ticked again next time you enter. There's also a\"Learn More\" link that leads to: http://reporting.qti.qualcomm.com/learnmore_en.html which doesn't load for me.", "dependencies": [], "neededBy": [], "labels": [], @@ -10366,7 +11500,7 @@ }, "com.qualcomm.qti.workloadclassifier": { "list": "Misc", - "description": "Runs \"WLCService\" in the background.\nI assume this has to do with CPU scheduling. Probably important for efficiency, if not basic operation.\nIn code I found: it's for performance and security? it categorize apps maybe for optimization.\nit's named workloadclassifier so it should do that. reads the list of installed applications, storage space.\nit's still unknown.", + "description": "Runs\"WLCService\" in the background.\nI assume this has to do with CPU scheduling. Probably important for efficiency, if not basic operation.\nIn code I found: it's for performance and security? it categorize apps maybe for optimization.\nit's named workloadclassifier so it should do that. reads the list of installed applications, storage space.\nit's still unknown.", "dependencies": [], "neededBy": [], "labels": [], @@ -10542,7 +11676,7 @@ }, "com.sec.android.smartfpsadjuster": { "list": "Oem", - "description": "SmartFPSAdjuster\nAdjusts FPS automatically in Samsung phones? Safe to delete.\nhttps://docs.samsungknox.com/CCMode/G985F_Q.pdf", + "description": "SmartFPSAdjuster\nResponsible for thermal camera adjustment and dynamic FPS control based on device temperature and hardware conditions\nLogging this data to feed an optimization algorithm using Q‑learning.\nSafe to delete.\nhttps://docs.samsungknox.com/CCMode/G985F_Q.pdf", "dependencies": [], "neededBy": [], "labels": [], @@ -10582,11 +11716,11 @@ }, "com.samsung.android.app.telephonyui": { "list": "Oem", - "description": "It's calling app from samsung China, Korea.\nI don't know how important this app is.", + "description": "Samsung Dialer UI.\nDisabling breaks Phone app settings and SIM Manager.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.samsung.android.appseparation": { "list": "Oem", @@ -10604,6 +11738,14 @@ "labels": [], "removal": "Advanced" }, + "com.samsung.android.callassistant": { + "list": "Oem", + "description": "Appears to handle a whole bunch of AI services related to Gallery and Phone. Can break stuff in OneUI 6.1+", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.samsung.phone.overlay.common": { "list": "Oem", "description": "Possibly the incoming-call screen?", @@ -10666,7 +11808,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.samsung.android.providers.contacts": { "list": "Oem", @@ -10972,6 +12114,22 @@ "labels": [], "removal": "Expert" }, + "com.tcl.guard": { + "list": "Oem", + "description": "TGuard. Runs in the background on boot.\nHas these services:\"Online Support\" (related to `com.tcl.usercare`?),\"IO Limit\",\"Health\" (device health?) stuff, battery and low-storage diagnostics. On model T509A, it links to `libTclRootCheck.so` (native shared dynamic library), very sus.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.tcl.ttvs": { + "list": "Oem", + "description": "TCSCore. Runs in the background all the time. Uses some Google tracking APIs. May request permission `org.microg.gms.STATUS_BROADCAST`, probably for detecting\"illegitimate\" Play Services installations.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.tcl.faceunlock": { "list": "Oem", "description": "Standard FaceUnlock functionality?\nUnlock your device by simply looking at the display.\nFace unlock is bad for security and privacy:\nhttps://www.ubergizmo.com/2017/03/galaxy-s8-facial-unlock-photograph/\nhttps://www.kaspersky.com/blog/face-unlock-insecurity/21618/\nhttps://www.freecodecamp.org/news/why-you-should-never-unlock-your-phone-with-your-face-79c07772a28/", @@ -11134,19 +12292,11 @@ }, "com.tct.gdpr": { "list": "Oem", - "description": "", + "description": "Whenever TCL updates their Privacy Policy, this app shows a notification prompting the user to read it. May include the\"User Experience Improvement Program\"", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Expert" - }, - "com.tct.onetouchbooster.a_overlay": { - "list": "Oem", - "description": "", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Expert" + "removal": "Recommended" }, "com.tct.privacymode": { "list": "Oem", @@ -11236,6 +12386,14 @@ "labels": [], "removal": "Expert" }, + "com.tct.contentcenter": { + "list": "Oem", + "description": "A panel that opens from the launcher (similar to\"samsung Free\"). Has news, weather forecasts, and a game center (similar to\"Game Booster\"). Has lots of trackers from facebook, bytedance, anythink, google, and other 3rd-parties", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.tct.weather": { "list": "Oem", "description": "Weather forecasting app.", @@ -11250,7 +12408,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.tct.wfcwebiew": { "list": "Oem", @@ -11286,7 +12444,7 @@ }, "com.lge.cic.eden.service": { "list": "Oem", - "description": "Memories album\nGallery automatically creates a Memories album with pictures and videos saved in the phone. \nMemories is a virtual album of pictures saved in the phone or SD card.\nSource : https://www.lg.com/hk_en/support/product-help/CT30019000-1433767985158-others\n", + "description": "Memories album\nGallery automatically creates a Memories album with pictures and videos saved in the phone.\nMemories is a virtual album of pictures saved in the phone or SD card.\nSource : https://www.lg.com/hk_en/support/product-help/CT30019000-1433767985158-others\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11374,7 +12532,7 @@ }, "com.lge.gcuv": { "list": "Oem", - "description": "GCUV\nNot 100% sure but @siraltus from XDA thinks it refers to \"Gauce Components\" which seems to be the LG's version of CSC \n(carrier sales code - automatic carrier-specific customization).\nIt gets run on first boot after factory reset, sets up the ROM features based on which carrier and country code is specified \nin the build.prop, and then gets frozen so it doesn't reconfigure things on subsequent boots.\nIt's basically the only person to mention \"Gauce components\" on the web (other than restricted LG webpages when using Google dorks).\nhttps://forum.xda-developers.com/tmobile-lg-v10/development/rom-lg-v10-h901-10c-debranded-debloated-t3277305/page12/page12\n", + "description": "GCUV\nNot 100% sure but @siraltus from XDA thinks it refers to\"Gauce Components\" which seems to be the LG's version of CSC\n(carrier sales code - automatic carrier-specific customization).\nIt gets run on first boot after factory reset, sets up the ROM features based on which carrier and country code is specified\nin the build.prop, and then gets frozen so it doesn't reconfigure things on subsequent boots.\nIt's basically the only person to mention\"Gauce components\" on the web (other than restricted LG webpages when using Google dorks).\nhttps://forum.xda-developers.com/tmobile-lg-v10/development/rom-lg-v10-h901-10c-debranded-debloated-t3277305/page12/page12\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11398,7 +12556,7 @@ }, "com.lge.gnsslogcat": { "list": "Oem", - "description": "GNSS Logcat\nUsed to dump GNSS logs. \n", + "description": "GNSS Logcat\nUsed to dump GNSS logs. \n", "dependencies": [], "neededBy": [], "labels": [], @@ -11414,7 +12572,7 @@ }, "com.lge.gnsstest": { "list": "Oem", - "description": "GNSS Test\nWoh ! Why does LG need so many GNSS test packages?! \n", + "description": "GNSS Test\nWoh ! Why does LG need so many GNSS test packages?!\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11486,7 +12644,7 @@ }, "com.lge.ime.solution.text": { "list": "Oem", - "description": "XT9 \nText predicting and correction for the LG keyboard.\nFor your culture (if you're young) : https://en.wikipedia.org/wiki/XT9\n\nWARNING: On LG G6 (and maybe on other LG phones) removing this may cause the LG keyboard to stop inputing characters. Make sure to use another keyboard before removing this package.", + "description": "XT9\nText predicting and correction for the LG keyboard.\nFor your culture (if you're young) : https://en.wikipedia.org/wiki/XT9\n\nWARNING: On LG G6 (and maybe on other LG phones) removing this may cause the LG keyboard to stop inputing characters. Make sure to use another keyboard before removing this package.", "dependencies": [], "neededBy": [], "labels": [], @@ -11510,7 +12668,7 @@ }, "com.lge.lgdmsclient": { "list": "Oem", - "description": "Actual \"Software Update\" App client\nI think you won't receive updates without this.\n", + "description": "Actual\"Software Update\" App client\nI think you won't receive updates without this.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11534,7 +12692,7 @@ }, "com.lge.lgmapui": { "list": "Oem", - "description": "LGMapUI\nUser Interface (UI) for displaying location tracking reccord on the Health app (com.lge.lifetracker) ? \n", + "description": "LGMapUI\nUser Interface (UI) for displaying location tracking reccord on the Health app (com.lge.lifetracker) ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11542,7 +12700,7 @@ }, "com.lge.LGSetupView": { "list": "Oem", - "description": "Setup View\nLG first setup (related to com.android.LGSetupWizard). \nThe first time you turn your device on, a Welcome screen is displayed. It guides you through the basics of setting up your device.\n", + "description": "Setup View\nLG first setup (related to com.android.LGSetupWizard).\nThe first time you turn your device on, a Welcome screen is displayed. It guides you through the basics of setting up your device.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11558,7 +12716,7 @@ }, "com.lge.lifetracker": { "list": "Oem", - "description": "LG Health (https://play.google.com/store/apps/details?id=com.lge.lifetracker)\nAccording to users reviews, it is a very bad activity tracking app. \nPrivacy wise, you should never use this kind of thing obviously. \nhttps://www.lg.com/us/support/help-library/lg-android-lg-health-CT30013120-20150103629401\n", + "description": "LG Health (https://play.google.com/store/apps/details?id=com.lge.lifetracker)\nAccording to users reviews, it is a very bad activity tracking app.\nPrivacy wise, you should never use this kind of thing obviously.\nhttps://www.lg.com/us/support/help-library/lg-android-lg-health-CT30013120-20150103629401\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11574,7 +12732,7 @@ }, "com.lge.mlt": { "list": "Oem", - "description": "LG MLT\nRun in background all the time and probably serves purpose to help LG remote support. The thing is this acts as a good spyware. \nIt tries to track all your activity and logs GPS position together with the details gathered, and that includes calls, apps starting etc...\nAll data is collected and placed on /mpt partition, it seems not to be per reboot, but actually kept during flash and upgrades.\n#\nhttps://forum.xda-developers.com/showthread.php?t=2187920\n", + "description": "LG MLT\nRun in background all the time and probably serves purpose to help LG remote support. The thing is this acts as a good spyware.\nIt tries to track all your activity and logs GPS position together with the details gathered, and that includes calls, apps starting etc...\nAll data is collected and placed on /mpt partition, it seems not to be per reboot, but actually kept during flash and upgrades.\n#\nhttps://forum.xda-developers.com/showthread.php?t=2187920\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11590,7 +12748,7 @@ }, "com.lge.musicshare": { "list": "Oem", - "description": "LG Audio Share \nEnables you to connect two devices so that you can share the sound from music or video files with another LG devices.\nhttps://www.lg.com/hk_en/support/product-help/CT30007700-20150123957406-others\n", + "description": "LG Audio Share\nEnables you to connect two devices so that you can share the sound from music or video files with another LG devices.\nhttps://www.lg.com/hk_en/support/product-help/CT30007700-20150123957406-others\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11614,7 +12772,7 @@ }, "com.lge.phonemanagement": { "list": "Oem", - "description": "Smart Doctor App\nEnables you to shut down idle apps and delete temporary files.\nLets you also see phone battery, mobile data, apps, network status and usage patterns.\nOn the paper it seems good but in practise, Android handle 8+ handles very well idles apps. \nhttps://www.lg.com/ca_en/support/product-help/CT20098088-20150129256824-others\n", + "description": "Smart Doctor App\nEnables you to shut down idle apps and delete temporary files.\nLets you also see phone battery, mobile data, apps, network status and usage patterns.\nOn the paper it seems good but in practise, Android handle 8+ handles very well idles apps.\nhttps://www.lg.com/ca_en/support/product-help/CT20098088-20150129256824-others\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11654,7 +12812,7 @@ }, "com.lge.remote.lgairdrive": { "list": "Oem", - "description": "LG AirDrive\nLets you to control files in your device via a wireless connection. \nTo use it, you need to sign in to your LG account on both the PC and mobile device.\nhttps://www.lg.com/africa/support/product-help/CT20080025-1436354408798-others\n \nLG AirDrive settings\nSee package below.\n", + "description": "LG AirDrive\nLets you to control files in your device via a wireless connection.\nTo use it, you need to sign in to your LG account on both the PC and mobile device.\nhttps://www.lg.com/africa/support/product-help/CT20080025-1436354408798-others\n\nLG AirDrive settings\nSee package below.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11662,12 +12820,20 @@ }, "com.lge.remote.setting": { "list": "Oem", - "description": "LG AirDrive\nLets you to control files in your device via a wireless connection. \nTo use it, you need to sign in to your LG account on both the PC and mobile device.\nhttps://www.lg.com/africa/support/product-help/CT20080025-1436354408798-others\n \nLG AirDrive settings\nSee package above.\n", + "description": "LG AirDrive\nLets you to control files in your device via a wireless connection.\nTo use it, you need to sign in to your LG account on both the PC and mobile device.\nhttps://www.lg.com/africa/support/product-help/CT20080025-1436354408798-others\n\nLG AirDrive settings\nSee package above.\n", "dependencies": [], "neededBy": [], "labels": [], "removal": "Recommended" }, + "com.lge.sizechangable.musicwidget.music": { + "list": "Oem", + "description": "Music widget\nIt breaks when LG Music is removed.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, "com.lge.sizechangable.weather": { "list": "Oem", "description": "Music widget\nNot sure if it only manages Music widget for the launcher or also for the lockscreen.\n\nWeather widget for the home screen.\n", @@ -11702,7 +12868,7 @@ }, "com.lge.smartshare": { "list": "Oem", - "description": "SmartShare \nFeature that uses DLNA technology to stream multimedia contents between DLNA devices.\nDLNA is a non-profit trade organisation which defines standards that enable devices to share stuff with each other.\nBasically LG provides a way to stream multimedia contents from your phone to your smart TV (or via a DLNA plugin)\nhttps://www.lg.com/ca_en/support/product-help/CT31903570-1428542236040-file-media-transfer-pictures-music-etc\n", + "description": "SmartShare\nFeature that uses DLNA technology to stream multimedia contents between DLNA devices.\nDLNA is a non-profit trade organisation which defines standards that enable devices to share stuff with each other.\nBasically LG provides a way to stream multimedia contents from your phone to your smart TV (or via a DLNA plugin)\nhttps://www.lg.com/ca_en/support/product-help/CT31903570-1428542236040-file-media-transfer-pictures-music-etc\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11710,7 +12876,7 @@ }, "com.lge.smartshare.provider": { "list": "Oem", - "description": "Provider for Smart Share. \nNeeded by com.lge.smartshare.\nREMINDER : content providers help an application manage access to data stored by itself, stored by other apps, \nand provide a way to share data with other apps. They encapsulate the data, and provide mechanisms for defining data security\n", + "description": "Provider for Smart Share.\nNeeded by com.lge.smartshare.\nREMINDER : content providers help an application manage access to data stored by itself, stored by other apps,\nand provide a way to share data with other apps. They encapsulate the data, and provide mechanisms for defining data security\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11718,7 +12884,7 @@ }, "com.lge.smartsharepush": { "list": "Oem", - "description": "Smart Share Push\nObviously related to Smart Share but I don't know its exact purpose. \n", + "description": "Smart Share Push\nObviously related to Smart Share but I don't know its exact purpose.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11726,7 +12892,7 @@ }, "com.lge.snappage": { "list": "Oem", - "description": "Snap Page\nPart of the QuickMemo+ app, lets you capture the text/images/URL from a web page without grabbing ads.\nIt’s much like instapaper or pocket app, but it works locally, like reading mode on some browsers, saving only the body of the article. \nhttp://www.lg.com/us/mobile-phones/g4/display\n", + "description": "Snap Page\nPart of the QuickMemo+ app, lets you capture the text/images/URL from a web page without grabbing ads.\nIt’s much like instapaper or pocket app, but it works locally, like reading mode on some browsers, saving only the body of the article.\nhttp://www.lg.com/us/mobile-phones/g4/display\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11748,6 +12914,14 @@ "labels": [], "removal": "Recommended" }, + "com.lge.upsell": { + "list": "Oem", + "description": "Contains dialogs from different carriers about upgrading the mobile plan\nShould be safe to remove?\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, "com.lge.video.vr.wallpaper": { "list": "Oem", "description": "Video Wallpaper\nLG 360° VR Wallpapers\n", @@ -11774,12 +12948,20 @@ }, "com.lge.voicecare": { "list": "Oem", - "description": "LG Voice care\nAllows you to use your device if the touch screen or display is damaged. \nYou must agree to location-based information use and personal information collection to use Voice Care. \nhttps://www.lg.com/hk_en/support/product-help/CT20136018-20150122834174-others\n", + "description": "LG Voice care\nAllows you to use your device if the touch screen or display is damaged.\nYou must agree to location-based information use and personal information collection to use Voice Care.\nhttps://www.lg.com/hk_en/support/product-help/CT20136018-20150122834174-others\n", "dependencies": [], "neededBy": [], "labels": [], "removal": "Recommended" }, + "com.lge.voicerecorder": { + "list": "Oem", + "description": "LG Voice Recorder\nSimple voice recording app.\nSafe to remove.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, "com.lge.vrplayer": { "list": "Oem", "description": "LG VR player\nEnables you to watch 360° pictures/videos.\n", @@ -11822,7 +13004,7 @@ }, "com.lge.wifi.p2p": { "list": "Oem", - "description": "LG P2p Service \nWifi-drect P2P allows the device to discover the services of nearby devices directly, without being connected to a network.\nNeeded for LG Wifi-direct feature.\nhttps://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct\n", + "description": "LG P2p Service\nWifi-drect P2P allows the device to discover the services of nearby devices directly, without being connected to a network.\nNeeded for LG Wifi-direct feature.\nhttps://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11830,7 +13012,7 @@ }, "com.lge.lgfmservice": { "list": "Oem", - "description": "Wifi Hotspot service\nREMINDER : Hotspot enable you to share the phone’s 4G data connection with any Wi-Fi capable devices.\nIt is not the Hotspot feature. Only the widget ! \n\nDual SIM status widget\nProbably only present in dual sim LG phone variants. Does not remove the persistent notification or dual SIM functionality.\n\nService menus. I believe if you remove the last one the secret code you can dial doesn't work anymore (who needs it anyway..?)\n\nLG support App remote access\nYou probably don't want that to happen\n\nLAOP test [MORE INFO NEEDED]\nI don't know what LAOP is. I could not find information about it. It's a test so it's probably fine. I have removed it.", + "description": "Wifi Hotspot service\nREMINDER : Hotspot enable you to share the phone’s 4G data connection with any Wi-Fi capable devices.\nIt is not the Hotspot feature. Only the widget !\n\nDual SIM status widget\nProbably only present in dual sim LG phone variants. Does not remove the persistent notification or dual SIM functionality.\n\nService menus. I believe if you remove the last one the secret code you can dial doesn't work anymore (who needs it anyway..?)\n\nLG support App remote access\nYou probably don't want that to happen\n\nLAOP test [MORE INFO NEEDED]\nI don't know what LAOP is. I could not find information about it. It's a test so it's probably fine. I have removed it.", "dependencies": [], "neededBy": [], "labels": [], @@ -11862,7 +13044,7 @@ }, "com.lge.homeselector": { "list": "Oem", - "description": "LG Home selector\nThis is the settings menu for the home launcher (present in the settings app as \"Home launcher\")\nIf you remove this app, the Home screen settings menu is gone from settings app. (not needed if you use external launcher)\n You can still switch between installed launchers, the package name is a bit misleading.\n", + "description": "LG Home selector\nThis is the settings menu for the home launcher (present in the settings app as\"Home launcher\")\nIf you remove this app, the Home screen settings menu is gone from settings app. (not needed if you use external launcher)\n You can still switch between installed launchers, the package name is a bit misleading.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11870,7 +13052,7 @@ }, "com.lge.launcher2": { "list": "Oem", - "description": "LG Home (v2)\nStock launcher\nIt's basically the home screen, the way icons apps are organized and displayed.\nDON'T REMOVE THIS IF YOU DIDN'T INSTALL ANOTHER LAUNCHER!\nNOTE : Yeah there is another package described as \"launcher\". Normally, you only have one of them on your phone. \n", + "description": "LG Home (v2)\nStock launcher\nIt's basically the home screen, the way icons apps are organized and displayed.\nDON'T REMOVE THIS IF YOU DIDN'T INSTALL ANOTHER LAUNCHER!\nNOTE : Yeah there is another package described as\"launcher\". Normally, you only have one of them on your phone.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11878,7 +13060,7 @@ }, "com.lge.launcher3": { "list": "Oem", - "description": "LG Home (v3)\nStock launcher\nIt's basically the home screen, the way icons apps are organized and displayed.\nDON'T REMOVE THIS IF YOU DIDN'T INSTALL ANOTHER LAUNCHER!\nNOTE : Yeah there is 3 packages described as \"launcher\". Normally, you only have one of them on your phone. \n", + "description": "LG Home (v3)\nStock launcher\nIt's basically the home screen, the way icons apps are organized and displayed.\nDON'T REMOVE THIS IF YOU DIDN'T INSTALL ANOTHER LAUNCHER!\nNOTE : Yeah there is 3 packages described as\"launcher\". Normally, you only have one of them on your phone.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11894,7 +13076,7 @@ }, "com.lge.floatingbar": { "list": "Oem", - "description": "LG Floating bar\nLets you put shortcuts to apps or features, as well as quick access to contacts and music player controls on a \"floating bar\" on the Home screen.\nhttps://www.neowin.net/news/lg-v30-closer-look-floating-bar/\n", + "description": "LG Floating bar\nLets you put shortcuts to apps or features, as well as quick access to contacts and music player controls on a\"floating bar\" on the Home screen.\nhttps://www.neowin.net/news/lg-v30-closer-look-floating-bar/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -11908,6 +13090,14 @@ "labels": [], "removal": "Expert" }, + "com.lge.theme.blackgold": { + "list": "Oem", + "description": "LG Black Bold theme.\nSafe to remove, but also probably pointless to do so as most theme packages are just data containers.\nMake sure you don't delete the package for the theme you're currently using. I don't know what will happen then.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.android.partnerbrowsercustomizations.btl.s600ww.overlay": { "list": "Oem", "description": "Theme overlay for some browser customization?", @@ -12134,7 +13324,7 @@ }, "com.evenwell.permissiondetection.overlay.base.s600ww": { "list": "Oem", - "description": "A theme overlay for some \"permissiondetection\" package?", + "description": "A theme overlay for some\"permissiondetection\" package?", "dependencies": [], "neededBy": [], "labels": [], @@ -12368,7 +13558,7 @@ }, "com.coloros.backuprestore": { "list": "Oem", - "description": "Most likely Oppo backup/restore feature \n", + "description": "Most likely Oppo backup/restore feature\n", "dependencies": [], "neededBy": [], "labels": [], @@ -12440,11 +13630,11 @@ }, "com.coloros.widget.smallweather": { "list": "Oem", - "description": "", + "description": "It is classified as a Safe app to remove. It is a widget that displays clock and weather, weather warnings, the clock, 15-day forecasts, etc.\nDoes not work with the at a Glance Google widget", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.coremobility.app.vnotes": { "list": "Oem", @@ -12488,38 +13678,6 @@ "labels": [], "removal": "Recommended" }, - "com.nttdocomo.android.applicationmanager": { - "list": "Carrier", - "description": "Docomo Application Manager", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, - "com.nttdocomo.android.store": { - "list": "Carrier", - "description": "Docomo App Market", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, - "com.nttdocomo.android.dhome": { - "list": "Carrier", - "description": "Docomo Launcher", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Advanced" - }, - "com.nttdocomo.android.initialization": { - "list": "Carrier", - "description": "Docomo Initialization app", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, "com.oppo.fingerprints.fingerprintsensortest": { "list": "Oem", "description": "Fingerprint sensort test\n", @@ -12530,7 +13688,7 @@ }, "com.oppo.logkitservice": { "list": "Oem", - "description": "Probably same as \"com.oem.oemlogkit\", which is a shady logging package on Oneplus devices.", + "description": "Probably same as\"com.oem.oemlogkit\", which is a shady logging package on Oneplus devices.", "dependencies": [], "neededBy": [], "labels": [], @@ -12698,15 +13856,15 @@ }, "com.amazon.venezia": { "list": "Misc", - "description": "Amazon AppStore\n", + "description": "Amazon AppStore\n Removal will result in breakage of app drawer on Amazon Fire TV devices.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.amazon.aa": { "list": "Misc", - "description": "Amazon Assistant app. Nice spyware ! \nShows you recommended products available on Amazon and price compare as you shop across the web.\nNOTE : https://www.gadgetguy.com.au/amazon-assistant-spies-on-you/\n", + "description": "Amazon Assistant app. Nice spyware !\nShows you recommended products available on Amazon and price compare as you shop across the web.\nNOTE : https://www.gadgetguy.com.au/amazon-assistant-spies-on-you/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -12786,7 +13944,7 @@ }, "com.facebook.services": { "list": "Misc", - "description": "Facebook Services is a tool that lets you manage different Facebook services automatically using your Android device. \nIn particular, the tool focuses on searching for nearby shops and establishments based on your interests.\nI don't know if this a dependency for com.facebook.katana but nobody cares because we all want to delete all the Facebook stuff right ?!!\n", + "description": "Facebook Services is a tool that lets you manage different Facebook services automatically using your Android device.\nIn particular, the tool focuses on searching for nearby shops and establishments based on your interests.\nI don't know if this a dependency for com.facebook.katana but nobody cares because we all want to delete all the Facebook stuff right ?!!\n", "dependencies": [], "neededBy": [], "labels": [], @@ -12810,7 +13968,7 @@ }, "com.whatsapp": { "list": "Misc", - "description": "Whatsapp (https://play.google.com/store/apps/details?id=com.whatsapp)\n)\n", + "description": "Whatsapp messenger.\nRequires Google Play Services to receive messages in the background.\nhttps://play.google.com/store/apps/details?id=com.whatsapp", "dependencies": [], "neededBy": [], "labels": [], @@ -12834,7 +13992,7 @@ }, "com.microsoft.office.powerpoint": { "list": "Misc", - "description": "", + "description": "PowerPoint\n", "dependencies": [], "neededBy": [], "labels": [], @@ -12858,7 +14016,7 @@ }, "com.microsoft.office.officehub": { "list": "Misc", - "description": "Microsoft Office Mobile\nIncludes the complete Word, PowerPoint, and Excel apps to offer a convenient office experience on the go. \n", + "description": "Microsoft Office Mobile\nIncludes the complete Word, PowerPoint, and Excel apps to offer a convenient office experience on the go.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -12922,7 +14080,7 @@ }, "org.codeaurora.ims": { "list": "Misc", - "description": "IMS(Ip Multimedia Subsystem) is an open industry standard for voice and multimedia communications over packet-based IP networks (VoLTE/VoIP/Wifi calling).\nRuns in the background as part of the system, with Google's IMS(com.google.android.ims, \"Carrier Services\") disabled, I haven't checked if it'd run with Carrier Services enabled.", + "description": "IMS(Ip Multimedia Subsystem) is an open industry standard for voice and multimedia communications over packet-based IP networks (VoLTE/VoIP/Wifi calling).\nRuns in the background as part of the system, with Google's IMS(com.google.android.ims,\"Carrier Services\") disabled, I haven't checked if it'd run with Carrier Services enabled.", "dependencies": [], "neededBy": [], "labels": [], @@ -12970,7 +14128,7 @@ }, "com.qti.snapdragon.qdcm_ff": { "list": "Misc", - "description": "Qualcomm Display Color Management tool\nAttempts to \"make colors look vibrant and true to life\". No idea if it actually does something useful or if it's only some garbage dynamic color tuning (they tend to destroy colors).\nContains a service, but I've never seen it run on my Oneplus 9. Could be tied to color \"improvement\" settings in Settings->Display (all of which are off for me).", + "description": "Qualcomm Display Color Management tool\nAttempts to\"make colors look vibrant and true to life\". No idea if it actually does something useful or if it's only some garbage dynamic color tuning (they tend to destroy colors).\nContains a service, but I've never seen it run on my Oneplus 9. Could be tied to color\"improvement\" settings in Settings->Display (all of which are off for me).", "dependencies": [], "neededBy": [], "labels": [], @@ -13002,7 +14160,7 @@ }, "com.qualcomm.atfwd": { "list": "Misc", - "description": "Used to send AT command messages from/to the modem\nAttention commands commands are a collection of short-string commands developed in the early 1980s \nthat were designed to be transmitted via phone lines and control modems. Different AT command strings can be merged together \nto tell a modem to dial, hang up, or change connection parameters. \nSmartphones include a basic modem component inside them, which allows the smartphone to connect to the Internet \nvia its telephony function.\nThis can be abused. It's been known for many years that Android devices are vulnerable to attacks carried out via AT commands:\nhttps://www.bleepingcomputer.com/news/security/smartphones-from-11-oems-vulnerable-to-attacks-via-hidden-at-commands/\n", + "description": "Used to send AT command messages from/to the modem\nAttention commands commands are a collection of short-string commands developed in the early 1980s\nthat were designed to be transmitted via phone lines and control modems. Different AT command strings can be merged together\nto tell a modem to dial, hang up, or change connection parameters.\nSmartphones include a basic modem component inside them, which allows the smartphone to connect to the Internet\nvia its telephony function.\nThis can be abused. It's been known for many years that Android devices are vulnerable to attacks carried out via AT commands:\nhttps://www.bleepingcomputer.com/news/security/smartphones-from-11-oems-vulnerable-to-attacks-via-hidden-at-commands/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13010,7 +14168,7 @@ }, "com.qualcomm.cabl": { "list": "Misc", - "description": "Content Adaptative Backlight Settings\nCABL will try to adjust the image being displaye by changing the contrast/quality/image backlight depending on \nthe content on the screen.\nDownside to this is loss of dynamic range which results in some colors being washed out/clipped.\nCABL != Auto brightness (which doesn't change the content of the screen, only the brightness)\nNOTE: You may want to remove this. It does not work very well on many phones\nhttps://mobileinternist.com/disable-adaptive-brightness-android\n", + "description": "Content Adaptative Backlight Settings\nCABL will try to adjust the image being displaye by changing the contrast/quality/image backlight depending on\nthe content on the screen.\nDownside to this is loss of dynamic range which results in some colors being washed out/clipped.\nCABL != Auto brightness (which doesn't change the content of the screen, only the brightness)\nNOTE: You may want to remove this. It does not work very well on many phones\nhttps://mobileinternist.com/disable-adaptive-brightness-android\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13162,7 +14320,7 @@ }, "com.qualcomm.qti.server.qtiwifi": { "list": "Misc", - "description": "it's made for analytics.\nThis service can be used to have oem specific feature development. \nCurrently this service is being used to collect CSI data from cfrtool \nvia hidl and then pass the data to application(user level).", + "description": "it's made for analytics.\nThis service can be used to have OEM specific feature development.\nCurrently this service is being used to collect CSI data from cfrtool\nvia hidl and then pass the data to application(user level).", "dependencies": [], "neededBy": [], "labels": [], @@ -13202,7 +14360,7 @@ }, "com.qualcomm.qti.auth.fidocryptoservice": { "list": "Misc", - "description": "Qualcomm FIDO implementation. \nFIDO : https://en.wikipedia.org/wiki/FIDO_Alliance\nFido is a set of open technical specifications for mechanisms of authenticating users to online services that do not depend on passwords.\nhttps://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-glossary.html\nhttps://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-overview-v2.0-rd-20170927.html\n", + "description": "Qualcomm FIDO implementation.\nFIDO : https://en.wikipedia.org/wiki/FIDO_Alliance\nFido is a set of open technical specifications for mechanisms of authenticating users to online services that do not depend on passwords.\nhttps://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-glossary.html\nhttps://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-overview-v2.0-rd-20170927.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13262,7 +14420,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.mediatek.zramwritebackoverlay": { "list": "Misc", @@ -13326,8 +14484,24 @@ "dependencies": [], "neededBy": [], "labels": [], + "removal": "Advanced" + }, + "com.mediatek.filemanager": { + "list": "Misc", + "description": "The com.mediatek.filemanager package is MediaTek’s proprietary file management app, designed to handle file browsing, organization, and management on devices with MediaTek chipsets. While it provides basic file management functions, there are many more advanced and feature-rich file manager apps available on Google Play.", + "dependencies": [], + "neededBy": [], + "labels": [], "removal": "Recommended" }, + "com.mediatek.fwk.plugin": { + "list": "Misc", + "description": "The com.mediatek.fwk.plugin package is part of MediaTek’s framework for managing plugins and extensions specific to MediaTek’s hardware and software ecosystem. This package may handle integration and support for various MediaTek-specific features and enhancements. Removing this package could affect some advanced functionalities or custom features provided by MediaTek, but it generally should not disrupt basic system operations.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.mediatek.frameworkresoverlay": { "list": "Misc", "description": "It have something to config AOD.\nAnd power saving.", @@ -13350,7 +14524,15 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" + }, + "com.mediatek.security": { + "list": "Misc", + "description": "The com.mediatek.security package is part of MediaTek’s security suite, providing features such as malware protection, privacy settings, and secure browsing options. While the package may offer added security features specific to MediaTek devices, there are alternative security solutions available on Google Play that can provide similar or enhanced protection. Removing this package might lead to a loss of MediaTek-specific security features, but it is generally not critical to the basic operation of the device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" }, "com.mediatek.SettingsProviderResOverlay": { "list": "Misc", @@ -13358,7 +14540,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.mediatek.systemuiwmshellresoverlay": { "list": "Misc", @@ -13410,7 +14592,7 @@ }, "com.mediatek.capctrl.service": { "list": "Misc", - "description": "It have mtkradioex. These are used for corporate deployment/controlling of devices.", + "description": "It have mtkradioex components used for corporate device management and telephony control.\nRemoving this will break key telephony functions such as SIM detection and carrier configuration, and cause com.android.phone to crash repeatedly.", "dependencies": [], "neededBy": [], "labels": [], @@ -13424,6 +14606,14 @@ "labels": [], "removal": "Advanced" }, + "com.mediatek.videoplayer": { + "list": "Misc", + "description": "The com.mediatek.videoplayer package is MediaTek’s default video player app, designed to handle video playback and provide basic media management features. Since there are numerous alternative video player apps available on Google Play that offer advanced features and better performance, removing this package is generally recommended.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.mediatek.voicecommand": { "list": "Misc", "description": "It's for voice commands like control music playing or voice control for alarm, camera.\nBut how to get access to it?\nProbably you need that for voice recognition but not sure.\nMaybe related to https://www.mediatek.com/products/smart-home/voice-assistant-devices", @@ -13490,7 +14680,7 @@ }, "com.mediatek.telephony": { "list": "Misc", - "description": "allows you to get information about the available \nSIMs/subscriptions and listen for changes or activity on the SIM cards, such as call or data activity or \nconnected cell details. In addition, the API enables apps to create SMS messages and send them using \na specific SIM card. it's not useful.", + "description": "allows you to get information about the available\nSIMs/subscriptions and listen for changes or activity on the SIM cards, such as call or data activity or\nconnected cell details. In addition, the API enables apps to create SMS messages and send them using\na specific SIM card. it's not useful.", "dependencies": [], "neededBy": [], "labels": [], @@ -13594,7 +14784,7 @@ }, "com.qti.xdivert": { "list": "Misc", - "description": "Smart-Divert\nIf enabled, diverts your calls to another number.\nYou can choose to divert all calls, divert on no reply or divert when the line is busy.\nWhere can you enable/disable this feature? \n", + "description": "Smart-Divert\nIf enabled, diverts your calls to another number.\nYou can choose to divert all calls, divert on no reply or divert when the line is busy.\nWhere can you enable/disable this feature?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13602,7 +14792,7 @@ }, "com.quicinc.cne.CNEService": { "list": "Misc", - "description": "Qualcomm Connectivity Engine\nEnables seamless hand-off between mobile data and Wi-Fi networks. Can also dynamically measure network performance to prioritize using the best one (I think that's part of \"Intelligently select the best Wi-Fi\" in settings).\nProbably worth keeping on; I noticed connection reliability getting worse when I disabled it.\nhttps://www.qualcomm.com/news/onq/2013/07/02/qualcomms-cne-bringing-smarts-3g4g-wi-fi-seamless-interworking\nhttps://programmersought.com/article/35091829299/", + "description": "Qualcomm Connectivity Engine\nEnables seamless hand-off between mobile data and Wi-Fi networks. Can also dynamically measure network performance to prioritize using the best one (I think that's part of\"Intelligently select the best Wi-Fi\" in settings).\nProbably worth keeping on; I noticed connection reliability getting worse when I disabled it.\nhttps://www.qualcomm.com/news/onq/2013/07/02/qualcomms-cne-bringing-smarts-3g4g-wi-fi-seamless-interworking\nhttps://programmersought.com/article/35091829299/", "dependencies": [], "neededBy": [], "labels": [], @@ -13666,7 +14856,7 @@ }, "com.qualcomm.qti.uim": { "list": "Misc", - "description": "Runs \"RemoteSimLockService\" in the background.\nThis might be the only remote SIM lock service, just called UIM because R-UIM(Removeable-UserIdentityModule) is a variant of SIM commonly used in Asia.", + "description": "Runs\"RemoteSimLockService\" in the background.\nThis might be the only remote SIM lock service, just called UIM because R-UIM(Removeable-UserIdentityModule) is a variant of SIM commonly used in Asia.", "dependencies": [], "neededBy": [], "labels": [], @@ -13674,7 +14864,7 @@ }, "com.qualcomm.qti.uimGbaApp": { "list": "Misc", - "description": "Contains a \"GbaService\", Related to uim card (R-UIM is a type of SIM card mainly used in Asia)", + "description": "Contains a\"GbaService\", Related to uim card (R-UIM is a type of SIM card mainly used in Asia)", "dependencies": [], "neededBy": [], "labels": [], @@ -13738,7 +14928,7 @@ }, "com.blurb.checkout": { "list": "Misc", - "description": "Blurb Checkout \nProvides book purchase and checkout for Samsung’s Story Album app (discontinued)\n", + "description": "Blurb Checkout\nProvides book purchase and checkout for Samsung’s Story Album app (discontinued)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13794,7 +14984,7 @@ }, "com.crowdcare.agent.k": { "list": "Misc", - "description": "Crowdcare is now Wysdom.AI\nFrom their Twitter description: the easiest way for businesses to improve customer satisfaction, contain costs, \nand generate revenue by using #AI to power customer experiences.\nWysdom.AI has joined the Microsoft Partner Network in 2018\nhttps://wysdom.ai/privacy-policy/ (not good)\n", + "description": "Crowdcare is now Wysdom.AI\nFrom their Twitter description: the easiest way for businesses to improve customer satisfaction, contain costs,\nand generate revenue by using #AI to power customer experiences.\nWysdom.AI has joined the Microsoft Partner Network in 2018\nhttps://wysdom.ai/privacy-policy/ (not good)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13850,7 +15040,7 @@ }, "com.dna.solitaireapp": { "list": "Misc", - "description": "Solitaire Game app from DNA company ? \n", + "description": "Solitaire Game app from DNA company ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13914,7 +15104,7 @@ }, "com.galaxyfirsatlari": { "list": "Misc", - "description": "Galaxy Fırsatları (https://play.google.com/store/apps/details?id=com.galaxyfirsatlari)\nSamsung-only app for Turkish people\nRecommands you stuff to buy. You are supposed to save money but we all know this kind of apps\nencourages consumption.\nExodus found 10 trackers and 17 permissions : https://reports.exodus-privacy.eu.org/fr/reports/143830/ \n", + "description": "Galaxy Fırsatları (https://play.google.com/store/apps/details?id=com.galaxyfirsatlari)\nSamsung-only app for Turkish people\nRecommands you stuff to buy. You are supposed to save money but we all know this kind of apps\nencourages consumption.\nExodus found 10 trackers and 17 permissions : https://reports.exodus-privacy.eu.org/fr/reports/143830/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -13922,7 +15112,7 @@ }, "com.generalmobi.go2pay": { "list": "Misc", - "description": "Go2Pay (https://play.google.com/store/apps/details?id=com.generalmobi.go2pay)\nPayment app that offers mobile pre-paid recharges and post-paid bill payment, data card recharges and bill payment, \nDTH recharges through cashless transactions.\nDTH = Direct To Home Television \n", + "description": "Go2Pay (https://play.google.com/store/apps/details?id=com.generalmobi.go2pay)\nPayment app that offers mobile pre-paid recharges and post-paid bill payment, data card recharges and bill payment,\nDTH recharges through cashless transactions.\nDTH = Direct To Home Television\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14010,7 +15200,7 @@ }, "com.ironsource.appcloud.oobe.huawei": { "list": "Misc", - "description": "Essentials apps\nApp which promotes some other apps (and encourages you to install them)\nDeveloped by IronSource, a \"next-generation advertising company\" \nhttps://aura.ironsrc.com/ (app) | https://company.ironsrc.com/ (company)\nWhen you try to read their privacy policy you arrive to an outstanding blank PDF file!\n(http://www.ironsrc.com/wp-content/uploads/2019/03/ironSource-Privacy-Policy.pdf)\n", + "description": "Essentials apps\nApp which promotes some other apps (and encourages you to install them)\nDeveloped by IronSource, a\"next-generation advertising company\"\nhttps://aura.ironsrc.com/ (app) | https://company.ironsrc.com/ (company)\nWhen you try to read their privacy policy you arrive to an outstanding blank PDF file!\n(http://www.ironsrc.com/wp-content/uploads/2019/03/ironSource-Privacy-Policy.pdf)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14072,6 +15262,30 @@ "labels": [], "removal": "Recommended" }, + "com.nbbird.hardwareinfo": { + "list": "Oem", + "description": "The com.nbbird.hardwareinfo package is likely associated with providing detailed information about the device’s hardware components, such as CPU, GPU, memory, and other system specifications. This app might be used for diagnostics or detailed hardware monitoring specific to the device. Removing it might disable access to this hardware information and could affect the ability to view detailed system diagnostics. However, it generally does not affect core system functionality and should not cause bootloop issues.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nbbsw.mmi_test": { + "list": "Oem", + "description": "The com.nbbsw.mmi_test package is likely associated with the Mobile Management Interface (MMI) testing tools provided by the OEM, possibly used for diagnostic and testing purposes to check various hardware and software functions of the device. Removing this package might impact the ability to perform certain diagnostic tests or troubleshooting functions provided by the OEM. While its removal should not affect the basic operation of the device, it could limit access to some specific testing tools or functionalities, which might be used for device maintenance or troubleshooting.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nbbsw.theme": { + "list": "Oem", + "description": "The com.nbbsw.theme package is likely related to theme management or customization features provided by the OEM, allowing users to apply and manage themes or visual styles on the device. Since many third-party launchers and theme apps available on Google Play offer similar or enhanced customization options, removing this package is generally recommended.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.netflix.mediaclient": { "list": "Misc", "description": "Netflix app (https://play.google.com/store/apps/details?id=com.netflix.mediaclient)\n", @@ -14104,6 +15318,14 @@ "labels": [], "removal": "Recommended" }, + "com.nuumobile.agingtest": { + "list": "Oem", + "description": "The com.nuumobile.agingtest package is used for running diagnostic tests related to hardware aging or wear, likely provided by the OEM. Since this package is mainly for diagnostic purposes and does not impact the core functionality of the device, it is safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.opera.branding": { "list": "Misc", "description": "Opera Branding Provider\nDon't know what it really does.\n", @@ -14138,7 +15360,7 @@ }, "com.opera.max.preinstall": { "list": "Misc", - "description": "Opera Max (discontinued)\nSystem-wide data-saving proxy that funnell all app data through Opera’s servers to compress images and videos \n", + "description": "Opera Max (discontinued)\nSystem-wide data-saving proxy that funnell all app data through Opera’s servers to compress images and videos\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14154,7 +15376,7 @@ }, "com.phonepe.app": { "list": "Misc", - "description": "PhonePe (https://play.google.com/store/apps/details?id=com.phonepe.app)\nPhonePe is a payment app that allows indian users to use BHIM UPI, your credit card and debit card or wallet to recharge your mobile phone, \npay your utility bills and also make instant payments at offline and online stores.\nPhonePe is an indian company (https://en.wikipedia.org/wiki/PhonePe)\nBHIM = Bharat Interface for Money : https://en.wikipedia.org/wiki/BHIM\nUPI = Unified Payement Interface : https://en.wikipedia.org/wiki/Unified_Payments_Interface\n", + "description": "PhonePe (https://play.google.com/store/apps/details?id=com.phonepe.app)\nPhonePe is a payment app that allows indian users to use BHIM UPI, your credit card and debit card or wallet to recharge your mobile phone,\npay your utility bills and also make instant payments at offline and online stores.\nPhonePe is an indian company (https://en.wikipedia.org/wiki/PhonePe)\nBHIM = Bharat Interface for Money : https://en.wikipedia.org/wiki/BHIM\nUPI = Unified Payement Interface : https://en.wikipedia.org/wiki/Unified_Payments_Interface\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14170,7 +15392,7 @@ }, "com.playphone.gamestore": { "list": "Misc", - "description": "Playphone Gamestore (https://www.playphone.com/)\n\"Helps\" you discover the \"best\" Android games and connects you to a global gaming community. Sounds Amazing !\n", + "description": "Playphone Gamestore (https://www.playphone.com/)\n\"Helps\" you discover the\"best\" Android games and connects you to a global gaming community. Sounds Amazing !\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14178,7 +15400,7 @@ }, "com.playphone.gamestore.loot": { "list": "Misc", - "description": "Loot \nPremium service from playphone ? \n", + "description": "Loot\nPremium service from playphone ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14186,7 +15408,7 @@ }, "com.pure.indosat.care": { "list": "Misc", - "description": "myIM3 (https://play.google.com/store/apps/details?id=com.pure.indosat.care)\nApp provided by Indosat Ooredoo, an Internet provider from Indonesia. \nEnables Indosat users to manage prepaid and postpaid numbers and check their credit and payments, purchase data packs, calls, SMS...\n", + "description": "myIM3 (https://play.google.com/store/apps/details?id=com.pure.indosat.care)\nApp provided by Indosat Ooredoo, an Internet provider from Indonesia.\nEnables Indosat users to manage prepaid and postpaid numbers and check their credit and payments, purchase data packs, calls, SMS...\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14210,7 +15432,7 @@ }, "com.pinsight.dw": { "list": "Misc", - "description": "App Stack \nForce-installed app by Sprint. Pinsight is an advertising company (https://pinsightmedia.com/)\nNote : Sprint sold Pinsight to InMobi in 2018.\nhttps://www.fiercewireless.com/wireless/sprint-sells-mobile-ad-biz-pinsight-media-to-inmobi\n", + "description": "App Stack\nForce-installed app by Sprint. Pinsight is an advertising company (https://pinsightmedia.com/)\nNote : Sprint sold Pinsight to InMobi in 2018.\nhttps://www.fiercewireless.com/wireless/sprint-sells-mobile-ad-biz-pinsight-media-to-inmobi\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14226,7 +15448,7 @@ }, "com.remotefairy4": { "list": "Misc", - "description": "AnyMote Universal Remote + Wifi Smart Home Control (https://play.google.com/store/apps/details?id=com.remotefairy4)\nIR Remote control app \nLots of trackers and permissions : https://reports.exodus-privacy.eu.org/en/reports/com.remotefairy4/latest/\n", + "description": "AnyMote Universal Remote + Wifi Smart Home Control (https://play.google.com/store/apps/details?id=com.remotefairy4)\nIR Remote control app\nLots of trackers and permissions : https://reports.exodus-privacy.eu.org/en/reports/com.remotefairy4/latest/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14282,7 +15504,7 @@ }, "com.sharecare.askmd": { "list": "Misc", - "description": "AskMD (discontinued) provided by Sharecare\nSymptom checker app. Lets you see what might be causing your symptoms and helps you find a nearby physician \nWorth Reading : https://en.wikipedia.org/wiki/Sharecare#Criticisms\n", + "description": "AskMD (discontinued) provided by Sharecare\nSymptom checker app. Lets you see what might be causing your symptoms and helps you find a nearby physician\nWorth Reading : https://en.wikipedia.org/wiki/Sharecare#Criticisms\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14346,7 +15568,7 @@ }, "com.telenav.app.android.scout_us": { "list": "Misc", - "description": "Scout GPS Navigation & Meet Up (https://play.google.com/store/apps/details?id=com.telenav.app.android.scout_us)\nBad GPS with bad chat features on top of that. \nhttps://www.scoutgps.com/\n", + "description": "Scout GPS Navigation & Meet Up (https://play.google.com/store/apps/details?id=com.telenav.app.android.scout_us)\nBad GPS with bad chat features on top of that.\nhttps://www.scoutgps.com/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14464,6 +15686,14 @@ "labels": [], "removal": "Recommended" }, + "com.yandex.searchapp": { + "list": "Oem", + "description": "Yandex' Search App\nRussian search app, similar to the Google search bar that appears on the phone's home screen.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "ru.yandex.disk": { "list": "Oem", "description": "Yandex' file cloud storage\nMay be installed with Samsung firmware update to comply with http://publication.pravo.gov.ru/Document/View/0001202011230051 if you're Russian. Can be installed manually from Google Play.", @@ -14488,6 +15718,46 @@ "labels": [], "removal": "Recommended" }, + "ru.vk.store": { + "list": "Oem", + "description": "Rustore, russian app market, preinstalled by russian law from 2019", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "ru.ivi.client": { + "list": "Oem", + "description": "Ivi, russian video service, preinstalled by russian law from 2019", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "ru.litres.android": { + "list": "Oem", + "description": "Litres, russian bookstore service, preinstalled by russian law from 2019", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "ru.ozon.app.android": { + "list": "Oem", + "description": "Ozon, russian marketplace, preinstalled by russian law from 2019", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "ru.dublgis.dgismobile": { + "list": "Oem", + "description": "2GIS, russian mapping service, preinstalled by rus law from 2019", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.yellowpages.android.ypmobile": { "list": "Misc", "description": "Yellow Pages (https://play.google.com/store/apps/details?id=com.yellowpages.android.ypmobile)\n", @@ -14498,7 +15768,7 @@ }, "com.zhiliaoapp.musically": { "list": "Misc", - "description": "TikTok App \nWorth reading : https://en.wikipedia.org/wiki/TikTok#Privacy,_cyberbullying_and_addiction_concerns\n", + "description": "TikTok App\nWorth reading : https://en.wikipedia.org/wiki/TikTok#Privacy,_cyberbullying_and_addiction_concerns\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14506,7 +15776,7 @@ }, "de.axelspringer.yana.zeropage": { "list": "Misc", - "description": "Upday news for Samsung (https://play.google.com/store/apps/details?id=de.axelspringer.yana)\n", + "description": "Upday news for Samsung (https://play.google.com/store/apps/details?id=de.axelspringer.yana)\n Eats your phone's resources and runs in the background. You can use other news providers that have more privacy than this, or your own browser with ad-blocking on.", "dependencies": [], "neededBy": [], "labels": [], @@ -14554,7 +15824,7 @@ }, "jp.co.omronsoft.openwnn": { "list": "Misc", - "description": "Japanese keyboard/IME (don't know why it's pre-installed on US/european devices)\nNote : IME = input method editor \n", + "description": "Japanese keyboard/IME (don't know why it's pre-installed on US/european devices)\nNote : IME = input method editor\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14570,7 +15840,7 @@ }, "msgplus.jibe.sca.vpl": { "list": "Misc", - "description": "Messaging Plus. Messings using the RCS protocol (https://en.wikipedia.org/wiki/Rich_Communication_Services)\n \tRelated to Google Jibe (https://jibe.google.com/)\n", + "description": "Messaging Plus. Messings using the RCS protocol (https://en.wikipedia.org/wiki/Rich_Communication_Services)\n\tRelated to Google Jibe (https://jibe.google.com/)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14714,7 +15984,7 @@ }, "com.dsi.ant.sample.acquirechannels": { "list": "Misc", - "description": "I don't know why there is \"sample\" in the name. Is this package really useful to find ANT channels ? \n", + "description": "I don't know why there is\"sample\" in the name. Is this package really useful to find ANT channels ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14738,7 +16008,7 @@ }, "co.sitic.pp": { "list": "Misc", - "description": "Designed to remotely lock the phone (by sending a simple SMS) in case you don't pay your bill \nhttps://www.reddit.com/r/Android/comments/fde3l6/3rd_party_telemetry_found_in_nokia_smartphones/fjh4zbx/?context=3\nThis app was pre-installed on phone not served by that carrier (América Móvil) from South America. \nNormally you should not have this app anymore because it was removed by Nokia during an Android 10 update.\n", + "description": "Designed to remotely lock the phone (by sending a simple SMS) in case you don't pay your bill\nhttps://www.reddit.com/r/Android/comments/fde3l6/3rd_party_telemetry_found_in_nokia_smartphones/fjh4zbx/?context=3\nThis app was pre-installed on phone not served by that carrier (América Móvil) from South America.\nNormally you should not have this app anymore because it was removed by Nokia during an Android 10 update.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14746,7 +16016,7 @@ }, "com.gd.mobicore.pa": { "list": "Misc", - "description": "Mobicore is now Trustonic\nTrustonic is a small OS running on the CPU providing a TEE, an isolated environment that runs in parallel with the operating system, guaranteeing code and data loaded inside to be protected.\nSounds great, but it's closed source and \"normal\" devs can't use it for their apps.\nSee \"com.trustonic.tuiservice\"", + "description": "Mobicore is now Trustonic\nTrustonic is a small OS running on the CPU providing a TEE, an isolated environment that runs in parallel with the operating system, guaranteeing code and data loaded inside to be protected.\nSounds great, but it's closed source and\"normal\" devs can't use it for their apps.\nSee\"com.trustonic.tuiservice\".", "dependencies": [], "neededBy": [], "labels": [], @@ -14762,7 +16032,7 @@ }, "com.trustonic.tuiservice": { "list": "Misc", - "description": "tuiService (Trusted User Interface) is a security layer by Trustonic.\nAllows a \"Trusted App\" to interact directly with the user, completely isolated from the device OS.\nIt's closed source and normal devs can't use it for their apps.\nhttps://stackoverflow.com/questions/16909576/how-to-make-use-of-arm-trust-zone-in-android-application\nMainly used by OEM apps like Samsung Pay and for DRM.\nGoogle implemented their own TUI in Android Pie: https://android-developers.googleblog.com/search/label/Trusted%20User%20Interface\nhttps://www.trustonic.com/news/blog/benefits-trusted-user-interface/\nhttps://en.wikipedia.org/wiki/Trusted_execution_environment\nDisabling will break \"Trusted Apps\".\nhttps://en.wikipedia.org/wiki/ARM_architecture#Security_extensions\nhttps://googleprojectzero.blogspot.com/2017/07/trust-issues-exploiting-trustzone-tees.html\nhttps://www.synacktiv.com/posts/exploit/kinibi-tee-trusted-application-exploitation.html\nhttps://blog.quarkslab.com/introduction-to-trusted-execution-environment-arms-trustzone.html\nGood ressources:\nhttps://medium.com/@nimronagy/arm-trustzone-on-android-975bfe7497d2\nhttps://www.gsd.inesc-id.pt/~nsantos/papers/pinto_acsur19.pdf\nhttps://blog.quarkslab.com/introduction-to-trusted-execution-environment-arms-trustzone.html\nhttps://medium.com/taszksec/unbox-your-phone-part-i-331bbf44c30c", + "description": "tuiService (Trusted User Interface) is a security layer by Trustonic.\nAllows a\"Trusted App\" to interact directly with the user, completely isolated from the device OS.\nIt's closed source and normal devs can't use it for their apps.\nhttps://stackoverflow.com/questions/16909576/how-to-make-use-of-arm-trust-zone-in-android-application\nMainly used by OEM apps like Samsung Pay and for DRM.\nGoogle implemented their own TUI in Android Pie: https://android-developers.googleblog.com/search/label/Trusted%20User%20Interface\nhttps://www.trustonic.com/news/blog/benefits-trusted-user-interface/\nhttps://en.wikipedia.org/wiki/Trusted_execution_environment\nDisabling will break\"Trusted Apps\".\nhttps://en.wikipedia.org/wiki/ARM_architecture#Security_extensions\nhttps://googleprojectzero.blogspot.com/2017/07/trust-issues-exploiting-trustzone-tees.html\nhttps://www.synacktiv.com/posts/exploit/kinibi-tee-trusted-application-exploitation.html\nhttps://blog.quarkslab.com/introduction-to-trusted-execution-environment-arms-trustzone.html\nGood ressources:\nhttps://medium.com/@nimronagy/arm-trustzone-on-android-975bfe7497d2\nhttps://www.gsd.inesc-id.pt/~nsantos/papers/pinto_acsur19.pdf\nhttps://blog.quarkslab.com/introduction-to-trusted-execution-environment-arms-trustzone.html\nhttps://medium.com/taszksec/unbox-your-phone-part-i-331bbf44c30c", "dependencies": [], "neededBy": [], "labels": [], @@ -14778,7 +16048,7 @@ }, "org.simalliance.openmobileapi.uicc2terminal": { "list": "Misc", - "description": "Open Mobile API (\"interface\") to access UICC secure elements \nUICC stands for Universal Integrated Circuit Card.\nIt is a the physical and logical platform for the USIM and may contain additional USIMs and other applications.\n(U)SIM is an application on the UICC.\nhttps://bluesecblog.wordpress.com/2016/11/18/uicc-sim-usim/\nGood read: https://arxiv.org/ftp/arxiv/papers/1601/1601.03027.pdf\nNote2: The term SIM is widely used in the industry and especially with consumers to mean both SIMs and UICCs.\nhttps://www.justaskgemalto.com/us/what-uicc-and-how-it-different-sim-card/\n", + "description": "Open Mobile API (\"interface\") to access UICC secure elements\nUICC stands for Universal Integrated Circuit Card.\nIt is a the physical and logical platform for the USIM and may contain additional USIMs and other applications.\n(U)SIM is an application on the UICC.\nhttps://bluesecblog.wordpress.com/2016/11/18/uicc-sim-usim/\nGood read: https://arxiv.org/ftp/arxiv/papers/1601/1601.03027.pdf\nNote2: The term SIM is widely used in the industry and especially with consumers to mean both SIMs and UICCs.\nhttps://www.justaskgemalto.com/us/what-uicc-and-how-it-different-sim-card/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14786,7 +16056,7 @@ }, "org.simalliance.openmobileapi.service": { "list": "Misc", - "description": "The SmartCard API is a reference implementation of the SIMalliance Open Mobile API specification that enables Android applications \nto communicate with Secure Elements, (SIM card, embedded Secure Elements, Mobile Security Card or others)\nhttps://github.com/seek-for-android/pool/wiki/SmartcardAPI\nSafe to remove if you think you don't need this\n", + "description": "The SmartCard API is a reference implementation of the SIMalliance Open Mobile API specification that enables Android applications\nto communicate with Secure Elements, (SIM card, embedded Secure Elements, Mobile Security Card or others)\nhttps://github.com/seek-for-android/pool/wiki/SmartcardAPI\nSafe to remove if you think you don't need this\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14794,7 +16064,7 @@ }, "com.mediatek": { "list": "Misc", - "description": "Mediatek is a Taiwanese chipset manufacturer.\nCan someone share the apk? This package name is really weird.\nIt is most likely a set of general APIs for accessing general mediatek functionalities.\nCause Bootloop.", + "description": "Core system services and drivers for MediaTek-powered devices.\nMediatek is a Taiwanese chipset manufacturer.\nCan someone share the apk? This package name is really weird.\nIt is most likely a set of general APIs for accessing general mediatek functionalities.\nCause Bootloop.", "dependencies": [], "neededBy": [], "labels": [], @@ -14810,15 +16080,15 @@ }, "com.mediatek.callrecorder": { "list": "Misc", - "description": "This is not the kind of feature expected from a Soc company.\nIf you remove this I guess you will not be able to record your calls from the stock dialer\nCan someone share the apk and verify this?\n", + "description": "Call recording app for MediaTek devices.\nThis is not the kind of feature expected from a Soc company.\nIf you remove this I guess you will not be able to record your calls from the stock dialer\nIf disabled, phone calls don't work. You can disable it, but then need to use the Google Phone app to place calls.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.mediatek.engineermode": { "list": "Misc", - "description": "Engineer mode you can access by dialing a secret code (*#*#3646633#*#* on some Xiaomi phones for instance)\nIt enables you to access the debug/logged data and some hidden firmware settings. \n", + "description": "Engineer mode you can access by dialing a secret code (*#*#3646633#*#* on some Xiaomi phones for instance)\nIt enables you to access the debug/logged data and some hidden firmware settings.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14834,7 +16104,7 @@ }, "com.mediatek.location.lppe.main": { "list": "Misc", - "description": "LPPE = LTE Positioning Protocol enhancements/extensions (LTE = \"4G\")\nPositioning and assistance protocol between E-SMLC (mobile location center) and UE (User Equipement = phone)\nhttps://www.gpsworld.com/wirelessexpert-advice-positioning-protocol-next-gen-cell-phones-11125/\nI don't know the app has the permission to read SMS\n", + "description": "LPPE = LTE Positioning Protocol enhancements/extensions (LTE =\"4G\")\nPositioning and assistance protocol between E-SMLC (mobile location center) and UE (User Equipement = phone)\nhttps://www.gpsworld.com/wirelessexpert-advice-positioning-protocol-next-gen-cell-phones-11125/\nI don't know the app has the permission to read SMS\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14850,7 +16120,7 @@ }, "com.mediatek.mdmconfig": { "list": "Misc", - "description": "Mobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure \nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nIt's a way to ensure employees stay productive and do not breach corporate policies\nYou should NEVER have a MDM tool on your personal phone. Never.\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\nThis package probably isn't a MDM tool on its own but you definitively don't need it on your phone.\nCan someone share the apk?\n", + "description": "Mobile Device Management (MDM) allows company’s IT department to reach inside your phone in the background, allowing them to ensure\nyour device is secure, know where it is, and remotely erase your data if the phone is stolen.\nIt's a way to ensure employees stay productive and do not breach corporate policies\nYou should NEVER have a MDM tool on your personal phone. Never.\nhttps://blog.cdemi.io/never-accept-an-mdm-policy-on-your-personal-phone/\nThis package probably isn't a MDM tool on its own but you definitively don't need it on your phone.\nCan someone share the apk?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -14986,7 +16256,7 @@ }, "com.android.midrive": { "list": "Oem", - "description": "Mi Drive \nMisleading package name. It is indeed a closed-source Xiaomi application.\nAllow for cloud storage (on Mi Cloud) and syncing across multiple Android devices.\n", + "description": "Mi Drive\nMisleading package name. It is indeed a closed-source Xiaomi application.\nAllow for cloud storage (on Mi Cloud) and syncing across multiple Android devices.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15002,7 +16272,7 @@ }, "com.baidu.duersdk.opensdk": { "list": "Oem", - "description": "Duer stuff from Baidu \nDuer is a virtual AI assistant.\n", + "description": "Duer stuff from Baidu\nDuer is a virtual AI assistant.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15010,7 +16280,7 @@ }, "com.baidu.input_mi": { "list": "Oem", - "description": "Baidu IME (Baidu keyboard)\nYOU SHOULD NEVER USE A CLOSED-SOURCE KEYBOARD ! \nhttps://www.techrepublic.com/blog/asian-technology/japanese-government-warns-baidu-ime-is-spying-on-users/\nArchive : https://web.archive.org/save/https://www.techrepublic.com/blog/asian-technology/japanese-government-warns-baidu-ime-is-spying-on-users/\nNOTE: Make sure you have installed another keyboard before removing this package.\n", + "description": "Baidu IME (Baidu keyboard)\nYOU SHOULD NEVER USE A CLOSED-SOURCE KEYBOARD !\nhttps://www.techrepublic.com/blog/asian-technology/japanese-government-warns-baidu-ime-is-spying-on-users/\nArchive : https://web.archive.org/save/https://www.techrepublic.com/blog/asian-technology/japanese-government-warns-baidu-ime-is-spying-on-users/\nNOTE: Make sure you have installed another keyboard before removing this package.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15042,7 +16312,7 @@ }, "com.duokan.phone.remotecontroller.peel.plugin": { "list": "Oem", - "description": "Peel Mi Remote (https://play.google.com/store/apps/details?id=com.duokan.phone.remotecontroller.peel.plugin)\nPeel Mi Remote is a TV guide extension for Xiaomi Mi Remote by \"Peel Smart Remote\".\n", + "description": "Peel Mi Remote (https://play.google.com/store/apps/details?id=com.duokan.phone.remotecontroller.peel.plugin)\nPeel Mi Remote is a TV guide extension for Xiaomi Mi Remote by\"Peel Smart Remote\".\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15074,7 +16344,7 @@ }, "com.huaqin.diaglogger": { "list": "Oem", - "description": "Secret logging menu only accessible by dialing using a \"secret code\" (*#*#CODE#*#*)\nYou can use any of these code : \"995995\", \"996996\", \"9434\", \"334334\", \"5959\", \"477477\"\nUsed to log Bluetooth traffic and send them to com.miui.bugreport\nWrite logs to \"/sdcard/diag_logs/\" | \"/sdcard/wlan_logs/\" | \"/sdcard/MIUI/debug_log/common/\"\n#\nFYI Huaqin is a Chinese mobile phone research and development company.\n", + "description": "Secret logging menu only accessible by dialing using a\"secret code\" (*#*#CODE#*#*)\nYou can use any of these code :\"995995\",\"996996\",\"9434\",\"334334\",\"5959\",\"477477\"\nUsed to log Bluetooth traffic and send them to com.miui.bugreport\nWrite logs to\"/sdcard/diag_logs/\" |\"/sdcard/wlan_logs/\" |\"/sdcard/MIUI/debug_log/common/\"\n#\nFYI Huaqin is a Chinese mobile phone research and development company.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15082,7 +16352,7 @@ }, "com.huaqin.factory": { "list": "Oem", - "description": "Hidden test app (dial *#*#64663#*#*)\nUsed by technician in factory to test the hardware. Not intented to be run by end-users. \nHas a huge amount of permissions.\nA vulnerability was found in 2019 (CVE-2019-15340) allowing any app co-located on the device to \nprogrammatically disable and enable Wi-Fi, Bluetooth, and GPS silently (and without the corresponding access permission)\nhttps://nvd.nist.gov/vuln/detail/CVE-2019-15340\n", + "description": "Hidden test app (dial *#*#64663#*#*)\nUsed by technician in factory to test the hardware. Not intented to be run by end-users.\nHas a huge amount of permissions.\nA vulnerability was found in 2019 (CVE-2019-15340) allowing any app co-located on the device to\nprogrammatically disable and enable Wi-Fi, Bluetooth, and GPS silently (and without the corresponding access permission)\nhttps://nvd.nist.gov/vuln/detail/CVE-2019-15340\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15098,7 +16368,7 @@ }, "com.milink.service": { "list": "Oem", - "description": "UniPlay Service\nMIUI screen casting service. \nIf removed, you'll have to use Android's native casting services which can be accessed through a 3rd party app.\n", + "description": "UniPlay Service\nMIUI screen casting service.\nIf removed, you'll have to use Android's native casting services which can be accessed through a 3rd party app.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15130,7 +16400,7 @@ }, "com.miui.accessibility": { "list": "Oem", - "description": "Mi Ditto\nAccesibility feature. Dictation (TTS) and speech output, \nmaking mobile devices more convenient for people who have difficulties using conventionally designed smartphones. \n", + "description": "Mi Ditto\nAccesibility feature. Dictation (TTS) and speech output,\nmaking mobile devices more convenient for people who have difficulties using conventionally designed smartphones.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15194,7 +16464,7 @@ }, "com.miui.greenguard": { "list": "Oem", - "description": "Security Guard Service\nThe app includes three different antivirus brands built in that the user can choose from to keep their phone protected: Avast, AVL, and Tencent. \nUpon selecting the app, the user selects one of these providers as the default Anti-Virus engine to scan the device.\nIt the app that scans an app before installing it\nNOTE : A vulnerability was found in 2019 : https://research.checkpoint.com/2019/vulnerability-in-xiaomi-pre-installed-security-app/\n", + "description": "Security Guard Service\nThe app includes three different antivirus brands built in that the user can choose from to keep their phone protected: Avast, AVL, and Tencent.\nUpon selecting the app, the user selects one of these providers as the default Anti-Virus engine to scan the device.\nIt the app that scans an app before installing it\nNOTE : A vulnerability was found in 2019 : https://research.checkpoint.com/2019/vulnerability-in-xiaomi-pre-installed-security-app/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15202,7 +16472,7 @@ }, "com.miui.hybrid": { "list": "Oem", - "description": "Quick Apps\nIt's basically an app which shows you ads and tracks you...\nFunny thing, Xiaomi's Quick Apps was reportedly being blocked by Google Play Protect.\nhttps://www.androidpolice.com/2019/11/19/xiaomi-quick-apps-flagged-blocked-google-play-protect/\n#\nReverse engineering of the app : \nhttps://medium.com/@gags.gk/reverse-engineering-quick-apps-from-xiaomi-a1c9131ae0b7\nSpoiler : you really should delete this package.\n", + "description": "Quick Apps\nIt's basically an app which shows you ads and tracks you...\nFunny thing, Xiaomi's Quick Apps was reportedly being blocked by Google Play Protect.\nhttps://www.androidpolice.com/2019/11/19/xiaomi-quick-apps-flagged-blocked-google-play-protect/\n#\nReverse engineering of the app :\nhttps://medium.com/@gags.gk/reverse-engineering-quick-apps-from-xiaomi-a1c9131ae0b7\nSpoiler : you really should delete this package.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15226,7 +16496,7 @@ }, "com.miui.miwallpaper": { "list": "Oem", - "description": "Mi Wallpaper \nRemoving this might make it impossible to set a lock or home wallpaper, resulting in a black solid wallpaper.\nNote: it may also result in longer boot times (~15s) because the system try to call miwallpaper during boot", + "description": "Mi Wallpaper app, causes a lot of UI damage when removed, but not bootloop.\nRemoving this makes it impossible to set a lock or home screen wallpaper, resulting in a black solid wallpaper everywhere.\nNote: it may also result in longer boot times (~+10s) because the system tries to call Mi Wallpaper during boot.\nOn HyperOS 2.0, The fingerprint outline disappears on lock screen after removing this. The fingerprint recognicion itself works properly.\nEverything in the status bar is becoming colored black on the lock screen after removing this, and you can only see the battery color. Elsewhere the status bar is colored properly.\nOn HyperOS 2.0, you will have to remove this package and reboot 3-5 times. It constantly restores itself after each reboot until around 3rd-5th attempt. It vanishes fully only around 3-5 attempts.\nOn HyperOS 2.0, the default color for system icons is also being reset to brown after removing this package. Similar behavior to as described here might also be observed on other devices.", "dependencies": [], "neededBy": [], "labels": [], @@ -15238,7 +16508,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.miwallpaper.overlay.customize": { "list": "Oem", @@ -15246,7 +16516,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.qr": { "list": "Oem", @@ -15298,7 +16568,7 @@ }, "com.miui.analytics": { "list": "Oem", - "description": "Xiaomi Analytics\nThis app is shady. According to a guy who tried to reverse engineer the app, Xiaomi Analytics can replace any (signed?) package \nthey want silently on your device within 24 hours. Maybe that no longer the case now but... you don't want analytics anyway.\nSource : http://blog.thijsbroenink.com/2016/09/xiaomis-analytics-app-reverse-engineered/\n", + "description": "Xiaomi Analytics\nThis app is shady. According to a guy who tried to reverse engineer the app, Xiaomi Analytics can replace any (signed?) package\nthey want silently on your device within 24 hours. Maybe that no longer the case now but... you don't want analytics anyway.\nSource : http://blog.thijsbroenink.com/2016/09/xiaomis-analytics-app-reverse-engineered/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15314,7 +16584,7 @@ }, "com.miui.antispam": { "list": "Oem", - "description": "MIUI Antispam \nspam phone numbers filter (blacklist).\nSuspicious analytics inside and has access to internet. Cloud backup possible.\nAt quick glance it is not a private antispam app.\nCan someone check what data are collected/transfered?\n", + "description": "MIUI Antispam\nspam phone numbers filter (blacklist).\nSuspicious analytics inside and has access to internet. Cloud backup possible.\nAt quick glance it is not a private antispam app.\nCan someone check what data are collected/transfered?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15346,7 +16616,7 @@ }, "com.miui.cleaner": { "list": "Oem", - "description": "Mi Cleaner\nShady Xiaomi cleaner app developed by Cheetah mobile which has previously been caught in ad fraud and user data theft with this app in 2018 (previously called com.miui.cleanmaster and banned from the PlayStore). This \"new\" app is still full of trackers\nhttps://www.gadgets360.com/apps/news/banned-security-app-clean-master-by-cheetah-mobile-collected-user-private-data-report-2189633\n\nPithus analysis: https://beta.pithus.org/report/f7f7ee425a8dc928db75105bd8f52e9b02f11dec3b398aac9fef1d42809d8ec1", + "description": "Mi Cleaner\nShady Xiaomi cleaner app developed by Cheetah mobile which has previously been caught in ad fraud and user data theft with this app in 2018 (previously called com.miui.cleanmaster and banned from the PlayStore). This\"new\" app is still full of trackers\nhttps://www.gadgets360.com/apps/news/banned-security-app-clean-master-by-cheetah-mobile-collected-user-private-data-report-2189633\n\nPithus analysis: https://beta.pithus.org/report/f7f7ee425a8dc928db75105bd8f52e9b02f11dec3b398aac9fef1d42809d8ec1", "dependencies": [], "neededBy": [], "labels": [], @@ -15362,7 +16632,7 @@ }, "com.miui.cloudservice.sysbase": { "list": "Oem", - "description": "Another Mi Cloud dependency \n", + "description": "Another Mi Cloud dependency\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15566,7 +16836,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.vsimcore": { "list": "Oem", @@ -15614,7 +16884,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.wallpaper.overlay.customize": { "list": "Oem", @@ -15622,7 +16892,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.yellowpage": { "list": "Oem", @@ -15642,7 +16912,7 @@ }, "com.mi.android.globalpersonalassistant": { "list": "Oem", - "description": "MI Vault aka the \"assistant\" you open swiping left from MI Home\n", + "description": "MI Vault aka the\"assistant\" you open swiping left from MI Home\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15650,7 +16920,7 @@ }, "com.mi.android.globalminusscreen": { "list": "Oem", - "description": "Default App Vault package\nSends notifications and can't be uninstalled through the Apps tab. Can be downloaded back from Play Store if needed.", + "description": "Default App Vault package\nSends notifications and can't be uninstalled through the Apps tab. Can be downloaded back from Play Store if needed.\nThe screen on the left on the first page of the launcher; mostly useless, especially when you use a third party launcher. Displays tonns of ads and clutter and constantly works in background.", "dependencies": [], "neededBy": [], "labels": [], @@ -15722,7 +16992,7 @@ }, "com.mi.liveassistant": { "list": "Oem", - "description": "Mi Live Assistant\nI don't really know what it is. Maybe an old name for \"com.mi.android.globalpersonalassistant\"\n", + "description": "Mi Live Assistant\nI don't really know what it is. Maybe an old name for\"com.mi.android.globalpersonalassistant\"\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15734,11 +17004,11 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.mi.webkit.core": { "list": "Oem", - "description": "MI WebView\nXiaomi alternative to Google WebView\nREMINDER : It is a system component for the Android operating system that allows Android apps to display content \nfrom the web directly inside an application. It's based on Chrome.\nWARNING: Make to have another Webview before uninstalling it or some apps may not work properly\n\n.An open-source privacy oriented Webview is Bromite (https://www.bromite.org/system_web_view)\n", + "description": "MI WebView\nXiaomi alternative to Google WebView\nREMINDER : It is a system component for the Android operating system that allows Android apps to display content\nfrom the web directly inside an application. It's based on Chrome.\nWARNING: Make to have another Webview before uninstalling it or some apps may not work properly\n\n.An open-source privacy oriented Webview is Bromite (https://www.bromite.org/system_web_view)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15746,7 +17016,7 @@ }, "com.qiyi.video": { "list": "Oem", - "description": "IQIYI (https://play.google.com/store/apps/details?id=com.qiyi.video)\nOnline video platform from Baidu (https://en.wikipedia.org/wiki/IQiyi).\nI didn't know this is currently one of the largest online video sites in the world, \nwith nearly 6 billion hours spent on its service each month, and over 500 million monthly active users.", + "description": "IQIYI (https://play.google.com/store/apps/details?id=com.qiyi.video)\nOnline video platform from Baidu (https://en.wikipedia.org/wiki/IQiyi).\nI didn't know this is currently one of the largest online video sites in the world,\nwith nearly 6 billion hours spent on its service each month, and over 500 million monthly active users.", "dependencies": [], "neededBy": [], "labels": [], @@ -15778,7 +17048,7 @@ }, "com.xiaomi.channel": { "list": "Oem", - "description": "Mi Talk \nMi instant messaging app that lets you do practically the same thing as Whatsapp. \nNOTE: You should use Signal or Wire instead Whatsapp/Mi Talk for more privacy.\n", + "description": "Mi Talk\nMi instant messaging app that lets you do practically the same thing as Whatsapp.\nNOTE: You should use Signal or Wire instead Whatsapp/Mi Talk for more privacy.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15802,7 +17072,7 @@ }, "com.xiaomi.lens": { "list": "Oem", - "description": "Related to camera app ?\nSafe to remove (according to a lot of users)\nI'd like to have more info about it. Can a Xiaomi user help ? \n", + "description": "Related to camera app ?\nSafe to remove (according to a lot of users)\nI'd like to have more info about it. Can a Xiaomi user help ?\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15850,7 +17120,7 @@ }, "com.xiaomi.pass": { "list": "Oem", - "description": "Mi Pass is an App allows Xiaomi NFC phones to replace cards and keys in real life usage. \nSupport NFC payment, bus card, key card, door and car lock features all together.\n", + "description": "Mi Pass is an App allows Xiaomi NFC phones to replace cards and keys in real life usage.\nSupport NFC payment, bus card, key card, door and car lock features all together.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -15898,7 +17168,7 @@ }, "com.xiaomi.micloud.sdk": { "list": "Oem", - "description": "Mi Cloud sdk \nsdk = Software development kit\nSeems to be a dependency for \"com.miui.gallery\" (MIUI auto reboots android after remove this package)", + "description": "Mi Cloud sdk\nsdk = Software development kit\nSeems to be a dependency for\"com.miui.gallery\" (MIUI auto reboots android after remove this package)", "dependencies": [], "neededBy": [], "labels": [], @@ -15906,7 +17176,7 @@ }, "com.xiaomi.mirecycle": { "list": "Oem", - "description": "Mi Recycle \nXiaomi has extended its partnership with Cashify to launch the 'Mi Recycle' feature through its MIUI Security app. \nIt will let Xiaomi phone users check the health of their smartphone and get their resale value directly from Cashify, \nthe online re-commerce company based out of New Delhi.\nSource : https://gadgets.ndtv.com/mobiles/news/xiaomi-mi-recycle-cashify-miui-security-app-2018024\n", + "description": "Mi Recycle\nXiaomi has extended its partnership with Cashify to launch the 'Mi Recycle' feature through its MIUI Security app.\nIt will let Xiaomi phone users check the health of their smartphone and get their resale value directly from Cashify,\nthe online re-commerce company based out of New Delhi.\nSource : https://gadgets.ndtv.com/mobiles/news/xiaomi-mi-recycle-cashify-miui-security-app-2018024\n", "dependencies": [], "neededBy": [], "labels": [], @@ -16018,7 +17288,7 @@ }, "com.miui.wmsvc": { "list": "Oem", - "description": "WMService\nRuns at boot and has access to internet + GPS\nI quickly looked at the decompiled code and saw some unsanitized SQL inputs, which is BAD! (vulnerable to SQL injection)\nTries to get your android unique Google advertising ID from Google Play Services.\nFeeds and launches the spying/analytics app \"com.miui.hybrid\".\nDoesn't seem to do anything important, only tracking.\nWARNING: It does not seem to affect any functionality or cause bootloop.", + "description": "WMService\nRuns at boot and has access to internet + GPS\nI quickly looked at the decompiled code and saw some unsanitized SQL inputs, which is BAD! (vulnerable to SQL injection)\nTries to get your android unique Google advertising ID from Google Play Services.\nFeeds and launches the spying/analytics app\"com.miui.hybrid\".\nDoesn't seem to do anything important, only tracking.\nWARNING: It does not seem to affect any functionality or cause bootloop.", "dependencies": [], "neededBy": [], "labels": [], @@ -16066,11 +17336,11 @@ }, "com.android.cameraextensions": { "list": "Oem", - "description": "CameraExtensionsProxy.\nCamera-related third-party apps can call Android camera extensions such as Portrait, Night Mode, and HDR, which doesn't seem to work significantly on MIUI.", + "description": "CameraExtensionsProxy.\nCamera-related third-party apps can call Android camera extensions such as Portrait, Night Mode, and HDR, which doesn't seem to work significantly on MIUI.\nhttps://developer.android.com/media/camera/camera-extensions", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.fileexplorer": { "list": "Oem", @@ -16082,7 +17352,7 @@ }, "com.android.globalFileexplorer": { "list": "Oem", - "description": "Misleading package name. It's the Xiaomi Files Manager on older phones\n", + "description": "Xiaomi File Explorer\/Manager.", "dependencies": [], "neededBy": [], "labels": [], @@ -16090,11 +17360,11 @@ }, "com.android.incallui": { "list": "Oem", - "description": "Xiaomi (and OnePlus) Phone dialer (here we go again! Another confusing package name)\n\nClosed-source app built on top of the AOSP package.\nThe name is doubly misleading because this package is the whole dialer. It does not only provide the 'in call' screen.", + "description": "Xiaomi Phone 11\nXiaomi's phone (dialer, incallui, etc.) app. Fetches APN lists on some phones. Package name is highly misleading.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.android.thememanager": { "list": "Oem", @@ -16110,7 +17380,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.thememanager.module": { "list": "Oem", @@ -16146,7 +17416,7 @@ }, "com.miui.aod": { "list": "Oem", - "description": "Always-on display and Lock screen editor\nSafe to remove if you don't use \"Always-on display\" and \"Lock screen editor\" features in settings.\nRequired for the fingerprint scanner if you want without double-tapping or pressing the power button.", + "description": "Always-on display and Lock screen editor\nSafe to remove if you don't use\"Always-on display\" and\"Lock screen editor\" features in settings.\nRequired for the fingerprint scanner if you want without double-tapping or pressing the power button.", "dependencies": [], "neededBy": [], "labels": [], @@ -16212,7 +17482,7 @@ }, "com.mi.globalminusscreen": { "list": "Oem", - "description": "Xiaomi App Vault\nhttps://play.google.com/store/apps/details?id=com.mi.android.globalminusscreen&gl=US", + "description": "Xiaomi App Vault\nhttps://play.google.com/store/apps/details?id=com.mi.android.globalminusscreen&gl=US\nThe screen on the left on the first page of the launcher; mostly useless, especially when you use a third party launcher. Displays tonns of ads and clutter and constantly works in background.", "dependencies": [], "neededBy": [], "labels": [], @@ -16244,7 +17514,7 @@ }, "com.miui.misound": { "list": "Oem", - "description": "Earphones (it's the name of the app)\nProvides the sounds section in Settings and is needed for the equalizing\nSome people removed this package but I personaly don't think it's worth it. This package isn't really an issue\n(no dangerous permissions and does not run in the background all the time)\nYou can still remove it. You'll be just fine if you really don't need it.\n", + "description": "Earphones (it's the name of the app)\nProvides the sounds section in Settings and is needed for the equalizing and the per app mixer feature\nSome people removed this package but I personaly don't think it's worth it. This package isn't really an issue\n(no dangerous permissions and does not run in the background all the time)\nYou can still remove it. You'll be just fine if you really don't need it.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -16268,7 +17538,7 @@ }, "com.miui.zman": { "list": "Oem", - "description": "Mi Secure sharing\nProvides an option in the settings of the Xiaomi Gallery to automatically remove location and metadata from images \nyou want to share. This do not remove metadata of the picture in the gallery but only the shared copy.\nThere's also a \"Secure sharing\" watermark that shows up when you share photos on WeChat without metadata.\nThe question is does this really remove all EXIF tags? Can someone test?\nThis is a useful app anyway but do not forget that all your photos/vidoes taken with the Xiaomi camera are still geo-tagged \n(+ all others exif tags) by default. \nWhat you can do is at least revoke the GPS permission to the camera.\nFOSS alternative to this app : \nhttps://f-droid.org/fr/packages/com.jarsilio.android.scrambledeggsif/\nhttps://f-droid.org/fr/packages/de.kaffeemitkoffein.imagepipe/\n", + "description": "Mi Secure sharing\nProvides an option in the settings of the Xiaomi Gallery to automatically remove location and metadata from images\nyou want to share. This do not remove metadata of the picture in the gallery but only the shared copy.\nThere's also a\"Secure sharing\" watermark that shows up when you share photos on WeChat without metadata.\nThe question is does this really remove all EXIF tags? Can someone test?\nThis is a useful app anyway but do not forget that all your photos/vidoes taken with the Xiaomi camera are still geo-tagged\n(+ all others exif tags) by default.\nWhat you can do is at least revoke the GPS permission to the camera.\nFOSS alternative to this app :\nhttps://f-droid.org/fr/packages/com.jarsilio.android.scrambledeggsif/\nhttps://f-droid.org/fr/packages/de.kaffeemitkoffein.imagepipe/\n", "dependencies": [], "neededBy": [], "labels": [], @@ -16284,7 +17554,7 @@ }, "com.xiaomi.bluetooth": { "list": "Oem", - "description": "MIUI Bluetooth Extension. Doesn't seem to affect bluetooth functionality. Tested on Poco M4 Pro 5G HyperOS 1.0.1.0. Note: If you deleted (com.xiaomi.xmsf) this package will likely send \"Bluetooth extension stopped working\" errors, uninstalling it removes them.", + "description": "MIUI Bluetooth Extension. Doesn't seem to affect bluetooth functionality. Tested on Poco M4 Pro 5G HyperOS 1.0.1.0. Note: If you deleted (com.xiaomi.xmsf) this package will likely send\"Bluetooth extension stopped working\" errors, uninstalling it removes them.", "dependencies": [], "neededBy": [], "labels": [], @@ -16300,7 +17570,7 @@ }, "com.xiaomi.bsp.gps.nps": { "list": "Oem", - "description": "GPS location\nI think bsp = board system package (https://en.wikipedia.org/wiki/Board_support_package)\nNot sure about nps (It might be Non-Permanent GPS station)\nIt's a small package which seems to display a notification when an app is using GPS.\nMore precisely, there is a receiver (GnssEventReceiver) which listen to com.xiaomi.bsp.gps.nps.GetEvent \nThis event most likely happen when an app use the GPS and refers to the state of the communication with the GNSS:\nFIX, LOSE, RECOVER, START, STOP\nIt's safe to remove if you really want to.\n", + "description": "GPS location\nI think bsp = board system package (https://en.wikipedia.org/wiki/Board_support_package)\nNot sure about nps (It might be Non-Permanent GPS station)\nIt's a small package which seems to display a notification when an app is using GPS.\nMore precisely, there is a receiver (GnssEventReceiver) which listen to com.xiaomi.bsp.gps.nps.GetEvent\nThis event most likely happen when an app use the GPS and refers to the state of the communication with the GNSS:\nFIX, LOSE, RECOVER, START, STOP\nIt's safe to remove if you really want to.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -16316,15 +17586,15 @@ }, "com.miui.global.packageinstaller": { "list": "Oem", - "description": "The security check / virus scan that runs after package installation.\nDisabling/Uninstalling does not cause a bootloop and package installation still works fine.", + "description": "MIUI Package Installer. Provides sideload apps virus checker when installing APKs. Removal causes bootloop on Xiaomi.EU custom ROMs. Use the built-in com.android.packageinstaller instead.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.miui.guardprovider": { "list": "Oem", - "description": "Guard Provider security app\nThe app includes 3 different antivirus brands built in that the user can choose (Avast, AVL and Tencent). \nThis app notably performs a virus scan of any apps you want to install. \nA serious vulnerability was found in 2019\nWorth reading : https://research.checkpoint.com/2019/vulnerability-in-xiaomi-pre-installed-security-app/\nYou may want to remove this app from a privacy stance.\nhttps://beta.pithus.org/report/797a7e405bc8e767deebbbcab3e06a19b05156de44292c918b582dff3078d7b8\nIMPORTANT NOTE: Removing this package will very likely break any app installation/update.\nBefore removing, disable security things in MIUI security app.\nOn HyperOS this module is responsible for showing the 'Install via USB' prompt when installing apps via ADB (enabled through developer options, requires Mi account the first time).", + "description": "Guard Provider security app\nThe app includes 3 different antivirus brands built in that the user can choose (Avast, AVL and Tencent).\nThis app notably performs a virus scan of any apps you want to install.\nA serious vulnerability was found in 2019\nWorth reading : https://research.checkpoint.com/2019/vulnerability-in-xiaomi-pre-installed-security-app/\nYou may want to remove this app from a privacy stance.\nhttps://beta.pithus.org/report/797a7e405bc8e767deebbbcab3e06a19b05156de44292c918b582dff3078d7b8\nIMPORTANT NOTE: Removing this package will very likely break any app installation/update.\nBefore removing, disable security things in MIUI security app.\nOn HyperOS this module is responsible for showing the 'Install via USB' prompt when installing apps via ADB (enabled through developer options, requires Mi account the first time).\n On MIUI 12, it broke app installation from APKs, and made app installation from Google Play be 2-5 minutes long. Apps were uninstallable properly though.", "dependencies": [], "neededBy": [], "labels": [], @@ -16338,6 +17608,14 @@ "labels": [], "removal": "Unsafe" }, + "com.simalliance.openmobileapi.eseterminal": { + "list": "Oem", + "description": "The com.simalliance.openmobileapi.eseterminal package is part of the Open Mobile API framework, which provides services for accessing and managing Secure Elements (SEs) on the device, such as SIM cards or embedded secure elements. This package specifically handles communication with the ESE (Embedded Secure Element) terminal. Removing this package might affect the device's ability to interact with certain secure services or applications that rely on the SE framework. While it is not crucial for basic device functionality, it may impact specific features related to secure transactions or services.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.silead.fingerprint": { "list": "Oem", "description": "Fingerprint silead manager\nHidden app for testing Fingerprint things. Not needed for normal users.", @@ -16392,7 +17670,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.miwallpaper.telcel.overlay": { "list": "Oem", @@ -16400,7 +17678,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.asus.alwayson": { "list": "Oem", @@ -16416,7 +17694,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.asus.appupdater": { "list": "Oem", @@ -17160,7 +18438,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.asus.cellbroadcastservice.overlay": { "list": "Oem", @@ -17168,7 +18446,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "asusims.overlay.common": { "list": "Oem", @@ -17184,7 +18462,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "asusims.overlay.documentsui": { "list": "Oem", @@ -17192,7 +18470,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.asus.teleserv.overlay.odm": { "list": "Oem", @@ -17792,7 +19070,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.zui.safecenter.overlay.mostbeautiful": { "list": "Oem", @@ -17800,7 +19078,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.zui.safecenter.overlay.phantom": { "list": "Oem", @@ -17808,7 +19086,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.zui.safecenter.overlay.redstorm": { "description": "Overlay to theme icon Security app.", @@ -17994,6 +19272,14 @@ "neededBy": [], "labels": [] }, + "com.lge.concierge": { + "description": "LG Smart Notice\nProvides a widget which has a clock, weather, lists notifications and much more, it's LG's version of Google Now.", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.lge.sui.widget": { "description": "Removing this package causes the clock app to crash when trying to set an alarm for a specific date instead of a day of the week.", "removal": "Advanced", @@ -18284,6 +19570,14 @@ "neededBy": [], "labels": [] }, + "com.lge.lockscreen.livewallpaper.kaleidoscope": { + "description": "The Kaleidoscope Live Wallpaper used in the lockscreen.\nSafe to remove but make sure it's not set as the Wallpaper.\n", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.lge.lockscreensettings": { "description": "LockScreenSettings\nLock Screen Settings.", "removal": "Unsafe", @@ -19140,8 +20434,8 @@ "labels": [] }, "com.motorola.securevault": { - "description": "Secure Folder\nUnnecessary tools to keep device secure.\nhttps://play.google.com/store/apps/details?id=com.motorola.securevault", - "removal": "Recommended", + "description": "Secure Folder\nNormally unnecessary tools to keep device secure, however, removal may cause background issues - it should be safe to disable instead.\nhttps://play.google.com/store/apps/details?id=com.motorola.securevault", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -19412,7 +20706,7 @@ "labels": [] }, "com.motorola.setup.auto_generated_rro_vendor__": { - "description": "I found it's \"no sim anim\". It's another component of Motorola first-boot setup.", + "description": "I found it's\"no sim anim\". It's another component of Motorola first-boot setup.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -21252,8 +22546,8 @@ "labels": [] }, "com.coloros.assistantscreen": { - "description": "HeyTap Shelf. ColorOS 'At a Glance'.\nShelf provides a variety of widgets that let you access important information or services from apps with ease. Swipe down on the Home screen to enter Shelf.\nhttps://play.google.com/store/apps/details?id=com.coloros.assistantscreen", - "removal": "Recommended", + "description": "Shelf. ColorOS/OnePlus 'At a Glance'.\nShelf provides a variety of widgets that let you access important information or services from apps with ease. Removing will also be unable to access third-party widgets (these are different from the 'normal' widgets in any launcher) in ColorOS 16/OxygenOS 16\nSwipe down on the Home screen to enter Shelf.\nhttps://play.google.com/store/apps/details?id=com.coloros.assistantscreen", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -21317,7 +22611,7 @@ "labels": [] }, "com.coloros.accessibilityassistant": { - "description": "Another thing for smart assistant", + "description": "AI VoiceScribe.\nIt's used to convert speech to text in real-time for accessibility purposes. Can be safely deleted if you don't use AI services.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -21328,7 +22622,13 @@ "description": "Screen Recognition (Breeno Touch).\nThis app is used to recognize screen contents and provide quick access to relevant services (like Text Extraction, AI Summarizer). com.coloros.ocrscanner, com.coloros.ocrservice, com.oplus.ocs, com.oplus.aiunit, com.coloros.ocs.opencapabilityservice are also needed for this to work.", "removal": "Recommended", "list": "Oem", - "dependencies": ["com.coloros.ocrscanner", "com.coloros.ocrservice", "com.oplus.ocs", "com.oplus.aiunit", "com.coloros.ocs.opencapabilityservice"], + "dependencies": [ + "com.coloros.ocrscanner", + "com.coloros.ocrservice", + "com.oplus.ocs", + "com.oplus.aiunit", + "com.coloros.ocs.opencapabilityservice" + ], "neededBy": [], "labels": [] }, @@ -21397,6 +22697,14 @@ "neededBy": [], "labels": [] }, + "com.oplus.callrecorder": { + "description": "Allows you to toggle call recording in the stock Dialer app.\nSafe to remove?\n", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.oplus.customize.coreapp": { "description": "Useless frameworks", "removal": "Recommended", @@ -21728,8 +23036,8 @@ "labels": [] }, "com.coloros.weather.service": { - "description": "Name indicates it's for the weather, but removing this causes the screen to flash and the phone will eventually become unresponsive.\nhttps://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/issues/585", - "removal": "Unsafe", + "description": "Name indicates it's for the weather, but removing this causes the screen to flash and the phone will eventually become unresponsive.\nhttps://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/issues/585. Disabling instead does not seem to cause this problem, see \nhttps://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/issues/585#issuecomment-3796739025", + "removal": "Expert", "list": "Oem", "dependencies": [], "neededBy": [], @@ -21784,7 +23092,7 @@ "labels": [] }, "com.oplus.postmanservice": { - "description": "Calibration, scan QR code test", + "description": "Diagnostics\nFor calibration of hardware", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -21856,8 +23164,8 @@ "labels": [] }, "com.coloros.wifibackuprestore": { - "description": "WifiBackupRestore\nBackup Wi-Fi to the cloud", - "removal": "Recommended", + "description": "WifiBackupRestore\nBackup Wi-Fi to the cloud\nNOTE: Removing or disabling this app would lose the ability for Backup and Restore functionality to backup locally stored wifi access points or credentials locally on your device", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -22080,7 +23388,7 @@ "labels": [] }, "com.coloros.recents": { - "description": "Recent apps. Provides navigation to alternate between multiple apps. Removal will result in no \"Recent App\" list and re-enablement will cause a soft reload.", + "description": "Recent apps. Provides navigation to alternate between multiple apps. Removal will result in no\"Recent App\" list and re-enablement will cause a soft reload.", "removal": "Expert", "list": "Oem", "dependencies": [], @@ -22152,8 +23460,8 @@ "labels": [] }, "com.svox.pico": { - "description": "Pico TTS\nHidden sample voice data. Useless.", - "removal": "Recommended", + "description": "Pico TTS\nOpen source TTS engine shipped on old Android devices and some custom ROMs\nUninstalling this without installing a TTS engine will break TTS, it also doesn't access the internet so there's not much to gain", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -22168,8 +23476,8 @@ "labels": [] }, "com.oplus.audio.effectcenter": { - "description": "AudioEffectCenter\nDolby support for Chinese apps and some Google. It's so bloated.", - "removal": "Recommended", + "description": "Sound effects and EQ settings, Dolby support for Chinese apps and some Google. Remove if you aren't planning to use sound effects or EQ.", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -22191,6 +23499,14 @@ "dependencies": [], "neededBy": [] }, + "com.android.providers.media.module": { + "description": "Media picker module\nNot recommended to remove this as it can break apps that use the photo picker.\n", + "removal": "Expert", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.google.ambient.streaming": { "description": "Access and use your Android phone's apps from your Chromebook", "removal": "Recommended", @@ -22200,8 +23516,8 @@ "labels": [] }, "com.android.angle": { - "description": "Have only empty main activity. it's not a joke.", - "removal": "Recommended", + "description": "Almost Native Graphics Layer Engine, open source experimental project that improves rendering performance.\nConverts the calls from the graphics drivers to a more consistent APIs like Vulkan.\nSee the source code here: https://github.com/google/angle", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -22280,7 +23596,7 @@ "removal": "Recommended" }, "com.google.android.euicc": { - "description": "Electronic Sim management\nNeeded for eSIM", + "description": "eUICC (embedded UICC) refers to the architectural standards for eSIM, a device used to securely store one or more SIM card profiles, which are the unique identifiers and cryptographic keys used by cellular network service providers to uniquely identify and securely connect to mobile network devices.\nBreaks SIM Manager.", "removal": "Expert", "list": "Oem", "dependencies": [], @@ -22348,7 +23664,9 @@ "removal": "Advanced", "list": "Oem", "dependencies": [], - "neededBy": ["com.felicanetworks.mfm.main"], + "neededBy": [ + "com.felicanetworks.mfm.main" + ], "labels": [] }, "com.shannon.rcsservice": { @@ -22978,7 +24296,15 @@ "com.focaltech.fingerprint": { "description": "Another fingerprint sensor test tool but Chinese.", "removal": "Recommended", - "list": "Oem", + "list": "Misc", + "dependencies": [], + "neededBy": [], + "labels": [] + }, + "com.focaltech.fpsensormmitest": { + "description": "Related to `com.focaltech.fingerprint`. Seems like a debugging activity triggered by dialing an MMI code", + "removal": "Recommended", + "list": "Misc", "dependencies": [], "neededBy": [], "labels": [] @@ -23039,6 +24365,14 @@ "neededBy": [], "labels": [] }, + "com.tcl.android.launcher.hotapp": { + "description": "Hot Apps. Unrelated to Recent Apps (launcher and/or app-switcher).\nSeemingly empty, but requests network+internet access. The manifest references `com.bumptech.glide.integration.okhttp3.OkHttpGlideModule`", + "removal": "Recommended", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.tcl.android.launchertheme.res": { "description": "Launcher theme resources\nIt's needed for themes, probably not sure if it's an important app.", "removal": "Expert", @@ -23104,8 +24438,32 @@ "labels": [] }, "com.tct.iris": { - "description": "NXTVISION\nIt's for reading mode and Display Enhancement.", - "removal": "Recommended", + "description": "TCL NXTVISION\"Display Enhancements\". GPU-accelerated post-processing (\"shaders\") for images, videos, and games. Only good for pretty pictures, and (maybe) accessibility (clearer view). This is the back-end, see `com.tct.nxtvision_ui*` for the settings.", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, + "com.tct.iris.overlay_product": { + "description": "Related to TCL NXTVISION", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, + "com.tct.nxtvision_ui": { + "description": "TCL NXTVISION (code-name `iris`) Settings front-end", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, + "com.tct.nxtvision_ui.overlay_product": { + "description": "TCL NXTVISION (code-name `iris`) Settings front-end overlay", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -23167,8 +24525,16 @@ "neededBy": [], "labels": [] }, + "com.tct.onetouchbooster.a_overlay": { + "list": "Oem", + "description": "Likely related to Smart Manager", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.tct.onetouchbooster": { - "description": "Power saving.", + "description": "Smart Manager. For\"Optimization\" of: battery (energy), memory (RAM), and storage. Removing it might break power-save mode", "removal": "Expert", "list": "Oem", "dependencies": [], @@ -23262,14 +24628,6 @@ "neededBy": [], "labels": [] }, - "com.tct.gpdr": { - "description": "GPDR\nUser Experience Improvement Program.", - "removal": "Recommended", - "list": "Oem", - "dependencies": [], - "neededBy": [], - "labels": [] - }, "com.tct.smart.ircontrol": { "description": "IR Remote\nI think it's useless.", "removal": "Recommended", @@ -23554,8 +24912,8 @@ "labels": [] }, "com.transsion.applock": { - "description": "AppLock\nProvides the only way to hide files and lock apps when using Transsion launchers (which the Transsion devices require for certain functionality like multiapps not working with other launchers). These are the only apps that hide files and lock apps with them.", - "removal": "Advanced", + "description": "AppLock\nProvides the only way to hide files and lock apps when using Transsion launchers (which the Transsion devices require for certain functionality like multiapps not working with other launchers). These are the only apps that hide files and lock apps with them.\nRemoval breaks recents.", + "removal": "Expert", "list": "Oem", "dependencies": [], "neededBy": [], @@ -24022,8 +25380,8 @@ "labels": [] }, "com.transsion.zahooc": { - "description": "Za-Hooc\nit's for secure card and Theft Alert.", - "removal": "Recommended", + "description": "This package is actually the 'Privacy' section in the Settings app. All the features inside, such as Blank Data, App Lock, App Twin, etc., belong to this package.", + "removal": "Expert", "list": "Oem", "dependencies": [], "neededBy": [], @@ -25221,7 +26579,7 @@ "labels": [] }, "com.spreadtrum.sgps": { - "description": "Useless GPS Test.", + "description": "A Chinese spyware GPS system app, consider removing if your phone doesn't have a GPS sensor.\nThis app is developed by a company called Zhantang, the same organization that made a dropper malware (com.redstone.ota.ui):\nhttps://www.malwarebytes.com/blog/news/2021/04/pre-installed-auto-installer-threat-found-on-android-mobile-devices-in-germany\nhttps://thehackernews.com/2021/04/pre-installed-malware-dropper-found-on.html", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25413,7 +26771,7 @@ "labels": [] }, "com.miui.phone.carriers.customized.overlay": { - "description": "Something about WiFi calling \"vowifi\", \"volte\", \"notification on keyguard\"\nIt's unused.", + "description": "Something about WiFi calling\"vowifi\",\"volte\",\"notification on keyguard\"\nIt's unused.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25421,7 +26779,7 @@ "labels": [] }, "com.miui.miinput": { - "description": "Removing this package breaks \"Gesture shortcuts\" under \"Additional settings\".", + "description": "Removing this package breaks\"Gesture shortcuts\" under\"Additional settings\".", "removal": "Advanced", "list": "Oem", "dependencies": [], @@ -25429,7 +26787,7 @@ "labels": [] }, "com.lbe.security.miui.customizedregion.overlay": { - "description": "Something about WiFi calling \"vowifi\", \"volte\", \"notification on keyguard\"\nIt's unused.", + "description": "Something about WiFi calling\"vowifi\",\"volte\",\"notification on keyguard\"\nIt's unused.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25437,7 +26795,7 @@ "labels": [] }, "com.android.inputsettings.overlay.miui": { - "description": "Keyboard demo found. It's something to miinput unused Chinese!", + "description": "Keyboard demo found. It's something to miinput unused Chinese! On HyperOS 3, it's a dependency of Camera Ring", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25549,7 +26907,7 @@ "labels": [] }, "com.samsung.android.mapsagent": { - "description": "Samsung App Recommendations\na lot of spying code. I guess it's an app from first-boot setup.", + "description": "Provides the\"recommendation\" service. It auto-installs recommended apps from Samsung & partners after a factory reset or first boot. Also recommends you apps when you access an app folder.\n Similar to com.samsung.android.app.omcagent", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25605,7 +26963,7 @@ "labels": [] }, "com.samsung.gpuwatchapp": { - "description": "GPUWatch\nIn this app, I only found GPU dumping mode, dev mode, game debugging. Useless.", + "description": "This app has GPU Dumping mode, developer mode, game debugging. This package also provides the feature to watch and log system performance. Useful if you need/want to monitor system performance. Otherwise it offers no benefit. Safe to remove in any case.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -25636,6 +26994,14 @@ "neededBy": [], "labels": [] }, + "com.samsung.slsi.telephony.silentlogging": { + "description": "Hidden network logging. Safe to remove", + "removal": "Recommended", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.sec.android.app.volumemonitorprovider": { "description": "VolumeMonitorProvider\nused in Digital Wellbeing to average the dB heard through earphones and display it.", "removal": "Recommended", @@ -25677,8 +27043,8 @@ "labels": [] }, "com.samsung.android.accessibility.talkback": { - "description": "TalkBack\nSamsung talkback in accessibility.", - "removal": "Recommended", + "description": "Samsung TalkBack in accessibility.\nhttps://galaxystore.samsung.com/prepost/000005296612?appId=com.samsung.android.accessibility.talkback", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -25732,6 +27098,14 @@ "neededBy": [], "labels": [] }, + "com.monotype.android.font.roboto": { + "description": "Roboto Font", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.samsung.android.uds": { "description": "Ultra data saving\nHave boring notifications and theres no point of keeping this app.\nhttps://play.google.com/store/apps/details?id=com.samsung.android.uds", "removal": "Recommended", @@ -25749,8 +27123,8 @@ "labels": [] }, "com.samsung.android.providers.factory": { - "description": "FactoryTestProvider\nIt's used for log or testing.", - "removal": "Recommended", + "description": "FactoryTestProvider\nDisabling breaks hwmoduletest.", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -25869,7 +27243,7 @@ "labels": [] }, "com.oplus.romupdate": { - "description": "Update Service\nIf you wanna remove it to keep ram, it's a bad idea. Better remove com.oplus.ota too if you don't plan to update system.", + "description": "Update Service\nResponsible for installing updates.", "removal": "Expert", "list": "Oem", "dependencies": [], @@ -26058,7 +27432,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.systemui.overlay.charging.anim.siphon_wireless": { "list": "Oem", @@ -26160,7 +27534,15 @@ "description": "Media Controller.\nResponsible for the Dynamic Island feature for music applications and showing the 'Now playing' notification on lockscreen.", "removal": "Expert", "list": "Oem", - "dependencies": ["com.oneplus.account", "com.oplus.ocs", "com.oplus.onet", "com.oplus.metis", "com.oplus.statistics.rom", "com.coloros.assistantscreen", "com.coloros.scenemode"], + "dependencies": [ + "com.oneplus.account", + "com.oplus.ocs", + "com.oplus.onet", + "com.oplus.metis", + "com.oplus.statistics.rom", + "com.coloros.assistantscreen", + "com.coloros.scenemode" + ], "neededBy": [], "labels": [] }, @@ -26197,8 +27579,8 @@ "labels": [] }, "com.oplus.linker": { - "description": "OPSynergy\nUsed for the Synergy app to link your phone to your PC (It doesn't work well beyond controlling your phone from your PC).", - "removal": "Recommended", + "description": "OPSynergy\nUsed for the Synergy app to link your phone to your PC (it doesn't work well beyond controlling your phone from your PC). This app is a dependency of screencast. Disabling will cause the screencast app to break.", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -26268,6 +27650,14 @@ "neededBy": [], "labels": [] }, + "com.oplus.sau": { + "description": "System Upgrade Service\nAllows you to update your phone.\nRuns at boot and could cause bootloop when removed.\n", + "removal": "Expert", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.oplus.sauhelper": { "description": "SAUHelper\nIt's very much a placeholder app with no real functionality, but it can't be uninstalled or deactivated, and it can be SUSPENDED.", "removal": "Recommended", @@ -26535,6 +27925,14 @@ "neededBy": [], "labels": [] }, + "com.oppo.usercenter": { + "description": "Just bloatware for account details and marketing of OPPO. Cannot log into OPPO/HeyTap account after disabling. Safe to disable if OPPO account is not used.", + "removal": "Advanced", + "list": "Oem", + "dependencies": [], + "neededBy": [], + "labels": [] + }, "com.coloros.findmyphone": { "description": "Find phone\nFind phone, logout from oppo account before", "removal": "Recommended", @@ -26600,7 +27998,7 @@ "labels": [] }, "com.coloros.karaoke": { - "description": "Karaoke\nKaraoke (Do not delete if you need Karaoke)", + "description": "In-ear monitoring\nBasically ColorOS's high volume warning system. Can be removed fine if you don't want it.", "removal": "Recommended", "list": "Oem", "dependencies": [], @@ -26656,8 +28054,8 @@ "labels": [] }, "com.oplus.trafficmonitor": { - "description": "OnePlus Data usage\nOneplus traffic monitor (monthly data usage, etc). This app is so bloated.", - "removal": "Recommended", + "description": "OnePlus Data usage / OnePlus traffic monitor (monthly data usage, etc). If removed, the 'Data Usage' option under 'Mobile network' will not work. Also App Info screen's 'Data usage' option will disappear. Required to restrict an app from accessing the network via settings > app info.", + "removal": "Advanced", "list": "Oem", "dependencies": [], "neededBy": [], @@ -26801,7 +28199,7 @@ }, "miui.systemui.plugin": { "list": "Oem", - "description": "System UI Plug-in. When removed, Android will use the AOSP style volume bar and reboot screen (option to power off or reboot your phone). Will break the iOS-style quick settings. The volume bar breakage only applies to MIUI-users. For HyperOS-users, all the above will apply.", + "description": "System UI Plug-in. When using HyperOS, removing this package breaks the iOS-style quick settings and Android will use the AOSP-version of the volume bar & reboot screen (AKA the option to power off/reboot your device). If your device is using MIUI, only the volume bar will change.\nWARNING: On Redmi Note 11 (Android 13, MIUI 14), it broke the entire status bar making it unable to draw the notification panel including the quick action menu.", "dependencies": [], "neededBy": [], "labels": [], @@ -26817,7 +28215,7 @@ }, "com.xiaomi.powerchecker": { "list": "Oem", - "description": "Power Detector\nSecurity> Battery> Activity Control. \nDetects abnormal power usage by apps (not all. Some Xiaomi apps are whitelisted)\nNeeded for 'com.miui.powerkeeper' to work.\n", + "description": "Power Detector\nSecurity> Battery> Activity Control.\nDetects abnormal power usage by apps (not all. Some Xiaomi apps are whitelisted)\nNeeded for 'com.miui.powerkeeper' to work.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -26849,15 +28247,15 @@ }, "com.xiaomi.finddevice": { "list": "Oem", - "description": "Find My Device feature (in the Settings)\nEnables you to locate your lost phone and erase your data remotely. \nYour phone needs to be connected to internet (Wifi/mobile data) for this feature to work. REMOVING THIS MIGHT BOOTLOOP YOUR DEVICE! This may depend on your MIUI version and device, see\nhttps://github.com/0x192/universal-android-debloater/issues/641", + "description": "Find My Device feature (in the Settings)\nAllows you to locate a lost phone and wipe it remotely, provided it has an active Wi-Fi/mobile data connection.\nBefore uninstalling, !!! log out of your Mi Account !!! Removing this breaks factory reset from UI, the Security Status page in Settings, and prevents Mi Account sign-in.\nConfirmed not to bootloop on HyperOS 1.0 and HyperOS 2.0, but other MIUI versions/devices may still bootloop\nsee https://github.com/0x192/universal-android-debloater/issues/641\nSends and receives around 1,5MB-2MB of data per day to/from an unknown source on HyperOS 2.0, even with Data Saver on and on mobile data. The UI blocks you from denying any kind of mobile data access.\nConsider replacing it with Google's find device. It's much more optimized, has offline location tracking feature and is already preinstalled even on the devices with Xiaomi's Find Device.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.miui.securitycenter": { "list": "Oem", - "description": "MIUI Security app\nProvides \"protection and optimization tools\" \nApp lock, Data usage, Security scan, Cleaner, Battery saver, Blocklist and other features.\nThis package is mostly the front-end (UI).\nhttps://beta.pithus.org/report/f8c24ccfc526389ff9084505c60fba3d3463565f92e2015190e2974b370e7c4e\nNOTE: REMOVING THIS WILL MOST LIKELY BOOTLOOP YOUR DEVICE! Uninstalling this on the Redmi Pad or Miui 13 and above is not causing any bootloop, but you will lose some functionality like the battery status/usage page, as well as the app usage/removal page.", + "description": "MIUI Security app\nProvides\"protection and optimization tools\"\nApp lock, Data usage, Security scan, Cleaner, Battery saver, Blocklist and other features.\nThis package is mostly the front-end (UI).\nhttps://beta.pithus.org/report/f8c24ccfc526389ff9084505c60fba3d3463565f92e2015190e2974b370e7c4e\nNOTE: REMOVING THIS WILL MOST LIKELY BOOTLOOP YOUR DEVICE! Uninstalling this on the Redmi Pad or Miui 13 and above is not causing any bootloop, but you will lose some functionality like the battery status/usage page, as well as the app usage/removal page.", "dependencies": [], "neededBy": [], "labels": [], @@ -26865,7 +28263,7 @@ }, "com.miui.securitycore": { "list": "Oem", - "description": "Core features of the \"com.miui.securitycenter\"\nREMOVING THIS WILL MOST LIKELY BOOTLOOP YOUR DEVICE! This may depend on your MIUI version and device, see\nhttps://github.com/0x192/universal-android-debloater/issues/641\nOn Miui 13 and above it doesnt bootloop and looks performance like the same, also this app has annoying notifications when you running new app.", + "description": "Core features of the\"com.miui.securitycenter\"\nProvides Enterprise Mode, Dual App, Second Space, Fingerprint Add, Gesture Settings\nREMOVING THIS MAY BOOTLOOP YOUR DEVICE! Depends on your MIUI version and device, see\nhttps://github.com/0x192/universal-android-debloater/issues/641\nOn MIUI 13 and above it doesn't bootloop and performance appears similar, but this app shows annoying notifications when running new apps.", "dependencies": [], "neededBy": [], "labels": [], @@ -26961,7 +28359,7 @@ }, "com.android.chrome": { "list": "Google", - "description": "Google Chrome (https://play.google.com/store/apps/details?id=com.android.chrome)\nOccasionally runs in the background.\nNOTE: disabling or uninstalling Chrome may break functionality for creating and storing passkeys (https://fidoalliance.org/passkeys/) on your phone, so keep this enabled if you want to use that form of authentication. G Play Services can provide this functionality on some devices", + "description": "Google Chrome (https://play.google.com/store/apps/details?id=com.android.chrome)\nOccasionally runs in the background.\nNOTE: Disabling or uninstalling Chrome may break functionality for creating and storing passkeys (https://fidoalliance.org/passkeys/) on your phone, so keep this enabled if you want to use that form of authentication. G Play Services can provide this functionality on some devices.\nWhen Chrome is updated via the Play Store, the Trichrome Library is also updated automatically. If Chrome is disabled or removed, it may impact WebView functionality.\nThis is because Chrome, WebView, and the Trichrome Library work together as a bundle starting from Android 10 (API 29) and above.", "dependencies": [], "neededBy": [], "labels": [], @@ -27009,7 +28407,7 @@ }, "com.google.android.apps.ads.publisher": { "list": "Google", - "description": "Google Adsense app (https://play.google.com/store/apps/details?id=com.google.android.apps.ads.publisher) \n", + "description": "Google Adsense app (https://play.google.com/store/apps/details?id=com.google.android.apps.ads.publisher)\n", "dependencies": [], "neededBy": [], "labels": [], @@ -27417,11 +28815,11 @@ }, "com.google.android.apps.wallpaper": { "list": "Google", - "description": "Google Wallpapers (https://play.google.com/store/apps/details?id=com.google.android.apps.wallpaper)\n", + "description": "Google Wallpapers (https://play.google.com/store/apps/details?id=com.google.android.apps.wallpaper)\nRemoves the wallpaper section in the settings app when removed, but keeps current wallpapers.\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.apps.wellbeing": { "list": "Google", @@ -27521,7 +28919,7 @@ }, "com.google.android.gallery3d": { "list": "Aosp", - "description": "Built-in Gallery app.\nThe ID could be \"recycled\" by OEMs for their own gallery implementations.", + "description": "Built-in Gallery app.\nThe ID could be\"recycled\" by OEMs for their own gallery implementations.", "dependencies": [], "neededBy": [], "labels": [], @@ -27529,7 +28927,7 @@ }, "com.google.android.googlequicksearchbox": { "list": "Google", - "description": "Google Search box (https://play.google.com/store/apps/details?id=com.google.android.googlequicksearchbox)\nRuns in the background.\nPointless. If you need a shortcut to Google on your homescreen just use a web-browser shortcut. Does also remove the Google Sound Search widget, but you can get that functionality from an app like Shazam, that additionally doesn't run in the background constantly like this package does.\nThis app also powers the Google Discover page (the news 'widget' when you go to the left of the home screen) and the app symbol called 'Google'.\nWARNING: disabling this package also breaks the Ok Google Search functionality as well as Google Lens.", + "description": "Google Search box (https://play.google.com/store/apps/details?id=com.google.android.googlequicksearchbox)\nRuns in the background.\nPointless. If you need a shortcut to Google on your homescreen just use a web-browser shortcut. Does also remove the Google Sound Search widget, but you can get that functionality from an app like Shazam, that additionally doesn't run in the background constantly like this package does.\nThis app also powers the Google Discover page (the news 'widget' when you go to the left of the home screen) and the app symbol called 'Google'.\nWARNING: disabling this package also breaks the Ok Google Search functionality as well as Circle to Search functionality.", "dependencies": [], "neededBy": [], "labels": [], @@ -27553,19 +28951,19 @@ }, "com.google.android.markup": { "list": "Google", - "description": "Google Markup app made for modifying pictures, shipped by default on every Pie+ device.\n", + "description": "Google Markup app made for modifying pictures, shipped by default on every Pie+ device.\nRemoves the button to quickly edit screenshots once taken.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.marvin.talkback": { "list": "Google", - "description": "Android Accessibility Suite (https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback)\nHelps blind and vision-impaired users.\n", + "description": "Android Accessibility Suite (https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback)\nHelps blind and visually impaired users.\nWARNING: Causes com.motorola.dynamicvolume to not display individual apps and their respective volumes when volume button pressed. Seems to revert to an older (maybe testing) version of the dynamicvolume pkg?\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.music": { "list": "Google", @@ -27601,35 +28999,35 @@ }, "com.google.android.safetycenter.resources": { "list": "Aosp", - "description": "Google Safety Center.\nProbably affects malware detection in new app installs, Gmail, and Chrome. Alternatively, you can use a libre spam-blocking and DNS-blocking solution instead.\nAnyway it looks like a useless frameworks.\nhttps://safety.google", + "description": "Google Safety Center.\nGoogle Safe Browsing.\nWARNING: Crashes Security and Privacy settings if removed.\nhttps://www.android.com/safety/", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.projection.gearhead": { "list": "Google", - "description": "Android Auto (https://play.google.com/store/apps/details?id=com.google.android.projection.gearhead)", + "description": "Android Auto (https://play.google.com/store/apps/details?id=com.google.android.projection.gearhead)\nNo direct replacement appears to exist.\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.pixel.setupwizard": { "list": "Google", - "description": "It's the basic configuration setup guides you through the basics of setting up Google features on your device.\nThe second package is only present on Pixel phones.\n", + "description": "It's the basic configuration setup guides you through the basics of setting up Google features on your device.\nThe second package is only present on Pixel phones.\nBreaks the Google Play System update page found on\"Security & privacy\", for whatever reason...", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.soundpicker": { "list": "Google", - "description": "Google Sounds. Removable if you already have another media select service.\n", + "description": "Google Sounds. Provides notification, alarm, and ringtone sounds, will be set to default sounds (and cannot be changed) if removed, unless you already have another media select service.\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.street": { "list": "Google", @@ -27841,7 +29239,7 @@ }, "com.google.android.apps.nexuslauncher": { "list": "Google", - "description": "Pixel Launcher (https://play.google.com/store/apps/details?id=com.google.android.apps.nexuslauncher)\nUsed to be called Nexus Launcher(back when Google's phones were called Nexus, not Pixel).\nA launcher is basically your homescreen.\nDON'T REMOVE IF YOU HAVEN'T INSTALLED ANOTHER LAUNCHER! Nova Launcher is usually the go-to custom launcher.", + "description": "Pixel Launcher (https://play.google.com/store/apps/details?id=com.google.android.apps.nexuslauncher)\nUsed to be called Nexus Launcher(back when Google's phones were called Nexus, not Pixel).\nA launcher is basically your homescreen.\nDON'T REMOVE IF YOU HAVEN'T INSTALLED ANOTHER LAUNCHER!\nREMOVING CAUSES GESTURES/THREE BUTTON NAVIGATION TO DISAPPEAR ENTIRELY!\nhttps://vikrant.is-a.dev/Android-Launcher-Comparison-Table/ has a comprehensive comparison of many alternative launchers\n", "dependencies": [], "neededBy": [], "labels": [], @@ -27849,11 +29247,11 @@ }, "com.google.android.apps.turbo": { "list": "Google", - "description": "Device Health Services (discontinued)", + "description": "Device Health Services.\nBreaks battery settings.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.apps.tycho": { "list": "Google", @@ -27865,7 +29263,7 @@ }, "com.google.android.apps.work.oobconfig": { "list": "Google", - "description": "Device Setup\nSets up device to be managed by EMM (Enterprise Mobility Management), which \"allows organizations to securely enable employee use of mobile devices\".\nMight also be what does the actual management on your device, if you set it up as a work device.\nOnly seems to run on boot(not in the background after boot) if you haven't set up your device as a work device.\nI tried to disable it through UAD-ng, but nothing happens? Seems immune to disabling?\nhttps://bayton.org/2020/11/google-announce-big-changes-to-zero-touch/\nhttps://bayton.org/docs/enterprise-mobility/android/what-is-android-zero-touch-enrolment/\nContains 4 services: GcmJobService, GservicesChangedObserverService, AppMeasurementService and FirebaseInstanceIdService.\nGCM(Google Cloud Messaging) was the backend for Android's push messaging system 2012-2019, after which it was replaced by FCM(Firebase Cloud Messaging). I assume the GCM/Firebase connection is for Push notification functionality.\nThe MANAGE_CARRIER_OEM_UNLOCK_STATE permission hints at doing something with carrier locks?\nNeeds Google Play Services to function?", + "description": "Device Setup\nSets up device to be managed by EMM (Enterprise Mobility Management), which\"allows organizations to securely enable employee use of mobile devices\".\nMight also be what does the actual management on your device, if you set it up as a work device.\nOnly seems to run on boot(not in the background after boot) if you haven't set up your device as a work device.\nI tried to disable it through UAD-ng, but nothing happens? Seems immune to disabling?\nhttps://bayton.org/2020/11/google-announce-big-changes-to-zero-touch/\nhttps://bayton.org/docs/enterprise-mobility/android/what-is-android-zero-touch-enrolment/\nContains 4 services: GcmJobService, GservicesChangedObserverService, AppMeasurementService and FirebaseInstanceIdService.\nGCM(Google Cloud Messaging) was the backend for Android's push messaging system 2012-2019, after which it was replaced by FCM(Firebase Cloud Messaging). I assume the GCM/Firebase connection is for Push notification functionality.\nThe MANAGE_CARRIER_OEM_UNLOCK_STATE permission hints at doing something with carrier locks?\nNeeds Google Play Services to function?", "dependencies": [], "neededBy": [], "labels": [], @@ -27945,7 +29343,7 @@ }, "com.google.android.gms": { "list": "Google", - "description": "Google Play Services\ngms = Google Mobile Services\nIt is a layer that sits on top of the OS and provides a bunch of Google APIs, giving apps access to various Google Services.\nIf you remove it all the apps relying on Google Play Services whill either: \n- detect the lack of play services and refuse to run\n- detect the lack of play services but allow you to run (improperly) by dismissing an annoying popup\nRemoving Google Play Services can bootloop some devices, so be careful.\nDisabling this package will improve battery life a lot.\nIMPORTANT: You need to uncheck Find My Device from the \"Device admin apps\" settings panel to be able to disable this package.\nSearch \"admin\" in the settings search bar.", + "description": "Google Play Services\nGMS = Google Mobile Services.\nIt is a layer that sits on top of the OS and provides a lot of proprietary Google APIs, giving apps access to various Google Services, such as:\"fused\"-location (internet and GPS chip), QR Code scanner, 2FA, G-Drive storage, Firebase API, Cloud Messaging, etc...\nIf you remove it, all the apps relying on it will either:\n- detect the lack of Play-Services and refuse to run\n- detect the lack of Play-Services but allow you to run (improperly) by dismissing an annoying popup\nRemoving Google Play Services can boot-loop some devices, so be careful.\nDisabling this package will improve battery life significantly, as it always runs in the background.\nIMPORTANT: You need to uncheck\"Find My Device\" from the\"Device admin apps\" settings panel to be able to disable this package.\nSearch\"admin\" in the Settings-app search bar, or go to the Security category.", "dependencies": [], "neededBy": [], "labels": [], @@ -27957,7 +29355,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.gms.location.history": { "list": "Google", @@ -28009,7 +29407,7 @@ }, "com.google.android.partnersetup": { "list": "Google", - "description": "Google Partner Setup\nOccasionally runs in the background.\nBased on an unclear explanation online: \"Enables applications to interact with your Google account/apps, for example: adding a Google Calendar event from a To-Do app.\"\nProbably safe to disable; haven't noticed any consequences of disabling from weeks of use.", + "description": "Google Partner Setup\nOccasionally runs in the background.\nBased on an unclear explanation online:\"Enables applications to interact with your Google account/apps, for example: adding a Google Calendar event from a To-Do app.\"\nProbably safe to disable; haven't noticed any consequences of disabling from weeks of use.", "dependencies": [], "neededBy": [], "labels": [], @@ -28017,7 +29415,7 @@ }, "com.google.android.webview": { "list": "Google", - "description": "Android System WebView (https://play.google.com/store/apps/details?id=com.google.android.webview) enables Android apps to display web content within the app itself, based on Chrome.\nNo root? Don't uninstall.\nRoot? If you delete WebView, make sure to install a replacement.\nMany third-party apps, such as banks, VPNs, GitHub, Discord and Reddit use web-based content and will crash without it.", + "description": "Android System WebView (https://play.google.com/store/apps/details?id=com.google.android.webview) enables Android apps to display web content within the app itself, based on Chrome.\nIf you delete WebView, make sure to install a replacement.\nMany third-party apps, such as banks, VPNs, GitHub, Discord and Reddit use web-based content and will crash without it.\nIt can cause notifications problems", "dependencies": [], "neededBy": [], "labels": [], @@ -28065,11 +29463,11 @@ }, "com.google.audio.hearing.visualization.accessibility.scribe": { "list": "Google", - "description": "Live Transcribe & Sound Notifications (https://play.google.com/store/apps/details?id=com.google.audio.hearing.visualization.accessibility.scribe)\nProvides push notifications for critical sounds around you. This feature can be helpful for people with hearing loss.\nhttps://blog.google/products/android/new-sound-notifications-on-android/\nWorks offline\n", + "description": "Live Transcribe & Sound Notifications (https://play.google.com/store/apps/details?id=com.google.audio.hearing.visualization.accessibility.scribe)\nProvides push notifications for critical sounds around you. This feature can be helpful for people with hearing loss.\nhttps://blog.google/products/android/new-sound-notifications-on-android/\nWorks offline\nProvides text-to-speech for most apps, find a replacement before uninstalling\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.vending": { "list": "Google", @@ -28121,7 +29519,7 @@ }, "com.google.android.captiveportallogin": { "list": "Aosp", - "description": "it's the same as (com.android.captiveportallogin). Support for captive portal.\nA captive portal login is a web page where the users have to input their login information or accept the displayed terms of use. \nSome networks (typically public wifi network) use the captive portal login to block access until the user inputs \nsome necessary information\nNOTE : This package is a now a mandatory mainline module\nhttps://en.wikipedia.org/wiki/Captive_portal\nhttps://www.xda-developers.com/android-project-mainline-modules-explanation", + "description": "it's the same as (com.android.captiveportallogin). Support for captive portal.\nA captive portal login is a web page where the users have to input their login information or accept the displayed terms of use.\nSome networks (typically public wifi network) use the captive portal login to block access until the user inputs\nsome necessary information\nNOTE : This package is a now a mandatory mainline module\nhttps://en.wikipedia.org/wiki/Captive_portal\nhttps://www.xda-developers.com/android-project-mainline-modules-explanation", "dependencies": [], "neededBy": [], "labels": [], @@ -28199,7 +29597,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.overlay.modules.permissioncontroller.forframework": { "list": "Aosp", @@ -28212,14 +29610,16 @@ "com.google.android.overlay.permissioncontroller": { "list": "Aosp", "description": "Breaks Google Play System updates (GPSu), related to Project Mainline. Page on Settings will crash altogether, or ask Play Store to be updated.\nhttps://support.google.com/product-documentation/answer/14343500", - "dependencies": ["com.android.vending"], + "dependencies": [ + "com.android.vending" + ], "neededBy": [], "labels": [], "removal": "Advanced" }, "com.verizon.obdm": { "list": "Carrier", - "description": "It's a set of metrics-related modules. Google Play uses the version of the Telemetry module to determine\nif updates are available for metrics-related modules and which security patch version to display to the end user. \nThis module doesn’t contain active code and has no functionality on its own. \nRemoving modules-related packages may not be safe since Android 11\nhttps://gitlab.com/W1nst0n/universal-android-debloater/-/issues/27#note_410012436\n", + "description": "It's a set of metrics-related modules. Google Play uses the version of the Telemetry module to determine\nif updates are available for metrics-related modules and which security patch version to display to the end user.\nThis module doesn’t contain active code and has no functionality on its own.\nRemoving modules-related packages may not be safe since Android 11\nhttps://gitlab.com/W1nst0n/universal-android-debloater/-/issues/27#note_410012436\n", "dependencies": [], "neededBy": [], "labels": [], @@ -28275,7 +29675,7 @@ }, "com.mobolize.sprint.securewifi": { "list": "Carrier", - "description": "Secure Wifi (https://play.google.com/store/apps/details?id=com.mobolize.sprint.securewifi)\nSprint VPN app provided by Mobolize. You need to pay for using it.\nYou'd better use a reliable third-party VPN if you really need to use one.\nThis one runs in background all time and every time it sees a \"unsecured network\" it will popup to encourage you to pay for this VPN.\nBest ressources I know for choosing a VPN:\nhttps://www.privacytools.io/providers/vpn/", + "description": "Secure Wifi (https://play.google.com/store/apps/details?id=com.mobolize.sprint.securewifi)\nSprint VPN app provided by Mobolize. You need to pay for using it.\nYou'd better use a reliable third-party VPN if you really need to use one.\nThis one runs in background all time and every time it sees a\"unsecured network\" it will popup to encourage you to pay for this VPN.\nBest ressources I know for choosing a VPN:\nhttps://www.privacytools.io/providers/vpn/", "dependencies": [], "neededBy": [], "labels": [], @@ -28291,7 +29691,7 @@ }, "com.sprint.safefound": { "list": "Carrier", - "description": "Safe & Found (https://play.google.com/store/apps/details?id=com.sprint.safefound)\nMobile safety and security application that helps protect and locate your \"loved ones\". \nYou have the ability to track and manage smartphones, tablets and Tracker all in one app.\nhttps://www.sprint.com/en/support/solutions/services/safe-and-found.html\n", + "description": "Safe & Found (https://play.google.com/store/apps/details?id=com.sprint.safefound)\nMobile safety and security application that helps protect and locate your\"loved ones\".\nYou have the ability to track and manage smartphones, tablets and Tracker all in one app.\nhttps://www.sprint.com/en/support/solutions/services/safe-and-found.html\n", "dependencies": [], "neededBy": [], "labels": [], @@ -28755,7 +30155,7 @@ }, "com.evenwell.SettingsUtils": { "list": "Oem", - "description": "Settings utils\n(crappy) Audio rendering. \nSee https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/9#note_369056538\n", + "description": "Settings utils\n(crappy) Audio rendering.\nSee https://gitlab.com/W1nst0n/universal-android-debloater/-/issues/9#note_369056538\n", "dependencies": [], "neededBy": [], "labels": [], @@ -29013,7 +30413,7 @@ }, "com.samsung.hiddennetworksetting": { "list": "Oem", - "description": "Set of hidden network settings (inlcuding frequency band choice).\nHow to see these settings: https://forum.xda-developers.com/galaxy-note-8/help/q-hidden-network-settings-pie-t3914421/page4", + "description": "Set of hidden network settings (including frequency band choice).\nHow to see these settings: https://forum.xda-developers.com/galaxy-note-8/help/q-hidden-network-settings-pie-t3914421/page4", "dependencies": [], "neededBy": [], "labels": [], @@ -29173,7 +30573,7 @@ }, "com.huawei.mirror": { "list": "Oem", - "description": "Huawei Mirror app.\nMirror like \"Glass\"", + "description": "Huawei Mirror app.\nMirror like\"Glass\"", "dependencies": [], "neededBy": [], "labels": [], @@ -29255,7 +30655,7 @@ }, "com.motorola.comcastext": { "list": "Oem", - "description": "See above. Provides special (useless) features from Comcast? App title is \"Activation\". Safe to remove (tested only on non-Comcast phone).\n", + "description": "See above. Provides special (useless) features from Comcast? App title is\"Activation\". Safe to remove (tested only on non-Comcast phone).\n", "dependencies": [], "neededBy": [], "labels": [], @@ -29267,7 +30667,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.sonyericsson.warrantytime": { "list": "Oem", @@ -29333,6 +30733,22 @@ "labels": [], "removal": "Recommended" }, + "com.google.android.apps.bard": { + "list": "Google", + "description": "Google Gemini, safe to remove", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.apps.pixel.subzero": { + "list": "Google", + "description": "Daily Hub - useless a general-purpose news app", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.google.android.apps.inbox": { "list": "Google", "description": "Inbox by Gmail (Discontinued)", @@ -29373,7 +30789,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.youtube": { "list": "Google", @@ -29553,15 +30969,15 @@ }, "com.android.bips": { "list": "Aosp", - "description": "Default Print Service.\nGeneric printing service that should work with most printers.\nWill break printing functionality if disabled, but other replacement print services can be downloaded from the Play Store.", + "description": "Disabling this can cause Settings app to crash and general device slowness. Tested on Sony Xperia X, Fairphone 4 and Lenovo Yoga tab. Default Print Service.\nGeneric printing service that should work with most printers.\nWill break printing functionality if disabled, but other replacement print services can be downloaded from the Play Store.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.android.email.partnerprovider": { "list": "Aosp", - "description": "Lets Google partners (OEM in most of the case) to customize the default email settings.\nThe manufacturer often changes the default signature displayed at the end of each of your mail (e.g \"Sent from my Nokia phone\")", + "description": "Lets Google partners (OEM in most of the case) to customize the default email settings.\nThe manufacturer often changes the default signature displayed at the end of each of your mail (e.g\"Sent from my Nokia phone\")", "dependencies": [], "neededBy": [], "labels": [], @@ -29937,7 +31353,7 @@ }, "com.transsnet.store": { "list": "Oem", - "description": "Palm Store. App store with unsecure apps and probably malware. Has ads trackers and lot of intrusives permissions. Shows intrusive ads and popups.\nPithus analysis: https://beta.pithus.org/report/35d762b27c9e16703adf1731b74bef2c53a753b6a7475c425bced53b553758e5", + "description": "Palm Store. App store with unsecure apps and probably malware. Has ads trackers and lot of intrusives permissions. Shows intrusive ads and popups.\nRequired for one-time removal of \"Hot Apps\" folder in XOS Launcher (via long press and \"Properties\").\nPithus analysis: https://beta.pithus.org/report/35d762b27c9e16703adf1731b74bef2c53a753b6a7475c425bced53b553758e5", "dependencies": [], "neededBy": [], "labels": [], @@ -30057,7 +31473,7 @@ }, "com.transsion.smartpanel": { "list": "Oem", - "description": "Smart Panel (Settings -> Smart Assistant)\nProvides \"easy\" access to your most used apps + features like gamemode and videoAssistant. Collects data and talks with the outside\n\nPithus analysis: https://beta.pithus.org/report/40d4b527fc650a9029e596d14aff7d640a6289e7aa50f471b142391b55eefe4a", + "description": "Smart Panel (Settings -> Smart Assistant)\nProvides\"easy\" access to your most used apps + features like gamemode and videoAssistant. Collects data and talks with the outside\n\nPithus analysis: https://beta.pithus.org/report/40d4b527fc650a9029e596d14aff7d640a6289e7aa50f471b142391b55eefe4a", "dependencies": [], "neededBy": [], "labels": [], @@ -30065,7 +31481,7 @@ }, "com.transsion.hamal": { "list": "Oem", - "description": "It seems to be an \"aftersales user experience logging app\". Really shady app with questionable code (judgeWhiteUser() function. See https://github.com/0x192/universal-android-debloater/pull/112).\n\nStart at boot and can access phone number and IMEI (READ_PHONE_STATE).\n\nPithus analysis: https://beta.pithus.org/report/35fd79ebbe51808196605146a62aaef13bc654477d917078a3ae5d3f06ba8836", + "description": "It seems to be an\"aftersales user experience logging app\". Really shady app with questionable code (judgeWhiteUser() function. See https://github.com/0x192/universal-android-debloater/pull/112).\n\nStart at boot and can access phone number and IMEI (READ_PHONE_STATE).\n\nPithus analysis: https://beta.pithus.org/report/35fd79ebbe51808196605146a62aaef13bc654477d917078a3ae5d3f06ba8836", "dependencies": [], "neededBy": [], "labels": [], @@ -30081,11 +31497,11 @@ }, "com.transsion.batterylab": { "list": "Oem", - "description": "Supposed to improve battery life but logs especially lots of usage info and bind it to your unique android advertiser id...The app tries to send data to a server. The POST request URL and content is obfuscated and I don't have the time to dig deeper. According to a user, no battery impact after months of usage after uninstalling it.\n\nPithus analysis: https://beta.pithus.org/report/7ef2b186a74102828346f23b094ab2aaaad2c57806c7c18e7a23a494f3cc982c", + "description": "Will either kill your battery life or is the \"Battery & Power Saving\" section in the Settings app with many useful battery features, depending on device. \n\nPithus analysis: https://beta.pithus.org/report/7ef2b186a74102828346f23b094ab2aaaad2c57806c7c18e7a23a494f3cc982c", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.transsion.stasticalsales": { "list": "Oem", @@ -30113,13 +31529,13 @@ }, "com.oplus.cosa": { "list": "Oem", - "description": "APP Enhancement Services\nIf enabled, connects to OPPO servers (icosa-service-eu.allawnos.com) every time a new app is installed. Seems to be mostly focused on gaming performance optimisation according to the settings description:\n'[...] a service that optimises phone performance for specific apps and game scenarios. [...] frame rates, battery usage, touch sensitivity, network connection, vibration and gameplay assistance features.'\n\nCan be disabled via hidden setting (Settings -> Search 'App Enhancement Services' -> App Enhancement Services).\nNote: removing this package prevents the OnePlus Game Center to detect games.\nCannot be uninstalled but it can be disabled. Note: removing this package prevents the OnePlus Game Center to detect games.\nPithus analysis: https://beta.pithus.org/report/f55e935357865f4647e59c98afb5a3a46aba22a48844d80d2819d122781e3fde.", + "description": "APP Enhancement Services\nIf enabled, connects to OPPO servers (icosa-service-eu.allawnos.com) every time a new app is installed. Seems to be mostly focused on gaming performance optimisation according to the settings description:\n'[...] a service that optimises phone performance for specific apps and game scenarios. [...] frame rates, battery usage, touch sensitivity, network connection, vibration and gameplay assistance features.'\nCan be disabled via hidden setting (Settings -> Search 'App Enhancement Services' -> App Enhancement Services).\nNote: removing this package prevents the OnePlus Game Center to detect games.\nCannot be uninstalled but it can be disabled. Note: removing this package prevents the OnePlus Game Center to detect games.\nPithus analysis: https://beta.pithus.org/report/f55e935357865f4647e59c98afb5a3a46aba22a48844d80d2819d122781e3fde.\nAnother note: the process is necessary for the GameEventServiceService which ensures that apps recognized as games have a fixed refresh rate, not an adaptive refresh rate; without it, refresh rates may be reduced from 120hz to 60hz. When there is not much going on on screen, there can even be drops in the refresh rate to 30hz and 1hz. There is no option to turn off adaptive refresh rate, so one is reliant on this OS service to undo its own damage. Without this, there also seems to be no way to display 120fps cloud gaming at 120hz (tested with Moonlight/Artemsi), as the OS does not exempt the streaming app from the adaptive refresh rate rule.", "dependencies": [], "neededBy": [ "com.oneplus.gamespace" ], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.oplus.blur": { "list": "Oem", @@ -30181,7 +31597,9 @@ "com.huawei.fastapp": { "list": "Oem", "description": "Quick App Center\nComponent of AppGallery (Huawei's app store) providing Quick Apps support. Quick Apps are Javascript+CSS apps that don't need any installation. This technology has its uses but I'm personally not a huge fan on having to rely on a JS engine to run an application\nThis system app has a lot of permissions (including SEND_SMS, CAMERA, READ_EXTERNAL_STORAGE, RECORD_AUDIO... why?)\nMore information: https://www.xda-developers.com/huawei-quick-apps-alternative-google-instant-apps/\n OW2 Quick App whitepaper: https://quick-app-initiative.ow2.io/docs/Quick_App_White_Paper.pdf", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Advanced" @@ -30354,7 +31772,7 @@ }, "com.coloros.compass2": { "list": "Oem", - "description": "ColorOS default compass app\nKeep in mind that by using this app you give your location to the weather Oppo servers.\nPithus analysis: https://beta.pithus.org/report/9a965f5587fa6ee21c526612f3d72c50ef3cc53679b741260298387c44f5a3dc", + "description": "ColorOS and OxygenOS 16's default compass app\nKeep in mind that by using this app you give your location to the weather Oppo/OnePlus servers.\nPithus analysis: https://beta.pithus.org/report/9a965f5587fa6ee21c526612f3d72c50ef3cc53679b741260298387c44f5a3dc", "dependencies": [], "neededBy": [], "labels": [], @@ -30420,7 +31838,7 @@ }, "com.coloros.video": { "list": "Oem", - "description": "Video Player\nDefault Oppo video player with too much permissions (21) for a video player! \nNote: using inbuilt screen recorder you won't be able to open the recorded video from the notification view.\n\nPithus analysis: https://beta.pithus.org/report/4ceb96c23ad0e26ee8eceab293d251f8b1bddaf4a901741ee467e0bb867db6e9", + "description": "Video Player\nDefault Oppo and OnePlus video player with too much permissions (21) for a video player!\nNote: using inbuilt screen recorder you won't be able to open the recorded video from the notification view.\n\nPithus analysis: https://beta.pithus.org/report/4ceb96c23ad0e26ee8eceab293d251f8b1bddaf4a901741ee467e0bb867db6e9", "dependencies": [], "neededBy": [], "labels": [], @@ -30428,7 +31846,7 @@ }, "com.heytap.browser": { "list": "Oem", - "description": "Oppo Browser\nRebranded HeyTap browser for Oppo. Full of ads and spams you in notifications. You should never use this browser\nHeyTap's terrible privacy policy: https://brand.heytap.com/eu/privacy.html", + "description": "Oppo Browser\nRebranded HeyTap browser for Oppo and OnePlus devices. Full of ads and spams you in notifications. You should never use this browser\nHeyTap's terrible privacy policy: https://brand.heytap.com/eu/privacy.html", "dependencies": [], "neededBy": [], "labels": [], @@ -30604,7 +32022,7 @@ }, "com.glance.internet": { "list": "Misc", - "description": "Displays unsolicited \"trending\" stories on Lockscreen", + "description": "Displays unsolicited\"trending\" stories on Lockscreen", "dependencies": [], "neededBy": [], "labels": [], @@ -30660,7 +32078,7 @@ }, "com.oplus.athena": { "list": "Oem", - "description": "OnePlus background process manager. Removing it will solve the notification delay you can have but will disable the virtual ram expansion feature (swap RAM to disk) and the 'close all' button in the 'recent apps' page.\nRemoving this app may deteriorate battery performance.", + "description": "OnePlus background process manager. It aggressively kills apps. Despite battery optimization settings it kills Chrome not in use within few seconds; and Tasker can't run long-time jobs.\nRemoving it will disable the virtual ram expansion feature (swap RAM to disk) and the 'close all' button in the 'recent apps' page.\nKeep the app if you worry about battery life. Remove if your apps are killed.\nhttps://xdaforums.com/t/did-anyone-find-a-solution-against-the-agressive-background-killing-of-apps.4491351/post-87421063", "dependencies": [], "neededBy": [], "labels": [], @@ -30684,11 +32102,11 @@ }, "com.oplus.exsystemservice": { "list": "Oem", - "description": "[NEED MORE INFO / APK NEEDED] Lots of permissions. The screenshot function will stop working when the app is disabled.", + "description": "Has a lot of permissions. The screenshot function will stop working when the app is disabled.\nCan cause bootloop on some phones\nhttps://gist.github.com/zxdawn/21771f89f0e6ee01bcb0bb740058e2a0\nhttps://xdaforums.com/t/extreme-debloat-op12.4688984/\nhttps://www.apkmirror.com/apk/oneplus-ltd/system-service-2/system-service-2-1-1-5-release/system-service-1-1-5-2-android-apk-download/", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Expert" + "removal": "Unsafe" }, "com.oplus.stdid": { "list": "Oem", @@ -30719,11 +32137,11 @@ }, "com.oplus.wifibackuprestore": { "list": "Oem", - "description": "Lets you backup your wifi credentials to the cloud. This app has obviously access to your wifi credential and have the INTERNET permission.\n\nPithus analysis: https://beta.pithus.org/report/76e43cf4dc55452f39d9b6117074f4072189d3c8ad9cb295a86e49438545f7aa", + "description": "Lets you backup your wifi credentials to the cloud and possibly local wifi access point backups with local backup and restore feature. This app has obviously access to your wifi credential and have the INTERNET permission.\n\nPithus analysis: https://beta.pithus.org/report/76e43cf4dc55452f39d9b6117074f4072189d3c8ad9cb295a86e49438545f7aa\n\nWARNING: Removing this package may have similar effects of removing `com.coloros.wifibackuprestore` (see desc) as this could also break local wifi credential backups functionality without it. However, it's effects is only tested with ColorOS devices with similar package before Oneplus merge.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.tripledot.solitaire": { "list": "Misc", @@ -30839,7 +32257,7 @@ }, "com.agui.usbcamera": { "list": "Oem", - "description": "Toolbox > \"USB Camera\" Only usefull if you want to use a USB Camera\n", + "description": "Toolbox >\"USB Camera\" Only usefull if you want to use a USB Camera\n", "dependencies": [], "neededBy": [], "labels": [], @@ -30871,11 +32289,11 @@ }, "com.android.fmradio": { "list": "Aosp", - "description": "FM Radio\n Plug in Head phones & listen to the Radio!\n", + "description": "FM Radio\n Plug in Head phones & listen to the Radio!\nUninstalling will break FM Radio until reinstalled, and no other FM apps can be downloaded from app stores", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.haoba.btsmart": { "list": "Misc", @@ -30987,7 +32405,7 @@ }, "com.agui.providers.pedometer": { "list": "Oem", - "description": "Toolbox > \"Pedometer\" Pedometer/step counter.\nBecause of a feature that integrates with the lock sceen the System UI crashes when removed.", + "description": "Toolbox >\"Pedometer\" Pedometer/step counter.\nBecause of a feature that integrates with the lock sceen the System UI crashes when removed.", "dependencies": [], "neededBy": [], "labels": [], @@ -31017,11 +32435,75 @@ "dependencies": [], "neededBy": [], "labels": [], + "removal": "Advanced" + }, + "com.aura.oobe.kddi": { + "list": "Carrier", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some au carrier phones\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], "removal": "Recommended" }, - "com.aura.oobe.kbdi": { + "com.aura.oobe.ntt": { + "list": "Carrier", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some docomo carrier phones\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.softbank": { + "list": "Carrier", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some SoftBank carrier phones\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.rakuten": { + "list": "Carrier", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Rakuten Mobile carrier phones\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.solutions": { "list": "Oem", - "description": "Appcloud\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Xiaomi phones\nSafe to remove.", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Nothing & CMF Phone\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.lenovo": { + "list": "Oem", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Lenovo\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.ml": { + "list": "Oem", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Motorola\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.motorola": { + "list": "Oem", + "description": "Aura from Unity\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Motorola\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.dti.motorola": { + "list": "Oem", + "description": "Digital Turbine\nPersistent notification until you click on it and agree to install games. Sort of game cloud pre-installed in some Motorola\nSafe to remove.", "dependencies": [], "neededBy": [], "labels": [], @@ -31117,7 +32599,7 @@ }, "com.vivo.voicewakeup": { "list": "Oem", - "description": "Voice wake-up. Has a lot of permissions (REQUEST_INSTALL_PACKAGES, READ_EXTERNAL_STORAGE, RECORD_AUDIO...). Kind of a \"smart assistant\" ? It is constantly listening waiting for a trigger word [MORE INFO NEEDED]", + "description": "Voice wake-up. Has a lot of permissions (REQUEST_INSTALL_PACKAGES, READ_EXTERNAL_STORAGE, RECORD_AUDIO...). Kind of a\"smart assistant\" ? It is constantly listening waiting for a trigger word [MORE INFO NEEDED]", "dependencies": [], "neededBy": [], "labels": [], @@ -31701,11 +33183,11 @@ }, "com.google.android.apps.safetyhub": { "list": "Google", - "description": "Personal Safety (https://play.google.com/store/apps/details?id=com.google.android.apps.safetyhub)\nPersonal Safety is a Pixel app that helps you prepare and react in an emergency by quickly calling emergency services (e.g if your phone detects that you've been in a car crash, it can call for help automatically)\n\nThis app has obviously a lot of dangerous permissions due to its operation.\n\nPithus analysis: https://beta.pithus.org/report/e207f7d0f59d9df268154b90fc10cd861d0483465e30bbac8f68a7b12340c67f", + "description": "Personal Safety (https://play.google.com/store/apps/details?id=com.google.android.apps.safetyhub)\nPersonal Safety is a Pixel app that helps you prepare and react in an emergency by quickly calling emergency services (e.g if your phone detects that you've been in a car crash, it can call for help automatically, but only with a google account)\nMost features require a Google account to work except for medical information and emergency contacts. Emergency SOS (ie. pressing the power button 5 times to call emergency services) still works without this app.\n\nThis app has obviously a lot of dangerous permissions due to its operation.\n\nPithus analysis: https://beta.pithus.org/report/e207f7d0f59d9df268154b90fc10cd861d0483465e30bbac8f68a7b12340c67f", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "androidhwext": { "list": "Oem", @@ -31829,7 +33311,7 @@ }, "com.unisoc.phone": { "list": "Oem", - "description": "LockAssistant\nRuns before the user unlocks the device (direct-boot aware). Reads IMEI, SMS, call log, uses gps/wifi. Unisoc is a CPU manufacturer.", + "description": "LockAssistant\nRuns before the user unlocks the device (direct-boot aware). Reads IMEI, SMS, call log, uses gps/wifi. Unisoc is a CPU manufacturer. Related to package `com.android.unisoc.telephony.server`.", "dependencies": [], "neededBy": [], "labels": [], @@ -31941,11 +33423,11 @@ }, "com.android.bluetooth.overlay": { "list": "Oem", - "description": "Not a standard package provided by the Android framework.\nIt seems to be a custom package specific to a particular Android device or custom ROM.\nBased on the search results, there is no official documentation or information available about in the Android documentation or developer resources.\nIt is possible that this package contains custom overlays or modifications related to the Bluetooth functionality on a specific device or ROM.\nOverlays are used to customize the behavior or appearance of the Android system without modifying the core framework.\nThese overlays can be provided by device manufacturers or custom ROM developers to add or modify features specific to their devices.", + "description": "Not a standard package provided by the Android framework.\nIt seems to be a custom package specific to a particular Android device or custom ROM.\nBased on the search results, there is no official documentation or information available about in the Android documentation or developer resources.\nIt is possible that this package contains custom overlays or modifications related to the Bluetooth functionality on a specific device or ROM.\nOverlays are used to customize the behavior or appearance of the Android system without modifying the core framework.\nThese overlays can be provided by device manufacturers or custom ROM developers to add or modify features specific to their devices. Safe to remove if com.android.bluetooth is removed.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.android.networkstack.inprocess.overlay": { "list": "Aosp", @@ -31961,7 +33443,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.android.networkstack.tethering.overlay": { "list": "Aosp", @@ -31969,7 +33451,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Unsafe" + "removal": "Expert" }, "com.android.overlay.gmscontactprovider": { "list": "Oem", @@ -31977,7 +33459,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.gmssettingprovider": { "list": "Oem", @@ -31985,7 +33467,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.gmssettings": { "list": "Oem", @@ -31993,7 +33475,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.gmstelecomm": { "list": "Oem", @@ -32001,7 +33483,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.gmstelephony": { "list": "Oem", @@ -32009,11 +33491,11 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.systemui": { "list": "Aosp", - "description": "On some phones, it is an overlay to app \"com.google.android.apps.safetyhub\".\nCheck out this app code and think about it.", + "description": "On some phones, it is an overlay to app\"com.google.android.apps.safetyhub\".\nCheck out this app code and think about it.", "dependencies": [], "neededBy": [], "labels": [], @@ -32092,37 +33574,280 @@ "removal": "Recommended" }, "com.felicanetworks.mfc": { - "list": "Carrier", - "description": "Chinese felicanetworks", + "list": "Oem", + "description": "Mobile FeliCa Client (https://play.google.com/store/apps/details?id=com.felicanetworks.mfm.main)\nEssential app for using FeliCa.\nUninstalling this may occur errors to install this in apps which uses FeliCa. You can uninstall this if you don't use FeliCa-related services.\nNOTE: Uninstalling this does not remove the data saved in FeliCa.", "dependencies": [], - "neededBy": [], + "neededBy": ["com.felicanetworks.mfw.a.boot", "com.felicanetworks.mfm.main"], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.felicanetworks.mfm.main": { - "list": "Carrier", - "description": "Chinese felicanetworks", - "dependencies": [], + "list": "Oem", + "description": "Osaifu-Keitai App (https://play.google.com/store/apps/details?id=com.felicanetworks.mfm.main)\nA digital wallet app for Osaifu-Keitai brand.\nIt does not appear to be related to the FeliCa core functionality, but is required for services under the Osaifu-Keitai brand, such as iD and Mobile Suica.\nFor details, please check the app description (https://play.google.com/store/apps/details?id=com.felicanetworks.mfm.main) on Play Store.", + "dependencies": ["com.felicanetworks.mfc"], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.felicanetworks.mfs": { - "list": "Carrier", - "description": "Chinese felicanetworks", + "list": "Oem", + "description": "Initial setup application for FeliCa. Payments with FeliCa still works after uninstalling this.", "dependencies": [], "neededBy": [], "labels": [], "removal": "Recommended" }, "com.felicanetworks.mfw.a.boot": { - "list": "Carrier", - "description": "Chinese felicanetworks", + "list": "Oem", + "description": "Osaifu-Keitai Web Plugin (https://play.google.com/store/apps/details?id=com.felicanetworks.mfw.a.boot)\nUsed by websites on your browser to get payment information and process payments with FeliCa.\nSafe to remove if you don't use Osaifu-Keitai online.", + "dependencies": ["com.felicanetworks.mfc"], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.nfc.felicalocktest": { + "list": "Oem", + "description": "Testing FeliCa carrier remote lock. Common to Softbank, au, and docomo.", "dependencies": [], "neededBy": [], "labels": [], "removal": "Recommended" }, + "com.nttdocomo.android.anmane2": { + "list": "Carrier", + "description": "Likely a placeholder for docomo's corporate MDM service. Empty package and disabled by default on consumer devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.anshinsecurity": { + "list": "Carrier", + "description": "Anshin-security (https://www.docomo.ne.jp/service/anshin_security/)\ndocomo's security suite providing virus scanning, spam call/email prevention and so on.\nSafe to remove, but you may want to check https://mydocomo.docomo.ne.jp for subscriptions. Frequently bundled with device insurance service.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.apnsw": { + "list": "Carrier", + "description": "APN switching control\nResource-only stub. Safe to remove.\nMay potentially cause tethering issues on legacy (pre-2016) models due to docomo's APN-switching requirements?", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.applicationmanager": { + "list": "Carrier", + "description": "docomo Application Manager\nManages installation and updates of docomo-specific app.\nSafe to remove if you don't use any docomo service.\nNOTE: After reinstall, reboot needed to launch in some cases.", + "dependencies": [], + "neededBy": [ + "com.nttdocomo.android.homezozo", + "com.nttdocomo.android.dhome" + ], + "labels": [], + "removal": "Advanced" + }, + "com.nttdocomo.android.databackup": { + "list": "Carrier", + "description": "Backup feature for application of docomo's service, mainly provides schedule/memo's cloud sync function.", + "dependencies": [], + "neededBy": ["com.nttdocomo.android.schedulememo"], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.devicehelp": { + "list": "Carrier", + "description": "Recommended usage tips\nIntrusive. Provide \"helpful hints\" based on user activity, but behaving like adware by showing frequent pop-ups.\nRequires high-level permissions such as Accessibility and \"Draw over other apps\" (overlay) to monitor user actions.\nIt's not enabled by default, but uninstalling recommended for a cleaner, more private experience.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.dmenu2": { + "list": "Carrier", + "description": "d-menu\nWeb page shortcut and notification receiver.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.docomoset": { + "list": "Carrier", + "description": "docomo service/cloud Settings\nAdds a \"docomo service/cloud\" entry to the system Settings app. Simple navigation screen providing entry points to docomo-specific app settings, such as d-account and docomo application manager.\nEssential for launching d-account settings.\nSafe to remove if you don't use any docomo service.", + "dependencies": [], + "neededBy": ["com.nttdocomo.android.idmanager"], + "labels": [], + "removal": "Advanced" + }, + "com.nttdocomo.android.homezozo": { + "list": "Carrier", + "description": "docomo LIVE UX\ndocomo's default home screen (launcher).\nSafe to remove ONLY IF another launcher is installed. Certain devices such as dtab may not have any other home screen apps preinstalled.\ndocomo application manager (com.nttdocomo.android.applicationmanager) must be installed to use this.", + "dependencies": ["com.nttdocomo.android.applicationmanager"], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nttdocomo.android.dhome": { + "list": "Carrier", + "description": "Legacy docomo LIVE UX\ndocomo's default home screen (launcher).\nSafe to remove ONLY IF another launcher is installed. Certain devices such as dtab may not have any other home screen apps preinstalled.\ndocomo application manager (com.nttdocomo.android.applicationmanager) must be installed to use this.", + "dependencies": ["com.nttdocomo.android.applicationmanager"], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nttdocomo.android.idmanager": { + "list": "Carrier", + "description": "d ACCOUNT Settings\nAccount Settings for d-account, includes an authentication component for other docomo apps.\nSafe to remove if you don't use any docomo services, but ensure you check your login method as you may need this app for two-step authentication when logging in from other devices.", + "dependencies": ["com.nttdocomo.android.docomoset"], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nttdocomo.android.initialization": { + "list": "Carrier", + "description": "DOCOMO initialization\nOOBE (Initial setup) component for docomo devices. Safe to remove.\nTips: Apps deleted here will be restored when you factory reset the device!", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.mascot": { + "list": "Carrier", + "description": "my daiz (https://www.docomo.ne.jp/service/mydaiz/)\ndocomo's information (e.g. weather, news) app. Also displays a mascot (looks like tofu) on docomo LIVE UX. Requires lots of permissions.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.msg": { + "list": "Carrier", + "description": "+Message\nA messaging app using a carrier-customized RCS implementation by Softbank, au, and docomo. It adds LINE-like features to the standard SMS/RCS.\nSafe to remove, but recommended to have an alternative SMS app for OTPs.\nGoogle Messages is a simpler and more standard alternative.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.mymagazine": { + "list": "Carrier", + "description": "SmartNews for docomo\nNews app. Special version of SmartNews for docomo user.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.networkservice": { + "list": "Carrier", + "description": "Office Link Settings\nProvides \"Office Link\" service (docomo's enterprise internal line service). Typically accessed through the settings menu of the OEM Phone app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.pf.dcmippushaggregator": { + "list": "Carrier", + "description": "A background platform service that manages docomo's proprietary IP push notification system.\nSafe to remove if you don't need to receive docomo's service notifications.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.remotelock": { + "list": "Carrier", + "description": "Omakase-lock (https://www.docomo.ne.jp/service/lock/)\nRemote device lock service. Allows docomo customer support to lock your device upon request.\nSafe to remove. Google's \"Find Hub\" are better-integrated alternatives including NFC (=FeliCa) remote lock.\nNOTE: To uninstall this, open settings > App permission > Special app access > Device admin apps and disable this app (May vary depending on your device).\nFor FeliCa remote lock, a separate package (com.nttdocomo.android.felicaremotelock) is used.", + "dependencies": ["com.nttdocomo.android.felicaremotelock"], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.schedulememo": { + "list": "Carrier", + "description": "Schedule & Memo\n2 different apps in one package; docomo's schedule and memo apps.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.store": { + "list": "Carrier", + "description": "d-Point Market\nWeb page shortcut and notification receiver.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.wipe": { + "list": "Carrier", + "description": "Remote Wipe (https://www.docomo.ne.jp/service/initialization/)\nAllows docomo customer support to wipe your device upon request. This does NOT clear data inside the FeliCa chip.\nSafe to remove. Google's \"Find Hub\" or oem provided services are better-integrated alternatives.\nNOTE: To uninstall this, open settings > App permission > Special app access > Device admin apps and disable this app (May vary depending on your device).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "jp.co.nttdocomo.anshinmode": { + "list": "Carrier", + "description": "Anshin-Filter for docomo (https://www.docomo.ne.jp/service/anshin_filter/0)\nCarrier-provided parental controls. Terrible.\nCauses excessive battery drain on both parent and child devices due to heavy background polling, and a ton of other issues.\nIf you care about your child's better well-being, digital experience and parent-child relationships, consider using alternative services such as Google Family link.\nStrongly recommended to uninstall.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "jp.co.nttdocomo.carriermail": { + "list": "Carrier", + "description": "docomo mail\nCarrier mail app. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "jp.co.nttdocomo.lcsapp": { + "list": "Carrier", + "description": "docomo location information\nProvides \"Keitai-Osagashi Service\" (Mobile Phone Finder Service) and \"imadoco search\" (parental tracking) by docomo.\ncom.nttdocomo.android.docomoset is needed to launch settings screen.\nSafe to remove, but you may want to check https://mydocomo.docomo.ne.jp for subscriptions and \"imadoco search\" Opt-Out at https://spf.spmode.ne.jp/location/posinfo_sp (spf.spmode.ne.jp is only accessible via mobile network).\nGoogle's \"Find Hub\" and \"Family Link\" are free and better alternatives integrated with Android.", + "dependencies": ["com.nttdocomo.android.docomoset"], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "jp.co.nttdocomo.saigaiban": { + "list": "Carrier", + "description": "Disaster kit (https://www.docomo.ne.jp/info/disaster/disaster_kit/)\nA dedicated app for docomo's safety registration service used during major emergencies. It allows users to post and search for safety status.\nNOTE: This is not related to the core functionality of Area Mail (early warning). For checking Area Mail history, you can find it in system settings.\nSafe to remove; use web171.jp, Disaster Message Dial (171) or LINE's safety status feature instead for about safety status.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nttdocomo.android.felicaremotelock": { + "list": "Oem", + "description": "This is used to lock the Osaifu-Keitai (FeliCa), works with Omakase-lock (com.nttdocomo.android.remotelock).\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.overlay.dcmconfig": { + "list": "Oem", + "description": "Static overlay that sets \"config_systemContacts\" to \"docomo phonebook\" (customized com.android.contacts).\nNOTE: Safe to remove, reboot needed after uninstalling.\n\"docomo phonebook\" itself is safe to remove whether this overlay is installed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.overlay.dcmconfig.sms": { + "list": "Oem", + "description": "Static overlay that sets \"config_defaultSms\" to \"+Message\" (com.nttdocomo.android.msg).\nNOTE: Safe to remove, reboot needed after uninstalling.\n\"+Message\" itself is safe to remove whether this overlay is installed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.nfc.resources.japan": { + "list": "Oem", + "description": "Overlay for com.android.nfc", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.aura.oobe.motorola": { "list": "Carrier", "description": "MotoApps\nIt's something to install apps, but it's an advertising company.", @@ -32221,7 +33946,7 @@ }, "com.android.uwb.resources": { "list": "Aosp", - "description": "Ultra-wideband (UWB) communication feature.\nUWB is a radio technology that enables precise ranging between devices,\nAllowing for accurate location measurements with an accuracy of 10 cm.\nhttps://developer.android.com/develop/connectivity/uwb\nhttps://source.android.com/docs/core/connect/uwb", + "description": "Uninstalling will cause bootloop on certain devices. Seems to be not affected by whether the hardware supports UWB or not.\nUltra-wideband (UWB) communication feature.\nUWB is a radio technology that enables precise ranging between devices, allowing accurate location measurements with an accuracy of 10 cm.\nSee https://developer.android.com/develop/connectivity/uwb\nhttps://source.android.com/docs/core/connect/uwb\nOnly supported on a currently narrow amount of devices, primarily high-end devices. But the app itself is often preinstalled even if your phone doesn't have any UWB hardware, especially on newer Android versions.\n", "dependencies": [], "neededBy": [], "labels": [], @@ -32373,7 +34098,7 @@ }, "com.motorola.omadm.usc": { "list": "Carrier", - "description": "OMA Device Management for Verizon \nHandles configuration of the device (including first time use), enabling and disabling features provided by carriers.\nhttps://en.wikipedia.org/wiki/OMA_Device_Management\nI believe it's only useful if you want to use a Verizon service with a non branded phone (not sure at all)\nhttps://www.androidpolice.com/2015/03/10/android-5-1-includes-new-carrier-provisioning-api-allows-carriers-easier-methods-of-setting-up-services-on-devices-they-dont-control/\nDisplays annoying notifications if you unlocked your bootloader", + "description": "OMA Device Management for Verizon\nHandles configuration of the device (including first time use), enabling and disabling features provided by carriers.\nhttps://en.wikipedia.org/wiki/OMA_Device_Management\nI believe it's only useful if you want to use a Verizon service with a non branded phone (not sure at all)\nhttps://www.androidpolice.com/2015/03/10/android-5-1-includes-new-carrier-provisioning-api-allows-carriers-easier-methods-of-setting-up-services-on-devices-they-dont-control/\nDisplays annoying notifications if you unlocked your bootloader", "dependencies": [], "neededBy": [], "labels": [], @@ -32461,15 +34186,7 @@ }, "com.sec.android.app.felicatest": { "list": "Oem", - "description": "FeliCa Test, hidden debugs,logs HAL_Nfc", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, - "com.nttdocomo.android.felicaremotelock": { - "list": "Oem", - "description": "FeliCa Remote security things, not needed", + "description": "FeliCa Test, hidden debugs, logs HAL_Nfc", "dependencies": [], "neededBy": [], "labels": [], @@ -32597,7 +34314,7 @@ }, "com.samsung.android.visualars": { "list": "Oem", - "description": "Smart Touch Call.\nIt allows the user to \"Get voice and Screen interactive service when you call a customer service\".\nBloated with Google API stuff", + "description": "Smart Touch Call.\nIt allows the user to\"Get voice and Screen interactive service when you call a customer service\".\nBloated with Google API stuff", "dependencies": [], "neededBy": [], "labels": [], @@ -32617,7 +34334,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.sec.android.settingsmaps": { "list": "Oem", @@ -32733,7 +34450,7 @@ }, "com.qualcomm.qti.tetherservice": { "list": "Oem", - "description": "Needed for tethering, some chinese phones uses qualcomm names apps instead of normal", + "description": "Needed for tethering, some chinese phones use qualcomm names apps instead of normal", "dependencies": [], "neededBy": [], "labels": [], @@ -32841,7 +34558,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.ims.dm": { "list": "Oem", @@ -32923,14 +34640,6 @@ "labels": [], "removal": "Recommended" }, - "com.felicanetworks.mfm": { - "list": "Carrier", - "description": "Setup Chinese felicanetworks", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, "com.sec.android.app.minimode.res": { "list": "Oem", "description": "Minimode will be not available when this app be removed", @@ -32981,7 +34690,15 @@ }, "jp.co.omronsoft.mushroom.CommonPhrase": { "list": "Oem", - "description": "Japanese Phrases app", + "description": "Provides a feature called \"Mushroom\" that is a phrase table shared between Japanese keyboards.\nJapanese keyboards still work without this.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "jp.co.omronsoft.mushroom.commonphrase": { + "list": "Oem", + "description": "Provides a feature called \"Mushroom\" that is a phrase table shared between Japanese keyboards.\nJapanese keyboards still work without this.", "dependencies": [], "neededBy": [], "labels": [], @@ -33153,7 +34870,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.samsung.commonimsservice": { "list": "Oem", @@ -33250,6 +34967,14 @@ "neededBy": [], "labels": [], "removal": "Expert" + }, + "com.sec.android.app.tfunlock": { + "list": "Carrier", + "description": "The unlocking interface and process when unlocking a Tracfone-based phone. Probably needed for unlocking your carrier status. probably needed if you want to unlock your phone from a Tracfone service.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" }, "com.sec.android.app.tourviewer": { "list": "Oem", @@ -33353,7 +35078,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.healthconnect.controller": { "list": "Aosp", @@ -33361,23 +35086,23 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.virtualmachine.res": { "list": "Aosp", - "description": "unknown app with no code that only has permissions to Use, Manage, Debug: Virtual Machine.\nIntroduced in Android 14.", + "description": "Empty app with no code that declares permissions to Use, Manage, Debug: Virtual Machine for use by other apps. Deleting this app may cause potential security issues because another app could redefine the permissions with lower restriction level. Nothing to gain by removing.\nIntroduced in Android 14.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.android.rkpdapp": { "list": "Aosp", - "description": "RemoteProvisioner. Have random stuff: security, notifications, accessibility, test modes, data usage, metrics, logs.\nIntroduced in android 14(it's the same app like `com.android.remoteprovisioner` Introduced in android 13).\nAgain this app is not available for users.\nAnd looks very useless.", + "description": "The Remote Provisioner app. Provisions cryptographic keys remotely from google servers instead of generating them only on-device.\nIt's likely to break security apps and services, such as bank apps, payment services, authentication, and other security-requiring operations if removed, as they won't work without cryptographic keys.\nPlay Integrity is also likely fail.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.apps.googlecamera.fishfood": { "list": "Aosp", @@ -33385,7 +35110,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.systemui.accessibility.accessibilitymenu": { "list": "Aosp", @@ -33405,11 +35130,11 @@ }, "com.stevesoltys.seedvault": { "list": "Oem", - "description": "Seedvault\nRunning in the background.\nit's app for Backup, Restore your data.", + "description": "Seedvault: https://github.com/seedvault-app/seedvault\nOpen source component for custom ROMs for backuping up apps (and files) with Android's internal backup APIs\nUseful but should be safe to remove, there aren't other rootless backup tools\nDoes not run in the background unless the user uses it.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.huawei.airlink": { "list": "Oem", @@ -33861,11 +35586,11 @@ }, "com.google.android.tungsten.setupwraith": { "list": "Oem", - "description": "First boot setup TV.\nhttps://play.google.com/store/apps/details?id=com.google.android.tungsten.setupwraith&hl=en&gl=US", + "description": "First boot setup TV.\nRemoving it crashes sound related system settings and breaks volume control on Sony Bravia TV.\nhttps://play.google.com/store/apps/details?id=com.google.android.tungsten.setupwraith&hl=en&gl=US", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.google.android.tv.axel": { "list": "Oem", @@ -33900,8 +35625,8 @@ "removal": "Expert" }, "com.google.android.tvlauncher": { - "list": "Oem", - "description": "Android TV Home\nhttps://play.google.com/store/apps/details?id=com.google.android.tvlauncher&hl=en&gl=US", + "list": "Google", + "description": "Android TV Home, on some devices, removing this causes the device to restore default settings on the next power on.\nhttps://play.google.com/store/apps/details?id=com.google.android.tvlauncher&hl=en&gl=US\nhttps://www.clrn.org/how-to-disable-google-tv-on-android/", "dependencies": [], "neededBy": [], "labels": [], @@ -34025,7 +35750,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.motorola.paramupdater": { "list": "Oem", @@ -34293,7 +36018,7 @@ }, "com.oplus.cota": { "list": "Oem", - "description": "Carrier software updater?\nLooks like software updater for carrier phones.", + "description": "Configuration Update Over The Air\nNeeded for OTA updates. Likely needed to download and install system updates, device configuration, and carrier/enterprise customizations on OnePlus devices. It ensures your device stays up-to-date and compliant with carrier or company requirements, and interacts with the user only when necessary (e.g., update dialogs, legal statements).", "dependencies": [], "neededBy": [], "labels": [], @@ -34362,6 +36087,38 @@ "neededBy": [], "labels": [], "removal": "Advanced" + }, + "com.oplus.aicall": { + "list": "Oem", + "description": "Provides AI summaries in the ODialer app", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.oplus.aimemory": { + "list": "Oem", + "description": "Mind Space (also called 'Breeno Memory')\nSaves and summarizes content using AI. Runs on the background, even though when you're not using it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.oplus.aiwriter": { + "list": "Oem", + "description": "AI Writer\nPop-up for AI text generation, often appears in places that are not text input fields.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.oplus.aipaint": { + "list": "Oem", + "description": "AI Paint\nUnsure what it's used for but probably has to do with editing images.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" }, "com.oplus.apprecover": { "list": "Oem", @@ -34433,7 +36190,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.oplus.engineercamera": { "list": "Oem", @@ -34489,7 +36246,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.launcher": { "list": "Oem", @@ -34645,11 +36402,11 @@ }, "com.android.DeviceAsWebcam": { "list": "Oem", - "description": "Using smartphone as webcam.", + "description": "Using smartphone as webcam. Dependency for Private space on Pixel devices.\nhttps://source.android.com/docs/security/features/private-space", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.omadm.service": { "list": "Oem", @@ -34681,7 +36438,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.grilservice": { "list": "Oem", @@ -34733,20 +36490,20 @@ }, "com.google.pixel.camera.services": { "list": "Oem", - "description": "CameraIDRemapper and a lot Debug stuff.", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Recommended" - }, - "com.google.android.apps.camera.services": { - "list": "Oem", - "description": "Pixel Camera Services\nExperimental stuff, Camera Calibration.", + "description": "CameraIDRemapper and a lot Debug stuff. Dependency for Private space on Pixel devices.\nhttps://source.android.com/docs/security/features/private-space", "dependencies": [], "neededBy": [], "labels": [], "removal": "Advanced" }, + "com.google.android.apps.camera.services": { + "list": "Oem", + "description": "Pixel Camera Services\nExperimental stuff, Camera Calibration. Will break any third-party camera app if removed", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.android.qns": { "list": "Oem", "description": "Apn service, emergency calling, not sure how useful this app is.", @@ -34929,7 +36686,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.emergency": { "list": "Oem", @@ -34969,7 +36726,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.logmanager": { "list": "Oem", @@ -34977,7 +36734,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.messaging": { "list": "Oem", @@ -34987,13 +36744,21 @@ "labels": [], "removal": "Advanced" }, + "com.android.music": { + "list": "Oem", + "description": "The com.android.music package is the default music player app that comes pre-installed on many Android devices. It provides basic music playback functionality and may include features like playlists and library management. Since there are many better and more feature-rich music player apps available on Google Play, and this app does not offer any unique features specific to your device, removing it should not impact the core functionality of the operating system.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.android.overlay.music": { "list": "Oem", "description": "Overlay to 'com.android.music' icons png.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.quicksearchbox": { "list": "Oem", @@ -35017,7 +36782,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.android.overlay.stk": { "list": "Oem", @@ -35035,6 +36800,14 @@ "labels": [], "removal": "Advanced" }, + "com.android.writeimei": { + "list": "Oem", + "description": "The com.android.writeimei package is responsible for handling the IMEI (International Mobile Equipment Identity) number on the device. This app is used for writing or managing the device’s IMEI, which is a unique identifier for mobile devices. Removing or tampering with this package can cause significant issues, such as loss of network connectivity, inability to make calls or send texts, and potential bootloop issues.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, "com.android.providers.settings.auto_generated_rro_vendor__": { "list": "Oem", "description": "rro = Runtime Resources Overlay.\nChanges values of a package config, based in the overlay definitions (heavily used by OEMs to customize the look and feel of Android).", @@ -35053,11 +36826,11 @@ }, "com.android.unisoc.telephony.server": { "list": "Oem", - "description": "UICC stands for Universal Integrated Circuit Card.\nIt is a the physical and logical platform for the USIM and may contain additional USIMs and other applications.\n(U)SIM is an application on the UICC.\nOnly for China.", + "description": "Unisoc 4G and 5G drivers. Removal will break incoming calls. https://xdaforums.com/t/oukitel-wp23-pro-unlocking-bootloader-rooting-gsi.4642483/#post-89239693", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Expert" }, "com.cdfinger.factorytest": { "list": "Oem", @@ -35273,7 +37046,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.transsion.powercenter": { "list": "Oem", @@ -35334,7 +37107,9 @@ "com.huawei.cloud": { "list": "Oem", "description": "Chinese only.\nHuawei Cloud Computer provides you with basic services of online desktop.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35366,7 +37141,9 @@ "com.huawei.android.findmyphone": { "list": "Oem", "description": "Find Device is an app that lets you locate your device and protect your data remotely.\nTo provide these features, this app needs to connect to the Internet during use.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Advanced" @@ -35374,7 +37151,9 @@ "com.huawei.gamebox": { "list": "Oem", "description": "GameCenter\nRequires HMS Core to run.\nIt's app for installing games.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35382,7 +37161,9 @@ "com.huawei.hicar": { "list": "Oem", "description": "Huawei HiCar\nTo connect to Huawei HiCar, press and hold the wireless button on the steering wheel or control panel.\nMore useful in China.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35390,7 +37171,9 @@ "com.huawei.smarthome": { "list": "Oem", "description": "AI Life\nRequire Logging in to your Huawei ID, HMSCore.\nIt's app that lets your control and manage routers and audio accessories.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35430,7 +37213,9 @@ "com.huawei.hiskytone": { "list": "Oem", "description": "SkyTone Overseas Data Service.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35550,7 +37335,9 @@ "com.huawei.fans": { "list": "Oem", "description": "Huawei Club is the official forum for Huawei users.\nIt provides the latest news and information, FAQs, and tutorials about Huawei and Honor products.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35574,7 +37361,9 @@ "com.huawei.lives": { "list": "Oem", "description": "HiLives is jointly developed by Huawei and certified third-party service providers to provide lifestyle services for you.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35718,7 +37507,9 @@ "com.huawei.hwvplayer.youku": { "list": "Oem", "description": "Video Youku\nVideo Player on Chinese Huawei. Has some ads and bad privacy.", - "dependencies": ["com.huawei.hwid"], + "dependencies": [ + "com.huawei.hwid" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35766,7 +37557,9 @@ "com.huawei.skytone": { "list": "Oem", "description": "SkyTone Data Service. Frameworks to 'com.huawei.hiskytone' SkyTone Overseas Data Service.", - "dependencies": ["com.huawei.hiskytone"], + "dependencies": [ + "com.huawei.hiskytone" + ], "neededBy": [], "labels": [], "removal": "Recommended" @@ -35805,11 +37598,11 @@ }, "jp.co.omronsoft.iwnnime.ml": { "list": "Carrier", - "description": "iWnn IME\nJapanese keyboard pre-installed on some Huawei phone's.", + "description": "iWnn IME\nJapanese keyboard pre-installed on some Huawei and Kyocera phones. Some phones cannot be unlocked without it.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Unsafe" }, "com.kmsjp": { "list": "Carrier", @@ -35889,7 +37682,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.google.android.overlay.gmsconfig.tier1": { "list": "Oem", @@ -36121,7 +37914,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.alam.overlay.android.systemui": { "list": "Oem", @@ -36129,7 +37922,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.qualcomm.atfwd2": { "list": "Misc", @@ -36161,7 +37954,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.miui.securitycenter.securitycenter_phone_overlay.config.overlay": { "list": "Oem", @@ -36169,7 +37962,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.xiaomi.touchservice": { "list": "Oem", @@ -36241,7 +38034,7 @@ "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.magiear.handsfree.assistant": { "list": "Misc", @@ -36349,11 +38142,11 @@ }, "com.android.role.notes.enabled": { "list": "Oem", - "description": "Notes Role enabled\nUnknown overlay, but looks like a safe to remove, sets default notes.", + "description": "Notes Role enabled\nUnknown overlay, sets default notes. Breaks seamlessly disabling and enabling developer options on Google Pixel(s).\n", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Recommended" + "removal": "Advanced" }, "com.xiaomi.oobhelper": { "list": "Oem", @@ -36459,6 +38252,14 @@ "labels": [], "removal": "Recommended" }, + "com.bird.motionrecognition": { + "list": "Oem", + "description": "The com.bird.motionrecognition package is likely related to motion recognition features on your device, such as gesture controls or other motion-based functionalities. This package may be specific to the OEM and provide unique functionalities not found in standard Android builds. While removing it might disable certain gesture or motion-based features, it should not impact core system functionalities.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, "com.baidu.BaiduMap": { "list": "Oem", "description": "Chinese Baidu Map.", @@ -36917,7 +38718,7 @@ }, "com.samsung.android.rampart": { "list": "Oem", - "description": "Auto Blocker\nUses for blocking unknown apps install, commands.", + "description": "Auto Blocker\nUses for blocking unknown apps install, commands. As of Oneui 6.1.1+, it is no longer tied to App Protection unless you use maximum restrictions. A powerful tool that can keep your device secure, but also be an annoyance if you sideload apps from F-Droid or other sources.", "dependencies": [], "neededBy": [], "labels": [], @@ -37005,11 +38806,11 @@ }, "com.samsung.android.providers.trash": { "list": "Oem", - "description": "SecTrashProvider\nIndexes almost things to trash.\nThis app probably only exist on China Samsung.", + "description": "SecTrashProvider\nTrash feature for Galaxy phones since One UI 6.0\nAllows users to delete and restore files from My Files, Gallery, Voice Recordings, etc. directly from the Trash folder in My Files.\nBreaks apps that delete to Trash.", "dependencies": [], "neededBy": [], "labels": [], - "removal": "Advanced" + "removal": "Expert" }, "com.samsung.android.tencentwifisecurity": { "list": "Oem", @@ -37067,6 +38868,14 @@ "labels": [], "removal": "Recommended" }, + "com.val.hardware": { + "list": "Oem", + "description": "FactoryApp\nOEM hardware diagnostic tool for manufacturing/service testing (camera, Bluetooth, WiFi, FM radio, telephony, battery, flashlight). Requires broad system permissions (reboot, audio/phone mods, secure settings).\nNot for end-users; safe to remove to reduce bloat.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, "com.samsung.android.sskds": { "list": "Oem", "description": "SoterSskdsService\nThis app has something to 'com.tencent.soter.soterserver'.\nOnly china.", @@ -37155,6 +38964,14 @@ "labels": [], "removal": "Unsafe" }, + "com.samsung.android.wifi.resources.wpa2": { + "list": "Oem", + "description": "Needed for WiFi.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, "com.samsung.sprint.chameleon": { "list": "Carrier", "description": "Chameleon service which is a service designed to store sprint-specific properties (customizes some apps).", @@ -37453,7 +39270,7 @@ }, "com.android.settings.resoverlay": { "list": "Oem", - "description": "Found in the code \"Declaration of Conformity\" on the TECNO phone, is probably unused, as it cannot be found in the Settings or anywhere else.\nIt can be safely removed, the Settings still work without this app.", + "description": "Found in the code\"Declaration of Conformity\" on the TECNO phone, is probably unused, as it cannot be found in the Settings or anywhere else.\nIt can be safely removed, the Settings still work without this app.", "dependencies": [], "neededBy": [], "labels": [], @@ -37644,14 +39461,14 @@ "removal": "Advanced" }, "com.samsung.android.server.wifi.mobilewips.client": { - "list": "Oem", - "description": "MobileWips\nDetects suspicious activity on Wi-Fi network.", - "dependencies": [], - "neededBy": [], - "labels": [], - "removal": "Advanced" + "list": "Oem", + "description": "MobileWips\nDetects suspicious activity on Wi-Fi network.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" }, -"com.onyx.aiassistant": { + "com.onyx.aiassistant": { "list": "Oem", "description": "Onyx Boox AI Assistant. Safe to remove", "dependencies": [], @@ -37667,8 +39484,7 @@ "labels": [], "removal": "Unsafe" }, - - "com.onyx.android.production.test":{ + "com.onyx.android.production.test": { "list": "Oem", "description": "Test app enabled by clicking 5 times on the Onyx Version, it contains tests for screen quality", "dependencies": [], @@ -37676,7 +39492,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.appmarket":{ + "com.onyx.appmarket": { "list": "Oem", "description": "The Onyx Store app, you will not have any other way to install app if you uninstall it\nYou will need to install an alternative store via adb", "dependencies": [], @@ -37692,7 +39508,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.clock":{ + "com.onyx.clock": { "list": "Oem", "description": "The Onyx Clock app", "dependencies": [], @@ -37700,7 +39516,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.dict":{ + "com.onyx.dict": { "list": "Oem", "description": "The Onyx Dict app", "dependencies": [], @@ -37708,7 +39524,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.easytransfer":{ + "com.onyx.easytransfer": { "list": "Oem", "description": "Onyx Easy Transfer app", "dependencies": [], @@ -37716,7 +39532,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.gallery":{ + "com.onyx.gallery": { "list": "Oem", "description": "Onyx Gallery app", "dependencies": [], @@ -37724,7 +39540,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.igetshop":{ + "com.onyx.igetshop": { "list": "Oem", "description": "Onyx iGetShot app, UNSAFE to remove because it will crash the Onyx Launcher but safe to DISABLE", "dependencies": [], @@ -37732,7 +39548,7 @@ "labels": [], "removal": "Unsafe" }, - "com.onyx.kime":{ + "com.onyx.kime": { "list": "Oem", "description": "Onyx Kime app", "dependencies": [], @@ -37740,7 +39556,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.kreader":{ + "com.onyx.kreader": { "list": "Oem", "description": "Onyx KReader app, UNSAFE to remove because it will crash the Onyx Launcher can be safely disabled.\nRemember to load another reader app", "dependencies": [], @@ -37748,7 +39564,7 @@ "labels": [], "removal": "Unsafe" }, - "com.onyx.latinime":{ + "com.onyx.latinime": { "list": "Oem", "description": "The Onyx Keyboard. Removing it will leave withe google STT keyboard.", "dependencies": [], @@ -37756,7 +39572,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.mail":{ + "com.onyx.mail": { "list": "Oem", "description": "Onyx Mail app", "dependencies": [], @@ -37764,7 +39580,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.musicplayer":{ + "com.onyx.musicplayer": { "list": "Oem", "description": "Onyx Music Player app", "dependencies": [], @@ -37772,7 +39588,7 @@ "labels": [], "removal": "Recommended" }, - "com.onyx.voicerecorder":{ + "com.onyx.voicerecorder": { "list": "Oem", "description": "Onyx Voice Recorder app", "dependencies": [], @@ -37780,7 +39596,7 @@ "labels": [], "removal": "Recommended" }, - "com.preff.kb.xm":{ + "com.preff.kb.xm": { "list": "Oem", "description": "'Emoji & Font Keyboard' on Xiaomi.\nXiaomi won't let me uninstall it. If it's same for you, consider disabling it instead.\nMake sure to install an alternate keyboard app before doing so.", "dependencies": [], @@ -37788,7 +39604,7 @@ "labels": [], "removal": "Advanced" }, - "com.nim.rogers":{ + "com.nim.rogers": { "list": "Carrier", "description": "Texture, a digital magazine service created by Rogers Media. Discontinued in 2019.", "dependencies": [], @@ -37796,7 +39612,7 @@ "labels": [], "removal": "Recommended" }, - "com.Rogers.MyRogersTab":{ + "com.Rogers.MyRogersTab": { "list": "Carrier", "description": "Appears to be the tablet version of MyRogers (https://play.google.com/store/apps/details?id=com.fivemobile.myaccount), an app to manage your account with Canadian carrier Rogers.", "dependencies": [], @@ -37804,7 +39620,7 @@ "labels": [], "removal": "Recommended" }, - "com.samsung.android.app.colorblind":{ + "com.samsung.android.app.colorblind": { "list": "Oem", "description": "This app provides colorblind accessibility features for Samsung devices, helping users with color vision deficiencies by adjusting display colors and improving visibility.", "dependencies": [], @@ -37812,7 +39628,7 @@ "labels": [], "removal": "Advanced" }, - "com.samsung.android.framework.res":{ + "com.samsung.android.framework.res": { "list": "Oem", "description": "This package is part of Samsung’s custom system framework and manages various resources for Samsung-specific features and UI enhancements.", "dependencies": [], @@ -37820,7 +39636,7 @@ "labels": [], "removal": "Advanced" }, - "com.samsung.android.timezone.autoupdate_N":{ + "com.samsung.android.timezone.autoupdate_N": { "list": "Oem", "description": "This app handles automatic updates for time zone information on Samsung devices, ensuring accurate timekeeping across different regions.", "dependencies": [], @@ -37828,7 +39644,7 @@ "labels": [], "removal": "Advanced" }, - "com.samsung.knox.appsupdateagent":{ + "com.samsung.knox.appsupdateagent": { "list": "Oem", "description": "This app is part of Samsung Knox, managing updates for apps within the Knox security framework.", "dependencies": [], @@ -37836,7 +39652,7 @@ "labels": [], "removal": "Advanced" }, - "com.sec.android.app.kidshome":{ + "com.sec.android.app.kidshome": { "list": "Oem", "description": "This app provides a child-friendly interface and controls on Samsung devices, designed to create a safe environment for children by restricting access to apps and content.", "dependencies": [], @@ -37844,7 +39660,7 @@ "labels": [], "removal": "Recommended" }, - "com.sec.android.app.wallpaperchooser":{ + "com.sec.android.app.wallpaperchooser": { "list": "Oem", "description": "This app provides the functionality to select and manage wallpapers on Samsung devices, including Samsung-specific wallpaper options.", "dependencies": [], @@ -37852,7 +39668,7 @@ "labels": [], "removal": "Advanced" }, - "com.sec.app.TransmitPowerService":{ + "com.sec.app.TransmitPowerService": { "list": "Oem", "description": "This app manages settings related to the transmit power of wireless communications on Samsung devices, such as Wi-Fi and Bluetooth.", "dependencies": [], @@ -38150,7 +39966,3231 @@ }, "com.google.android.apps.weather": { "list": "Google", - "description": "The new Weather app by Google. If removed, \"At a Glance\" and the lock screen will still redirect to the Google app (like before).\nhttps://play.google.com/store/apps/details?id=com.google.android.apps.weather", + "description": "The new Weather app by Google. If removed,\"At a Glance\" and the lock screen will still redirect to the Google app (like before).\nhttps://play.google.com/store/apps/details?id=com.google.android.apps.weather", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.android.avatarpicker": { + "list": "Aosp", + "description": "Lets you assign pictures to contacts. It has two options: take picture from the camera, or choose from the gallery.\nSource code: https://android.googlesource.com/platform/packages/apps/AvatarPicker", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.de_DE": { + "list": "Oem", + "description": "This is the German language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.\nPath: /system/priv-app/SVoiceLang_GermanPack_DE_1.0/SVoiceLang_GermanPack_DE_1.0.apk", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.en_US": { + "list": "Oem", + "description": "This is the English language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.es_ES": { + "list": "Oem", + "description": "This is the Spanish language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.fr_FR": { + "list": "Oem", + "description": "This is the French language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.it_IT": { + "list": "Oem", + "description": "This is the Italian language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.svoice.lang.ru_RU": { + "list": "Oem", + "description": "This is the Russian language pack for Samsung's old S Voice assistant, enabling speech recognition and responses.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "mobile.miki": { + "list": "Oem", + "description": "Samsung's Factory Mode app for hardware testing and diagnostics.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.sos": { + "list": "Oem", + "description": "Emergency SOS app for quick access to emergency services and contacts.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.nfc.overlay.common": { + "list": "Oem", + "description": "Common overlay configuration for NFC functionality.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.systemui.clocks.flex": { + "list": "Oem", + "description": "Flexible clock interface for system UI customization.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.systemui.overlay.pixelbatteryhealthconfig": { + "list": "Oem", + "description": "Battery health overlay for Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.rkpdapp": { + "list": "Oem", + "description": "Security and privacy management app for Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.pixelsystemservice": { + "list": "Oem", + "description": "System service app for Pixel device management.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.pixel.avatarpicker": { + "list": "Oem", + "description": "Avatar picker for Google Pixel personalization.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "android.auto_generated_characteristics_rro": { + "list": "Oem", + "description": "Automatically generated RRO characteristics for Android customization.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.retaildemo": { + "list": "Oem", + "description": "Retail demo app for product displays in stores.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.apps.pixel.creativeassistant": { + "list": "Oem", + "description": "Creative Assistant for media editing and artistic tasks on Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.systemui.clocks.bignum": { + "list": "Oem", + "description": "Large clock display interface for the system UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.nfc.overlay": { + "list": "Oem", + "description": "NFC overlay configuration for system-level settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.settings.shiba": { + "list": "Oem", + "description": "Settings app with internal device-specific features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.telephony": { + "list": "Oem", + "description": "Core telephony system app for managing calls and messaging.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.systemui.overlay.pixelvpnconfig": { + "list": "Oem", + "description": "Pixel VPN configuration overlay for network management.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.devicediagnostics.auto_generated_rro_vendor__": { + "list": "Oem", + "description": "Device diagnostics and vendor-specific overlays for troubleshooting.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.settings.overlay.shiba": { + "list": "Oem", + "description": "Device-specific settings overlay for internal features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.devicelockcontroller": { + "list": "Oem", + "description": "Device lock and security controller for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.avatarpicker": { + "list": "Oem", + "description": "Avatar picker for Google account customization.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "android.autoinstalls.config.google.nexus": { + "list": "Oem", + "description": "Auto-install configuration for Google apps on Nexus devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.companiondevicemanager.auto_generated_characteristics_rro": { + "list": "Oem", + "description": "Companion device manager for Android device connections.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.overlay.devicelockcontroller": { + "list": "Oem", + "description": "Pixel device lock configuration overlay.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.microdroid.empty_payload": { + "list": "Oem", + "description": "Empty payload for MicroDroid sandbox testing.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.tetheringentitlement": { + "list": "Oem", + "description": "Tethering entitlement management for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.googlequicksearchbox.nga_resources": { + "list": "Oem", + "description": "Resources for Google Assistant quick search.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.phone.auto_generated_characteristics_rro": { + "list": "Oem", + "description": "Telephony characteristics for phone app customization.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.pixel.iwlan": { + "list": "Oem", + "description": "IWlan optimization for Pixel Wi-Fi connections.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.devicediagnostics": { + "list": "Oem", + "description": "Device diagnostics and health check tools for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.overlay.pixelconfig2021": { + "list": "Oem", + "description": "Pixel 2021 configuration overlay for device features and UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.compos.payload": { + "list": "Oem", + "description": "Payload for Google's Compose system handling notifications and widgets.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.pixeldisplayservice.auto_generated_rro_product__": { + "list": "Oem", + "description": "Auto-generated display service configurations for Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.storagemanager": { + "list": "Oem", + "description": "Storage management app for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.apps.diagnosticstool": { + "list": "Oem", + "description": "Diagnostic tool for troubleshooting Google services and system issues.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.wallpaper.effects": { + "list": "Oem", + "description": "Wallpaper visual effects for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.pixeldisplayservice": { + "list": "Oem", + "description": "Display management service for Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.systemui.clocks.inflate": { + "list": "Oem", + "description": "Customizable clock display for system UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.systemui.clocks.calligraphy": { + "list": "Oem", + "description": "Calligraphy-style clock faces for system UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.bluetooth": { + "list": "Oem", + "description": "Bluetooth management for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.apps.wallpaper.pixel": { + "list": "Oem", + "description": "Wallpaper app for Google Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.euiccpixel.permissions": { + "list": "Oem", + "description": "Permission manager for EU-configured Google Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.rilextension": { + "list": "Oem", + "description": "Google Assistant extension for enhanced functionality.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.internal.display.cutout.emulation.avoidAppsInCutout": { + "list": "Oem", + "description": "Avoid displaying apps in the notch area of the screen.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.devicediagnostics.auto_generated_rro_product__": { + "list": "Oem", + "description": "Auto-generated diagnostics configurations for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.contactkeys": { + "list": "Oem", + "description": "Contact key manager for Android interactions.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.systemui.clocks.weather": { + "list": "Oem", + "description": "Clock with integrated weather updates for system UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.providers.telephony.auto_generated_characteristics_rro": { + "list": "Oem", + "description": "Telephony characteristics for phone app and services.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.euiccpixel.overlay.zuma": { + "list": "Oem", + "description": "EU Pixel device overlay for regional functionality.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.iwlan": { + "list": "Oem", + "description": "IWLAN feature manager for enhanced connectivity.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.systemui.clocks.numoverlap": { + "list": "Oem", + "description": "Adjustable number overlap for system clock display.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.settings.overlay.pixelvpnconfig": { + "list": "Oem", + "description": "VPN configuration for Pixel devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.virtualmachine.res": { + "list": "Oem", + "description": "Resources for Android virtual machine environment.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.telephony.imsmedia": { + "list": "Oem", + "description": "IMS media management for VoLTE and video calling.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.healthconnect.overlay": { + "list": "Oem", + "description": "Health Connect overlay for fitness data integration.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.overlay.trafficlightfaceoverlay": { + "list": "Oem", + "description": "Traffic light face overlay for system UI enhancement.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.google.android.uwb.resources": { + "list": "Oem", + "description": "UWB technology resources for location tracking.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.systemui.clocks.growth": { + "list": "Oem", + "description": "Growth-themed dynamic clock display for system UI.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.server.deviceconfig.resources": { + "list": "Oem", + "description": "Device configuration server resources for Android devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "Info.Plateau.Einkbro": + { + "list": "Misc", + "description": "Open source web browser designed to fit E-ink devices, https://github.com/plateaukao/einkbro", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.inkbook.awesomereader": + { + "list": "Oem", + "description": "Stock reader app on Inkbook e-readers. Uninstall only if planning to use a different reader.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.inkbook.exoereader": + { + "list": "Oem", + "description": "Stock reader app on Inkbook e-readers. Uninstall only if planning to use a different reader.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.inkbook.os.plus": + { + "list": "Oem", + "description": "App repository for Inkbook e-readers: Kindle, Kobo etc. Safe to uninstall if not using them. Also installs and updates EinkBro and a stats tracking app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.inkbook.os.library": + { + "list": "Oem", + "description": "Default library app on Inkbook e-readers. Will break the UI if uninstalled so only do so if you plan to replace the default UI app with e.g. SimpleLauncher or somehting of the sort.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.inkbook.os.settings": + { + "list": "Oem", + "description": "Wrapper for Android settings which hides most irrelevant settings for e-ink devices e.g enabling animations.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.zte.linkspeedup": { + "list": "Oem", + "description": "Causes bootloop", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.google.android.settings.intelligence": { + "list": "Aosp", + "description": "Setting Services. Adds the main search bar for the settings app (the one at the top on the default page).\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.redstone.ota.ui": { + "list": "Oem", + "description": "This malware disguises itself as an update app, tracks the user and installs malware in the background.\nhttps://www.virustotal.com/gui/file/0aefcffd253e575474dbbbf1f60d77cfaa679c0abe3241d0ee397fbbb2ad9924/details\nhttps://www.malwarebytes.com/blog/news/2021/04/pre-installed-auto-installer-threat-found-on-android-mobile-devices-in-germany\nhttps://thehackernews.com/2021/04/pre-installed-malware-dropper-found-on.html", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.wagd.gem": { + "list": "Oem", + "description": "This malware is capable of sending malicious messages via WhatsApp, opening new tabs in the default web browser to game websites, downloading more malicious apps, and possibly other malicious behaviors.\nThe malicious WhatsApp messages are most likely in order to further spread the infection to other mobile devices.\nhttps://www.malwarebytes.com/blog/news/2021/04/pre-installed-auto-installer-threat-found-on-android-mobile-devices-in-germany", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.wagd.smarter": { + "list": "Oem", + "description": "This malware is capable of sending malicious messages via WhatsApp, opening new tabs in the default web browser to game websites, downloading more malicious apps, and possibly other malicious behaviors.\nThe malicious WhatsApp messages are most likely in order to further spread the infection to other mobile devices.\nhttps://www.malwarebytes.com/blog/news/2021/04/pre-installed-auto-installer-threat-found-on-android-mobile-devices-in-germany", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.wagd.xiaoan": { + "list": "Oem", + "description": "This malware is capable of sending malicious messages via WhatsApp, opening new tabs in the default web browser to game websites, downloading more malicious apps, and possibly other malicious behaviors.\nThe malicious WhatsApp messages are most likely in order to further spread the infection to other mobile devices.\nhttps://www.malwarebytes.com/blog/news/2021/04/pre-installed-auto-installer-threat-found-on-android-mobile-devices-in-germany", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.oplus.studycenter": { + "list": "Oem", + "description": "Study Center is an educational application officially developed by OPPO for children aged 0-12 in China.\nAsk for a lot of permissions. Has a lot of security issues:\nhttps://beta.pithus.org/report/e006d8b22e473e603ceb86c654889e08da460b73d609cd9b17642f49d530239a", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.oplus.ovoicemanager.wakeup": { + "list": "Oem", + "description": "Voice Assistant related. A component for com.oplus.ovoicemanager.\nhttps://www.apkmirror.com/apk/oneplus-ltd/ovoicemanagerskillservice-2/ovoicemanagerskillservice-1-1-13-release/ovoicemanagerskillservice-1-1-13-android-apk-download/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.knox.er": { + "list": "Oem", + "description": "Knox ER component. Part of Samsung Knox enterprise features; safe to remove only if you do not use Knox/enterprise functionality.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.knox.kfbp": { + "list": "Oem", + "description": "Knox Frame Buffer Provider. Provides graphics buffer services for Knox UI/containers.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.knox.knnr": { + "list": "Oem", + "description": "Knox Neural Network Runtime. ML runtime used by some Knox/enterprise features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.knox.sandbox": { + "list": "Oem", + "description": "Knox Sandbox. Isolation/sandboxing support for Knox secure environments.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.app.vex.scanner": { + "list": "Oem", + "description": "Document Scanner. Samsung's VEX document scanning component used by Camera/Gallery/Office features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.motionphoto.app": { + "list": "Oem", + "description": "Motion Photo. Enables capture/view of motion photos (short video with still photo) in Samsung Camera/Gallery.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.partnerbrowsercustomizations.example": { + "list": "Oem", + "description": "This hidden Chinese/Romanian adware changes Google Chrome's home page, it varies by manufacturers.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sprd.systemupdate": { + "list": "Oem", + "description": "Another update app by Zhantang, this one seems to provide updates unlike other app com.redstone.ota.ui, which is a dropper. Removing it after your update support ends is probably the safest option.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sencatech.iwawa.iwawahome": { + "list": "Misc", + "description": "Pre-installed parental control bloatware with ads. (https://play.google.com/store/apps/details?id=com.sencatech.iwawa.iwawahome)", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.flipkart.android": { + "list": "Misc", + "description": "Pre-installed Indian shopping bloatware with ads. (https://play.google.com/store/apps/details?id=com.flipkart.android)", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.example.test": { + "list": "Oem", + "description": "Bigme HiBreak Pro calendar optimized for e-ink displays.\nCheck that you have this phone before disabling! The package name is generic.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.test.logcollect": { + "list": "Oem", + "description": "Bigme HiBreak Pro app to submit log reports when user requests it. Uploads Android and kernel logs to a Chinese cloud (Baidu). If uninstalled, Log Report button in the settings will not open a pop-up.\nCheck that you have this phone before disabling! The package name is generic.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sohu.inputmethod.sogou.oem": { + "list": "Oem", + "description": "Keyboard app used in some Chinese phones. There is a report that this keyboard might have contained security vulnerabilities in the past: https://citizenlab.ca/2024/04/vulnerabilities-across-keyboard-apps-reveal-keystrokes-to-network-eavesdroppers/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xsyt.faceregister": { + "list": "Oem", + "description": "Bigme HiBreak Pro app to unlock the phone with your face.\nThis app frequently connected to lp.xl-ads.com in the past, which caused security concerns on Reddit in relation to the BadBox 2.0 botnet and Bigme to issue a firmware upgrade that changes the usage of that domain.\nIf disabled, face unlock won't work and the option to activate it in the settings will crash Bigme's settings app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.xrz.ai": { + "list": "Oem", + "description": "Wrapper around ChatGPT used on Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.dictapp": { + "list": "Oem", + "description": "Dictionary provided on the Bigme HiBreak Pro (XDict). Requires to download the dictionaries manually in the app's settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.b300.xrz.web": { + "list": "Oem", + "description": "App called XRZWebExport on the Bigme HiBreak Pro. Does not show up in the app list when enabled.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.soundrecord": { + "list": "Oem", + "description": "Voice Recorder app on the Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.voice.text": { + "list": "Oem", + "description": "Bigme HiBreak Pro app that doesn't show up in the app list. Likely used as voice to text application. Installed as the DaWoYuJi.apk.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.scandoc": { + "list": "Oem", + "description": "Document scan app on the Bigme HiBreak Pro. Does not show up in the app list.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.video": { + "list": "Oem", + "description": "Video player of the Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.bookmall": { + "list": "Oem", + "description": "Chinese book store on the Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.bookself": { + "list": "Oem", + "description": "App that collects epub files and other documents to read on the Bigme HiBreak Pro.\nCan work together with xReader to act as a libary.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.xreaderV3": { + "list": "Oem", + "description": "eBook reader app used on the Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.btranslate": { + "list": "Oem", + "description": "Translator on the Bigme HiBreak Pro.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.xrz.ebook": { + "list": "Oem", + "description": "xReader, used by Bigme HiBreak Pro. In the state of my phone, this app crashes and does not provide useful functionality.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.ebook.wifitransferbook": { + "list": "Oem", + "description": "Allows to transfer files on the Bigme HiBreak Pro via Wi-Fi by exposing a web interface on the local network that you can access from another device on the same network.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.iflytek.speechcloud": { + "list": "Oem", + "description": "App called OfflineTTs on the Bigme HiBreak Pro. Does not show up in the app list.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sprd": { + "list": "Oem", + "description": "Unisoc's hidden aging test. Uninstalling it doesn't seem to break anything for Android 10 GO, S21 Plus 2021_EEA.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.spreadtrum.csvt": { + "list": "Oem", + "description": "potentially riskware, (sends information to another infamously hacked apk com.redstone.ota.ui).\n However it seems to work for handling 3G mobile data(and all broadcasts over 3G)\n It should not be removed if your provider/government works over 3G, any emergency message might fail.\n it is also a SOC, so removing ought to be careful.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.unisoc.keyboxchecker": { + "list": "Oem", + "description": "Unknown purpose, likely spyware. Can't be pulled with ADB. Uninstalling it doesn't seem to break anything for Android 10 GO, S21 Plus 2021_EEA.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.unisoc.storageclearmanager": { + "list": "Oem", + "description": "StorageClearManager\nUninstalling it doesn't seem to break anything for Android 10 GO, S21 Plus 2021_EEA.\nhttps://www.virustotal.com/gui/file/478e3ac5a3f7a69b73ae34d58ac246507deb0fdec439f9f5f6c7a2b28d450ae0", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.apps.photosgo": { + "list": "Google", + "description": "Google Gallery (https://play.google.com/store/apps/details?id=com.google.android.apps.photosgo)", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sprd.powersavemodelauncher": { + "list": "Oem", + "description": "PowerSaveModeLauncher\nUnisoc's default home app/launcher for Ultra saving mode connects to the internet. May oddly appear as disabled to UADng and NetGuard.\nhttps://www.virustotal.com/gui/file/787a4de0bc440c62bde9bf913c6f9ba188307d850e1ee6fb575ad62950cfbdc1", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.samsung.android.app.sketchbook": { + "list": "Oem", + "description": "Drawing Assistant\nThis is an useless AI extension for Samsung Keyboard. It keeps a notification dot on the emoji button.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.mydevice": { + "list": "Oem", + "description": "This app shows your devices on the QuickPanel.\nhttps://galaxystore.samsung.com/prepost/000008084719?appId=com.samsung.android.mydevice", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "ca.bell.selfserve.mybellmobile": { + "list": "Carrier", + "description": "Bell's 'award winning' (no source) app for managing your Bell account and services. Useless, especially if you don't use Bell. (https://play.google.com/store/apps/details?id=ca.bell.selfserve.mybellmobile). Note that Bell violates section F.1 of the Canadian Wireless Code by selling locked devices. If you use Bell, switch carriers if possible! Don't support lawbreaking companies.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.quickplay.android.bellmediaplayer": { + "list": "Carrier", + "description": "App for watching your Bell Fibe TV on the go. Useless, especially if you don't use Bell. (https://play.google.com/store/apps/details?id=com.quickplay.android.bellmediaplayer). Note that Bell violates section F.1 of the Canadian Wireless Code by selling locked devices. If you use Bell, switch carriers if possible! Don't support lawbreaking companies.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.opencalendar": { + "list": "Oem", + "description": "Samsung Subscription Calendars.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.systemui.hidenotch": { + "list": "Oem", + "description": "Hide notch overlay.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.systemui.hidenotch.withoutcornerround": { + "list": "Oem", + "description": "Hide notch overlay without corner round.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.QRreader": { + "list": "Oem", + "description": "Samsung QR code reader.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.UsimRegistrationKOR": { + "list": "Oem", + "description": "USIM Registration.\nThis app is used to register your USIM card in South Korea.\nIt is not needed outside of South Korea.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.biometrics.service": { + "list": "Oem", + "description": "Intelligent Scan for Samsung Galaxy S9(+) and Note 9.\nNOTE: Removing this will break Intelligent Scan.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.overlay.iconrecentsconfig": { + "list": "Oem", + "description": "A completely useless 0 bytes app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.overlay.wallpaperconfig": { + "list": "Oem", + "description": "A completely useless 0 bytes app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.settings.overlay.oversea": { + "list": "Oem", + "description": "A completely useless 0 bytes app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.overlay.gmsagoconfig": { + "list": "Oem", + "description": "A completely useless 0 bytes app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hancom.office.editor": { + "list": "Oem", + "description": "Proprietary office suite, primarly targeted towards Korean users. This version, typically preinstalled on old Samsung devices, is no longer maintained", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.app.appupdater": { + "list": "Oem", + "description": "Discontinued app to update Samsung's proprietary apps.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.overlay.gmsgoconfig": { + "list": "Oem", + "description": "A completely useless 0 bytes app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.nousguide.android.rbtv": { + "list": "Misc", + "description": "Red Bull TV\nA 1 star streaming service owned by a company that sells electronic cigars and energy drinks to the youth. Can be uninstalled via Settings.\nhttps://play.google.com/store/apps/details?id=com.nousguide.android.rbtv", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.davincikids.tv": { + "list": "Misc", + "description": "Davinci Media\nA 2 star streaming service.\nhttps://play.google.com/store/apps/details?id=com.davincikids.tv", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.artorial.client": { + "list": "Oem", + "description": "SmartArt\nProvides AI slop wallpapers, mobile games and news to Blackview devices. Can be disabled via Settings.\nhttps://www.blackview.hk/privacy\nhttps://www.virustotal.com/gui/file-analysis/YTg5NWU0ZTVkNzFiMDk4NjliZjdlNWQ0NjNjNDk5Yjk6MTc2MjAwNTk1OA==", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.weather": { + "list": "Oem", + "description": "Weather\nBlackview's weather app. Can be disabled via Settings.\nhttps://www.blackview.hk/privacy", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.userfeedback": { + "list": "Oem", + "description": "User feedback\nRequires agreeing to a Privacy Policy (that allows Blackview to sell your location to data brokers) to send feedback to Blackview. Can be disabled via Settings.\nhttps://www.blackview.hk/privacy\nhttps://www.virustotal.com/gui/file-analysis/NWNjODQ4OWEwZjU5MzkzZTFmN2MxNjkwMzcyZTExNjc6MTc2MjAwNzkxNQ==", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.launcher": { + "list": "Oem", + "description": "BvLauncher\nBlackview's launcher app.\nDON'T REMOVE IF YOU HAVEN'T INSTALLED ANOTHER LAUNCHER!\nhttps://www.blackview.hk/privacy", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.tripledot.triple.tile.match.pair.game.three.master.object": { + "list": "Misc", + "description": "Triple Tile\nPre-installed mobile game with ads and in-app purchases up to 129.99 USD. Can be disabled via Settings.\nhttps://play.google.com/store/apps/details?id=com.tripledot.triple.tile.match.pair.game.three.master.object", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.apps.speechservices": { + "list": "Google", + "description": "Google Speech Services\nAbsolute garbage. There is already another speech recognition app (Speech Recognition and Synthesis from Google), so this app is just spyware, judging by the URLs it connects to.\nhttps://www.virustotal.com/gui/file/9340b2aa1cb6f3fab3481a4bd5c0dacae2441bbb0849691b08a6e8bcedae2662/details", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.app.scrollcapture": { + "list": "Oem", + "description": "Samsung's app for taking screenshots.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.android.sprd.telephony.server": { + "list": "Oem", + "description": "Unknown purpose, likely spyware. Uninstalling it doesn't seem to break anything for Android 10 GO, S21 Plus 2021_EEA.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.authservice": { + "list": "Oem", + "description": "Runs in the background on Galaxy S7 and earlier, can't seem to find a purpose for this app. No issues when removing it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.radiobasedlocation": { + "list": "Oem", + "description": "Tracks location in the background. Doesn't seem to be needed for anything.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.radiobasedlocation.manager": { + "list": "Oem", + "description": "Tracks location in the background. Doesn't seem to be needed for anything.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.tzdata.update": { + "list": "Oem", + "description": "App for updating time zone changes on Samsung devices. Now discontinued and completely useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.videolist": { + "list": "Oem", + "description": "Video player included on Samsung devices (https://play.google.com/store/apps/details?id=com.samsung.android.videolist). Works fine enough as a basic video player.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.tmowfc.wfccontroller": { + "list": "Oem", + "description": "Wifi Calling for T-mobile clients only! (tmowfc = t-mobile only wifi calling)\nLets you call or text on Wi-Fi networks with your T-Mobile phone number\nhttps://www.t-mobile.com/support/coverage/wi-fi-calling-from-t-mobile\nVoLTE/IMS is needed for this to work (see com.sec.imsservice)\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.camera.plb": { + "list": "Oem", + "description": "Looks like an app to record videos for Facebook. Despite having 'camera' in the name, it is not needed for the camera at all.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.clipvideo": { + "list": "Oem", + "description": "App to create a video collage.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.easylauncher": { + "list": "Oem", + "description": "TouchWiz easy home -- gives you large icons and makes things the home screen significantly simpler. Primarly designed for elderly users. Discontinued after the release of Samsung Experience in 2017.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.music": { + "list": "Oem", + "description": "Samsung's proprietary music app, allows you to play local music or connect your Spotify account (https://play.google.com/store/apps/details?id=com.sec.android.app.music). Safe to uninstall, and there's much better open source alternatives for both local music and Spotify.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.spen.flashannotate": { + "list": "Oem", + "description": "Take notes on your screen. Unneeded, and can't even be accessed unless you're using a Galaxy Note or S Ultra, despite being preinstalled on all Samsungs.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.telus.featuredapps": { + "list": "Carrier", + "description": "Recommended apps from Telus. Now discontinued and doesn't show any apps.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "service.odtcfactory.sec.com.odtcfactoryservice": { + "list": "Oem", + "description": "Purpose of this app is completely unknown, but it eats battery and data and is safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.uncube.launcher3": { + "list": "Oem", + "description": "Torque Launcher\nDefault launcher for BlueStacks. Has ads.\nDON'T REMOVE IF YOU HAVEN'T INSTALLED ANOTHER LAUNCHER!\nhttps://play.google.com/store/apps/details?id=com.uncube.launcher3&hl=en-US", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.htc.blackviewhome": { + "list": "Oem", + "description": "BV Family\nBlackiew's application for access to their store, website, feedback and other things. Can track like a browser.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "org.lineageos.waydroidupdater": { + "list": "Oem", + "description": "Waydroid Updater\nhttps://www.virustotal.com/gui/file/543f8eb038c052c4a00a6f3fdda026f2cec327a435c81f62d8738412c748510b/details", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.blackview.surfline": { + "list": "Oem", + "description": "Surfline\nBackview's Safari ripoff with ads. They didn't even bother to remove Chrome, probably because they knew you won't use it. Can be disabled via Settings.\nhttps://www.blackview.hk/privacy", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.filetrans": { + "list": "Oem", + "description": "Moving Assistant/Data Migration Assistant\nApp used to transfer data from one device to another.\nWARNING: Uninstalling it breaks the App info Settings page on Android 15, Blackview Tab 60 WiFi.\nTry disabling instead of uninstalling in case that happens.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.blackview.dokegamecenter": { + "list": "Oem", + "description": "DKGame Center", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.ai.vidgen": { + "list": "Oem", + "description": "VidGen", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.ai.doki": { + "list": "Oem", + "description": "Hi Doki", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.ai.imagex": { + "list": "Oem", + "description": "ImageX", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.ai.soundle": { + "list": "Oem", + "description": "Soundle", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "bnd.com": { + "list": "Oem", + "description": "Hardware Check\nWARNING: Uninstalling it breaks the App info Settings page on Android 15, Blackview Tab 60 WiFi. It has an internet permission and can install other apps in the background, which means it's a backdoor! Please remove its permissions, block its internet access using NetGuard or check if uninstalling it breaks anything related to the Settings app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.blackview.appsedge": { + "list": "Oem", + "description": "AppsEdge", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.note": { + "list": "Oem", + "description": "Notebook", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sprd.runtime": { + "list": "Oem", + "description": "RuntimeTest", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.gamemode": { + "list": "Oem", + "description": "Game mode", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.cplog": { + "list": "Oem", + "description": "cplog", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.clock.pt1.keeptesting": { + "list": "Oem", + "description": "KeepTesting2.9.42\nWARNING: Each boot, the system randomly decides whether to perform checks or not. If a check is attempted while the app is missing, the device won't boot past the OEM's logo until restart. Teseted for Android 15, Blackview Tab 60 WiFi.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.blackview.useguide": { + "list": "Oem", + "description": "User's Manual", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.easytrans": { + "list": "Oem", + "description": "EasyShare", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.frozenapp": { + "list": "Oem", + "description": "Cold Room", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "lineageos.platform": { + "list": "Oem", + "description": "LineageOS System", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.kddi.android.cmail": { + "list": "Carrier", + "description": "+Message\nA Japanese messaging and e-mail app.\nhttps://play.google.com/store/apps/details?id=com.kddi.android.cmail", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.miui.carrierinstructions": { + "list": "Carrier", + "description": "Manual\nShortcut to the carrier's online manual.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.aura.oobe.kddi": { + "list": "Carrier", + "description": "AppCloud\nSeems to exist to try to get you to download games and another testimonial.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.android.provision.carrieroverlay.kddi": { + "list": "Carrier", + "description": "Useless Japanese overlay app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.A12.d01.wallpapermulti": { + "list": "Oem", + "description": "Default Multiple Wallpaper Resource\nA 0 bytes overlay app for Samsung Galaxy A12, you can tell by its package name. Uninstalling it doesn't break the wallpaper slide show on the lock screen. Can be disabled via Settings.\nhttps://www.virustotal.com/gui/file/c5c5e173ccd3b515ec8684cc1c0d3d625ff57fe97a381b691596747225f2403d/details", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.wifi.sbs.resources": { + "list": "Oem", + "description": "WifiRROverlayAppSBS\nhttps://www.virustotal.com/gui/file/94140aa1e8e581bbdfbec9a31b983672d05cb1fda255e3155e3cb85cb5140bad/details", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.blackview.app.cloudfolder": { + "list": "Oem", + "description": "Rec. Apps\nThis adware provides a widget that allows you to install sponsored apps like Temu. Can be disabled via Settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.apps.aiwallpapers": { + "list": "Google", + "description": "Provides the ability to create wallpapers by using AI and several presets.\nNot sure how this can be useful to the average user + collects device info.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.searchcenter": { + "list": "Oem", + "description": "Search Centre\nCan be disabled via Settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.macropinch.swan": { + "list": "Misc", + "description": "Weather\nhttps://play.google.com/store/apps/details?id=com.macropinch.swan", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.digitalturbine.android.apps.news.att": { + "list": "Carrier", + "description": "Essentials\nThis application results in fullscreen advertisements upon unlocking the device.\nhttps://play.google.com/store/apps/details?id=com.digitalturbine.android.apps.news.att&hl=en_US\nhttps://www.virustotal.com/gui/file/a7625586ea2d21efcb76b528c5ad66c9cf77e74a52029cabcd415deff5b5107d/details\nhttps://reports.exodus-privacy.eu.org/en/reports/com.digitalturbine.android.apps.news.att/latest/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.dot.app.sancharsaathi": { + "list": "Carrier", + "description": "Spyware billed as citizen-centric safety tool that is required by Goverment of India be pre-installed.\nhttps://www.reuters.com/sustainability/boards-policy-regulation/what-is-indias-politically-contentious-sanchar-saathi-cyber-safety-app-2025-12-02", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.taboola.mip": { + "list": "Misc", + "description": "Intrusive background module (Taboola) that keeps pushing a lock-screen stories feed — spam-ads and irrelevant articles (often from foreign/hostile sources).\nRuns in background, uses data, nags user until it is enabled. No system function — safe to remove.\nhttps://techissuestoday.com/motorola-lock-screen-ads-articles/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.android.frameworks.telresources": { + "list": "Misc", + "description": "Completely empty package. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.crucialsoft.asm": { + "list": "Oem", + "description": "Doesn't seem to do anything, but has permissions to read and write storage. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.crucialsoft.fido.client": { + "list": "Oem", + "description": "Does absolutely nothing. Despite the package name saying 'Fido', it is unrelated to Fido, it is an LG package. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.crucialtec.uaf": { + "list": "Oem", + "description": "Claims to be related to the fingerprint sensor and has fingerprint permissions. Fingerprint sensor still works fine with it removed, however.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.evernote.promohelper": { + "list": "Misc", + "description": "Companion for the Evernote app, seems to drain battery.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.ipsec.service": { + "list": "Oem", + "description": "Has internet access and does nothing. Possibly for an IPSec service and dependency of the LG VPN? Not really sure.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.ipsec.vpnclient": { + "list": "Oem", + "description": "LG VPN. Doesn't seem to affect VPN functionality, and LG doesn't run a VPN, afaik.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge": { + "list": "Oem", + "description": "Main LG system framework. Do not remove, will bootloop your device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.lge.autosimlockservice": { + "list": "Oem", + "description": "Has reboot permissions and can check when SIM state is changed. Possibly used for carrier locking devices? No issues when removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.cota.blm.sf340_enabler": { + "list": "Oem", + "description": "I can't find any purpose for this app. Titled 'LG Conference Call Update', 'sf340' is part of the codename for the LG Stylo 3 Plus (full codename is sf340n), likely related to some discontinued LG service designed specifically for the Stylo 3 Plus.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.drive.activator": { + "list": "Oem", + "description": "This app used to give you a free 100GB Google Drive storage for 5 years after buying an LG phone, however, Google no longer does this offer, and the app just gives an error now.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.gba.android": { + "list": "Oem", + "description": "Needed for proper VoLTE functionality on LG devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.lge.hiddenmenu": { + "list": "Oem", + "description": "Hidden testing menu on LG devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.hiddenpersomenu": { + "list": "Oem", + "description": "Used to unlock LG phones remotely, from carriers like Sprint.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.lge.inputdevices": { + "list": "Oem", + "description": "Completely empty package. Safe to remove", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.ipprovider": { + "list": "Oem", + "description": "Completely empty package. Safe to remove", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.ipservice": { + "list": "Oem", + "description": "Needed for Wi-Fi calling on LG T-Mobile devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.lge.shutdownmonitor": { + "list": "Oem", + "description": "Shows the shut down animation when powering off or rebooting LG devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.lge.sizechangable.musicwidget.widget": { + "list": "Oem", + "description": "LG Music widget. There are much better music apps available.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.themesquare": { + "list": "Oem", + "description": "Change the theme on LG UX.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.lge.wificall": { + "list": "Oem", + "description": "Needed for Wi-Fi Calling on LG devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.phasebeamorange": { + "list": "Aosp", + "description": "\"Sun Beam\" live wallpaper. Just Phase Beam but orange.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.apps.gcs": { + "list": "Google", + "description": "Internet services for Pixel and Nexus devices, including Wi-Fi/Mobile data switching, enabling a Google VPN on public networks, and Call Casting for Chromebooks. https://play.google.com/store/apps/details?id=com.google.android.apps.gcs", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.google.android.apps.genie.geniewidget": { + "list": "Google", + "description": "News and weather widget. App was discontinued in 2018 and no longer works, therefore there is no point to have it anymore.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.google.android.gm.exchange": { + "list": "Google", + "description": "Microsoft Exchange ActiveSync support for Gmail. Now part of the Gmail (com.google.android.gm) app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.SprintHiddenMenu": { + "list": "Carrier", + "description": "Hidden diagnostic menu for Sprint LG devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lge.update": { + "list": "Oem", + "description": "LG Update Center for updating your LG device. LG's OTA server shut down on June 30, 2025, so this app now has no purpose.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.redbend.vdmc": { + "list": "Oem", + "description": "Required for OTA on older LG and HTC devices. While neither of these companies make phones anymore, uninstalling this package results in \"vDM Client has stopped unexpectly\" and \"com.process.android.acore has stopped\", so best to leave this installed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.fivemobile.myaccount": { + "list": "Carrier", + "description": "App for managing your Rogers account.\nRogers violates section F.1 of Canada's Wireless Code, they refuse to unlock devices sold before December 1, 2017, even if it doesn't affect you, don't support practices like this! Switch to another carrier (such as Telus) if possible.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.nhl.gcl.canada": { + "list": "Carrier", + "description": "Rogers NHL app. Just opens a 404 page in the web browser. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.rogers.npd.appzone": { + "list": "Carrier", + "description": "An app store just for Rogers bloat. Why the hell would you want this?", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.communitake.remotecontrolservice": { + "list": "Carrier", + "description": "Remote management app installed by Bell on some devices. Has access to almost every permission so probably best to remove this.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.epson.mobilephone.samsungprintservice": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.fixmo.isa": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.fmm.dm": { + "list": "Oem", + "description": "Samsung's Find My Mobile service for tracking your phone if you lost it. Unsure of the difference(s) between this and com.fmm.ds. Can lead to logcat spam in some cases.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.fmm.ds": { + "list": "Oem", + "description": "Samsung's Find My Mobile service for tracking your phone if you lost it. Unsure of the difference(s) between this and com.fmm.dm, however this one doesn't logcat spam unlike com.fmm.dm.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hp.android.printservice": { + "list": "Misc", + "description": "Print to your HP printer using your Android phone. Most reviews on Google Play say it doesn't work very well. https://play.google.com/store/apps/details?id=com.hp.android.printservice", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.infraware.polarisviewer5": { + "list": "Oem", + "description": "A dumbed down version of Polaris Office Editor 5 (which is a Microsoft Office like app).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.lifevibes.trimapp": { + "list": "Oem", + "description": "Video trimmer used by the default Samsung Gallery app on some older Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.LocalFota": { + "list": "Oem", + "description": "Required to install OTA updates on older Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.qualcomm.interfacepermissions": { + "list": "Misc", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.app.headlines": { + "list": "Oem", + "description": "Flipboard app for Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.app.shareaccessibilitysettings": { + "list": "Oem", + "description": "Seems to be like a package for saving your accessibility settings, likely to transfer them to another phone.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.intelligenceservice": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.proxy.calendar": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.proxy.contacts": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.proxy.memo": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.proxy.sbrowser": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.proxy.snote3": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.scloud.quota": { + "list": "Oem", + "description": "Literally all this app does is tell you when you're out of storage on your Samsung Cloud. Why this isn't part of the main Samsung Cloud app? I have no idea.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.app.video": { + "list": "Oem", + "description": "Can't figure out what this package does, but no adverse effects to removing it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.everglades.video": { + "list": "Oem", + "description": "Part of the TouchWiz video player.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.pickuptutorial": { + "list": "Oem", + "description": "A guide to some gestures on Samsung devices, however it doesn't seem to be accessable anywhere. Maybe intended for demo units?", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.allshare.service.controlshare": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.allshare.service.fileshare": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.allshare.service.mediashare": { + "list": "Oem", + "description": "Share media to your other Samsung devices with Allshare. Allshare is discontinued and no longer present on modern Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.FileShareClient": { + "list": "Oem", + "description": "Receive files from Samsung devices with Allshare. Allshare is discontinued and no longer present on modern Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.FileShareServer": { + "list": "Oem", + "description": "Send files to Samsung devices with Allshare. Allshare is discontinued and no longer present on modern Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.filtermanager": { + "list": "Oem", + "description": "Manage camera filters on your Samsung device.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.interactivekeyguardtutorial": { + "list": "Oem", + "description": "A guide on how to unlock your phones screen, however it doesn't seem to be present anywhere on the phone. Maybe intended for demo units?", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.mediasync": { + "list": "Oem", + "description": "Share music for group play.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.mobileprint": { + "list": "Oem", + "description": "Samsung print service for supported printers.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.mv.player": { + "list": "Oem", + "description": "Share videos to other devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.rakein": { + "list": "Oem", + "description": "Completely empty package. Useless", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.sbrowsertry": { + "list": "Oem", + "description": "Samsung Internet browser, there are much better browsers available and Samsung Internet has a really sketchy privacy policy.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.app.SmartClipService": { + "list": "Oem", + "description": "Default image editor on older Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.videoplayer": { + "list": "Oem", + "description": "TouchWiz video player.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.wluc": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.cloudagent": { + "list": "Oem", + "description": "Part of Dropbox integration on TouchWiz", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.cloudagent.dropboxoobe": { + "list": "Oem", + "description": "Get a free 50GB Dropbox account with your Samsung device! Would be useful, but Dropbox ended this offer about 10 years ago.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.directshare": { + "list": "Oem", + "description": "Part of Samsung's SBeam service. SBeam has known security vulnerabilities (https://labs.withsecure.com/advisories/samsung-s5-arbitary-file-retrieval-during-sbeam-transfer), so you should really uninstall this.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.easysettings": { + "list": "Oem", + "description": "Settings app if you're using the Easy Mode feature on Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.fotaclient": { + "list": "Oem", + "description": "OTA for legacy Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.fwupgrade": { + "list": "Oem", + "description": "Updates AllShare components. Since Samsung AllShare is discontinued, this is now useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.Kies": { + "list": "Oem", + "description": "Required for connecting your device to Samsung Kies, Samsung's long discontinued iTunes competitor. Everything that can be done with Kies can be done with ADB or Heimdall, so there isn't really a point to keeping this.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.mmapp": { + "list": "Oem", + "description": "Required for Samsung's proprietary music app to work.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.nearby.mediaserver": { + "list": "Oem", + "description": "Samsung nearby share, part of AllShare. Discontinued.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.SamsungDrmProvider": { + "list": "Oem", + "description": "Completely empty package. Useless. Content with DRM still works without this package.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.service.bezel": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.service.cm": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.voltesettings": { + "list": "Oem", + "description": "Needed for VoLTE to function properly, which is a feature a lot of carriers now require.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.sec.android.wfds.printplugin": { + "list": "Oem", + "description": "Needed for Wi-Fi direct printing on Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.widget.samsungapps": { + "list": "Oem", + "description": "Widget for Galaxy Apps, showing app suggestions on your home screen.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.android.widgetapp.activeapplicationwidget": { + "list": "Oem", + "description": "Completely empty package. Useless", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.dsm.phone": { + "list": "Oem", + "description": "Completely empty package. Useless", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.dsm.system": { + "list": "Oem", + "description": "Part of Samsung's Find my Mobile service, appears this app is so you can ring your phone if you lost it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.knox.seandroid": { + "list": "Oem", + "description": "Samsung Knox security features. Can't be disabled or uninstalled without root.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.pcw.device": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.providers.settingsearch": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.sec.setdefaultlauncher": { + "list": "Oem", + "description": "Completely empty package. Useless. You can still change launchers without this package.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.siso.app.generic": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.siso.app.genericprintservice": { + "list": "Oem", + "description": "Completely empty package. Useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.telenav.app.android.bell": { + "list": "Carrier", + "description": "Bell Navigator app. It works, but there are much better Maps apps available. https://play.google.com/store/apps/details?id=com.telenav.app.android.bell", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.apple.atve.androidtv.appletv": { + "list": "Oem", + "description": "Apple TV\nFactory-installed Apple TV app. Reverts to factory-version when uninstalled by normal means.\n(Shipped with Philips Android TVs, but may be present on other devices as well.)\nhttps://play.google.com/store/apps/details?id=com.apple.atve.androidtv.appletv", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.android.networkstack.tethering.inprocess": { + "list": "Oem", + "description": "Causes a lockscreen loop on some Xiaomi devices. Provides TetherableWifiRegexs, the lack of which crashes systemui and miui.home.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.samsung.android.a20.d01.wallpapermulti": { + "list": "Oem", + "description": "Seems like a completely useless empty package, but the default lock screen wallpaper slideshow stops working if you uninstall this. Wallpapers can still be set fine, so it's still pretty useless.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.timezone.data_R": { + "list": "Oem", + "description": "Causes bootloop on any Samsung Galaxy A50 when removed. \n Rescue Party will be triggered, package manager service will fail to start. \n Device becomes unbootable. Do NOT remove on older Samsung devices.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.sec.android.usermanual": { + "list": "Oem", + "description": "Opens the device’s built‑in user manual PDF", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.a50.d01.wallpapermulti": { + "list": "Oem", + "description": "Provides the wallpapers used by the lockscreen multi-pack feature", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.SMT.lang_es_mx_f00": { + "list": "Oem", + "description": "Voice pack for Samsung TTS in Spanish (Mexico).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.SMT.lang_pt_br_f00": { + "list": "Oem", + "description": "Voice pack for Samsung TTS in Portuguese (Brazil).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.SMT.lang_en_us_f00": { + "list": "Oem", + "description": "Voice pack for Samsung TTS in English (United States).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.internal.overlay.config.default_contextual_search": { + "list": "Oem", + "description": "The code only assigns (com.google.android.googlequicksearchbox) as the default contextual search package via (config_defaultContextualSearchPackageName).\nI suppose that if (com.google.android.googlequicksearchbox) is removed, this feature stops working.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.drmboost": { + "list": "Oem", + "description": "Boosts CPU performance during secure DRM (Digital Rights Management) playback by monitoring codec activity and applying a DVFS (Dynamic Voltage and Frequency Scaling) hint (1400).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.nfc.resources.default": { + "list": "Oem", + "description": "Provides default NFC configuration resources (booleans and polling delays). Contains no executable code.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.privateaccesstokens": { + "list": "Oem", + "description": "Provides a system module used by Samsung Internet for an automatic verification feature on compatible websites to skip CAPTCHAs.\nOn my device the option never appeared. Removing it does not affect normal system functionality.\nIt relies on a few privileged permissions such as READ_PRIVILEGED_PHONE_STATE , SAMSUNG_KEYSTORE_PERMISSION , ACCESS_KEYGUARD_SECURE_STORAGE , and INTERNET/ACCESS_NETWORK_STATE.\nhttps://apps.samsung.com/appquery/appDetail.as?appId=com.samsung.android.privateaccesstokens", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.accessory.budsunitemgr": { + "list": "Oem", + "description": "Provides the system component that manages Galaxy Buds features and configuration. It handles firmware updates, noise control modes (ANC / Ambient sound), touch controls, and all device‑specific settings.\nOn my device, uninstalling it removed the ability to update the Buds or use any of the features mentioned above.\nAccording to the Galaxy Store description, it also requires the Galaxy Wearable package (com.samsung.android.app.watchmanagerstub) to function.\nhttps://apps.samsung.com/appquery/appDetail.as?appId=com.samsung.accessory.budsunitemgr\nhttps://play.google.com/store/apps/details?id=com.samsung.accessory.budsunitemgr", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.mygalaxy.service": { + "list": "Oem", + "description": "Module likely used by the MyGalaxy app (https://play.google.com/store/apps/details?id=com.mygalaxy).\nOnly works on India CSC INS/INU. On all other regions it disables itself automatically.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "in.gov.uidai.pehchaan": { + "list": "Oem", + "description": "National ID app based on a unique 12 digit number and biometrics information. Privately mandated by Government of India to be pre-installed on devices.\nSource: https://www.reuters.com/world/china/indias-proposal-preload-national-id-app-aadhaar-phones-faced-pushback-2026-03-19/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.launcher": { + "list": "Oem", + "description": "Honor launcher app.\nIt's basically the home screen, the way icons apps are organized and displayed.\nDON'T REMOVE THIS IF YOU DIDN'T INSTALL ANOTHER LAUNCHER !\nYou will need this package for the recent apps feature to work, and will completely break the gestural navigation bar.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.calendar": { + "list": "Oem", + "description": "Honor's calendar app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.photos": { + "list": "Oem", + "description": "Honor's photos app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.lens": { + "list": "Oem", + "description": "App kinda like Google Lens, used for scanning QR Codes and more.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.appmarket": { + "list": "Oem", + "description": "HONOR's App store.\nSafe to remove.\nNOTE: Installed apps via this store will no longer auto-update after removal.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.phoneservice": { + "list": "Oem", + "description": "My Honor.\nhttps://play.google.com/store/apps/details?id=com.hihonor.phoneservice&hl=fr", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.notepad": { + "list": "Oem", + "description": "Honor's notepad app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.filemanager": { + "list": "Oem", + "description": "Honor's file manager.\nIt is not the system one so it's safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.calculator": { + "list": "Oem", + "description": "Honor's calculator app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.contacts": { + "list": "Oem", + "description": "Honor's contacts app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.videoeditor": { + "list": "Oem", + "description": "Honor's video editing app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.magazine": { + "list": "Oem", + "description": "Magic Pictorial/Magazine unlock.\nSafe to remove if you're not using it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.thememanager": { + "list": "Oem", + "description": "Honor's Theme manager.\nDisabling it will prevent you from changing themes.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.search": { + "list": "Oem", + "description": "HONOR Search.\nhttps://www.honor.com/sa-en/support/content/en-us15829481/\nSafe to remove if you're not using it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.collectcenter": { + "list": "Oem", + "description": "HONOR Favourites space.\nSafe to remove if you're not using it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.soundrecorder": { + "list": "Oem", + "description": "Honor's audio recording app.\nSafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.bluetooth": { + "list": "Oem", + "description": "Contact import via blueooth on Honor devices, probably safe to remove if you don't plan using this function.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.ouc": { + "list": "Oem", + "description": "OTA Updates for Honor devices. Probably unsafe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.mmitest": { + "list": "Oem", + "description": "MMITest\nHidden hardware tests. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.fmradio": { + "list": "Oem", + "description": "Honor's stock radio player. Remove if FM isn't relevant for you.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.keychain": { + "list": "Oem", + "description": "Face recognition and fingerprint authentication. Probably a bad idea to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.compass": { + "list": "Oem", + "description": "Honor's compass app. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.imedia.sws": { + "list": "Oem", + "description": "Audio 3D effects found in the settings. Safe to remove if you don't use these settings.\nCauses an audio glitch after the first reboot following the uninstallation or disabling of this package.\nWhen you start or resume playing any audio content in any media application, the sound volume initially sets to maximum for half a second, then normalizes.\nAffects only external audio devices with any connection type.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.hnasm": { + "list": "Oem", + "description": "FIDO UAF Authenticator-Specific Module.\nSee 'com.hihonor.fido.uafclient' for FIDO explaination.\nThe UAF Authenticator-Specific Module (ASM) is a software interface on top of UAF authenticators which gives a standardized way for FIDO UAF clients to detect and access the functionality of UAF authenticators and hides internal communication complexity from FIDO UAF Client.\nhttps://fidoalliance.org/specs/fido-uaf-v1.0-ps-20141208/fido-uaf-asm-api-v1.0-ps-20141208.html", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.fido.uafclient": { + "list": "Oem", + "description": "UAF client for FIDO.\nFido is a set of open technical specifications for mechanisms of authenticating users to online services that do not depend on passwords.\nhttps://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-glossary.html\nhttps://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-overview-v2.0-rd-20170927.html\nThe UAF protocol is designed to enable online services to offer passwordless and multi-factor security by allowing users to register their device to the online service and using a local authentication mechanism such as iris or fingerprint recognition.\nhttps://developers.google.com/identity/fido/android/native-apps\nSafe to remove if you don't use password-less authentication to access online services.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.dsdscardmanager": { + "list": "Oem", + "description": "Dual card management\nIt's sim card management in Honor settings.\nAfter removing, sim card management in settings will not work.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.gameassistant": { + "list": "Oem", + "description": "Honor Game Suite (HiGame).\nMobile game app store.\nhttps://club.hihonor.com/in/topic/16341/detail.htm\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.game.kitserver": { + "list": "Oem", + "description": "Probably safe to remove if you don't play games.\nHas window show, keybind set and more things.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.powergenie": { + "list": "Oem", + "description": "Task killer app in EMUI 9+ (Android 9+).\nTask killer apps tend to do more harm than help as they clear cached RAM for no good reason, removing the battery and time savings involved in caching. In addition to the obvious issues with background functionality like notifications.\nFrom issue#104.\nSystem will start lagging a little bit (you will notice it while scrolling and on some animations, for example scrolling installed apps), battery consumption will become slightly higher and battery stats will disappear soon. At the same time, logcat will be full of errors like: PowerKit: PG Server is not found. calling pid xxxx.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.hiviewtunnel": { + "list": "Oem", + "description": "This displays details/attributes of pictures in the gallery (ISO, exposure time, etc.).\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.hiview": { + "list": "Oem", + "description": "hiview\nRemoving this doesn't remove access to the picture attributes, so what does it actually do?\nIt's the same as (com.hihonor.hiviewtunnel), which is useless.\nIt has 19 permissions, Crash App Dialog, logs. So do not trust these apps.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.assetsync": { + "list": "Oem", + "description": "HnAssetSync\nNeeded for HiCloud, Cloud syncing.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.assetsyncservice": { + "list": "Oem", + "description": "It's for 'com.hihonor.securityserver' for start this service app.\nNeeded for HiCloud sync security.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.securityserver": { + "list": "Oem", + "description": "HnSecurityServer\nNot needed app without code and useless assets to spying apps.\nNeeded for face unlock, black screen will be shown if you remove this package (?). Doesn't apply to all devices", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.iaware": { + "list": "Oem", + "description": "App Prioritizer. Prioritizes apps to avoid slowdown\nUp to you but there is apparently no noticeable difference when deleted?\nSystem will start lagging a little bit (you will notice it while scrolling and on some animations, for example scrolling installed apps), battery consumption will become slightly higher and battery stats will disappear soon. At the same time, logcat will be full of errors like: PowerKit: PG Server is not found. calling pid xxxx.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.autoinstallapkfrommcc": { + "list": "Oem", + "description": "Auto Install apk from mcc\nAuto Install apk from mcc? it's only information and logs.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.omacp": { + "list": "Oem", + "description": "Provisioning message\nUsed for provisioning APN settings to devices via SMS. I think you shouldnt touch it if you want sms messages.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.motionservice": { + "list": "Oem", + "description": "Gesture Service\nNot very useful gestures available in settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.hndockbar": { + "list": "Oem", + "description": "Honor Multi-Window dock\nProbably fine to remove if you're not using Honor Multi-Window features.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.pcassistant": { + "list": "Oem", + "description": "HiSuite service. Used by HiSuite PC software.\nHiSuite enables you to backup your data and restore them from/to your phone.\nhttps://consumer.huawei.com/en/support/hisuite/\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.wifieapsimplmn": { + "list": "Oem", + "description": "PredefinedEapSim\nNeeded for WiFi to work properly? WiFi may not work (?)", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.android.mirrorshare": { + "list": "Oem", + "description": "MirrorShare feature (Miracast rebranded by Honor)\nUsed to mirror screen of you smartphone on a TV.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.projectmenu": { + "list": "Oem", + "description": "ProjectMenu\nHidden settings not available for users. ProjectMenu interface: phone *#*#2846579#*#*\nhttps://www.99mediasector.com/open-project-menu-huawei-device-huawei-code/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.remotepassword": { + "list": "Oem", + "description": "RemotePassword\nremotepassword: errors, invalid, null, errors generally\nalso subscribe info, device info. Better remove that.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.koBackup": { + "list": "Oem", + "description": "As of writing this, Honor phones cannot be rooted.\nThis Backup application is probably able to backup more than any other 3rd party backup app.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.iconnect": { + "list": "Oem", + "description": "iConnect\nHidden menu 'install PCAssistant' when connected to PC? I have never seen it. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.linktowindowsservice": { + "list": "Oem", + "description": "Windows Phone Link Service. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.systemserver": { + "list": "Oem", + "description": "Honor System Services\nIt depends on (com.hihonor.systemmanager).\nNeeded for navigation with a fingerprint reader that is on a Huawei Mate 10, but fingerprint unlock will still work if you remove it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.android.internal.app": { + "list": "Oem", + "description": "Component of Honor sharing\nMay break the sharing function in several applications (in particular, apps will crash).", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.synergy": { + "list": "Oem", + "description": "Honor Cloud & Network Synergy.\nSeems to be related to B2B (Business To Business) cloud stuff.\nhttps://www.huawei.com/en/press-events/news/2016/10/Cloud-Network-Synergy-Whitepaper\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.contacts.sync": { + "list": "Oem", + "description": "Huawei Contacts sync\nMy guess (can't have the apk on hand) is this enables you to synchronise your contacts with your Huawei account.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.deviceauth": { + "list": "Oem", + "description": "TrustedDeviceAuth\nI guess it's for authentication keys", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.android.FloatTasks": { + "list": "Oem", + "description": "Floating/Navigation dock (also called NaviDot).\nhttps://consumer.huawei.com/en/support/how-to/detail-troubleshooting/en-us00310067/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.wfdft": { + "list": "Oem", + "description": "Wi-Fi Direct feature.\nNote: Wifi direct enables devices to establish a direct Wi-Fi connection (without a router) over which the two can send and receive files.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.browserhomepage": { + "list": "Oem", + "description": "Honor Browser component.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.searchservice": { + "list": "Oem", + "description": "Fusion Search Service\nNeeded for searching? \nalso found trackers components that connects to Honor servers unnecessarily.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.assistant": { + "list": "Oem", + "description": "AI Suggestions\nDidn't find any issues when removing it.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.hnstartupguide": { + "list": "Oem", + "description": "A one-time setup app that is no longer needed", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.camera": { + "list": "Oem", + "description": "Safe to remove, but not recommended, as other camera apps are not much better than this one.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.HnMultiScreenShot": { + "list": "Oem", + "description": "Scrolling screenshot feature\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.smartshot": { + "list": "Oem", + "description": "Smart screenshots\nNeeded for screenshots.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.screenrecorder": { + "list": "Oem", + "description": "Stock screen recorder\nUseful only in pre-Android Pie for having system audio recording without root.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.permissioncontroller.overlay": { + "list": "Oem", + "description": "Found help app permissions - only link to Google site in code, overlay to permission things like buttons, dialogs, etc.\nBut it's not needed?", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.ddmp": { + "list": "Oem", + "description": "DDMP\nHas a lot frameworks.\nUninstalling breaks calling app even if you disable.\nIt does not cause bootloop but removing is highly not recommended.\nNot only breaks the dialer app, but causes lag in whole system too.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.detectrepair": { + "list": "Oem", + "description": "Honor Smart diagnosis (discontinued?)\nUseless features and run in background.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.hnaps": { + "list": "Oem", + "description": "HnAps\nManages Intelligent Resolution and changing screen resolution in settings.\nIntelligent Resolution will be not available and changing screen resolution in settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.behaviorauth": { + "list": "Oem", + "description": "BehaviorAuth\nIt seems to be related to verifying the authenticity of user behavior and enhancing password security. User can disable it so it's safe to remove.\nhttps://www.android-hilfe.de/forum/huawei-p30-p30-pro-p30-lite.3510/was-ist-die-behaviorauth-app-fuer-das-p30.1008750.html", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.chr": { + "list": "Oem", + "description": "HnChrService\nHonor Call History Record.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.coauthservice": { + "list": "Oem", + "description": "HnCoAuthService\nApplock, lockscreen password, face recognition things, fingerprint, not sure if it's worth removing it.\nNeeded for manual apk installation.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.nearby": { + "list": "Oem", + "description": "HnNearby\nNeeded for Honor Share features. (com.hihonor.android.instantshare)\nHonor Share features may not work after remove.\nNeeded to show a preview of recently opened apps in task manager. I agree, makes no sense, but that's what it is.", + "dependencies": [ + "com.hihonor.android.instantshare" + ], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.hnpanpayservice": { + "list": "Oem", + "description": "Payment related service. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.securitypluginbase": { + "list": "Oem", + "description": "HnSecurityPluginBase\nAntivirus Service supports bad antiviruses, HnLog, not needed", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.hnupgradeguide": { + "list": "Oem", + "description": "hnupgradeguide\nit's guide menu at first start Honor App Market.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.android.instantshare": { + "list": "Oem", + "description": "Honor Share features.\nFile transfer tool between Honor mobiles, using Bluetooth connection and WiFi Direct technology.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.numberidentity": { + "list": "Oem", + "description": "Designed to block unwanted calls.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.deskclock": { + "list": "Oem", + "description": "Honor Clock App.\n", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.systemmanager": { + "list": "Oem", + "description": "System Manager\nHonor's stock phone cleaner. Consumes a lot of battery power for useless 'security' checks.\n NOTE: breaks the functionality of closing and cleaning background apps.\nThis is more than a phone cleaner, you will lose a lot of settings like battery and notifications management if you remove this.\n WARNING: apparently needed for managing app permissions, not safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.airlink": { + "list": "Oem", + "description": "Air link service, it's probably needed for Wireless Projection.\nNo activities, only more debugging stuff, location things, logs", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "androidhnext": { + "list": "Oem", + "description": "EMUI Graphical User Interface:\nhttps://fixyourandroid.com/about/androidhwext\nThe framework responsible for the themes (even the standard one) of EMUI to launch. Also, it's the core for the Themes app. REMOVING IT CAUSES A BOOTLOOP!", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.hihonor.trustcircle": { + "list": "Oem", + "description": "Device authentication service\nThe app's usage is unknown, but it can be removed if apps such as com.hihonor.id, com.hihonor.appmarket are also removed. This is what I found while exploring the APK: Huawei Mobile Services?, managing installation and updates of AppGallery.\nHuawei HWID account may be inaccessible without this app.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.id": { + "list": "Oem", + "description": "Honor Mobile Services\nHonor’s alternative to Google Play Services. Needed to access advanced Honor features.\nA Honor ID is required to access services, like Themes. This may break an app like InPost Mobile, see:\nhttps://github.com/0x192/universal-android-debloater/issues/477\nSee more about Honor Mobile Services: https://www.xda-developers.com/huawei-hms-core-android-alternative-google-play-services-gms/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.printservice": { + "list": "Oem", + "description": "Print service", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.hihonor.lbs": { + "list": "Oem", + "description": "Location Based Services\nLocation-based services (LBS) are applications or services that utilize location data from a user's device, such as a smartphone or GPS, to provide relevant information, directions, or recommendations tailored to their specific location. These services rely on a combination of technologies, including Global Positioning System (GPS), Wi-Fi, cellular networks, and sensors, to determine a user's position accurately.\nNOTE: Can cause bootloops on some devices.\nThe primary goal of LBS is to offer personalized and context-aware experiences based on a user's geographical location. This can include services like:\n1. Navigation and Mapping, 2. Location-Based Advertising, 3. Social Networking, 4. Emergency Services, 5. IoT Asset Tracking\nhttps://forum.huawei.com/enterprise/en/location-based-services/thread/703168442200375296-667213855346012160", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.aipluginengine": { + "list": "Oem", + "description": "Assistant Basic Services\nSeems to be a dependency of Honor Lens. Safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.hihonor.systemappsupdater": { + "list": "Oem", + "description": "System apps update\nUnless you want to manually update system apps, do not remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.hihonor.awareness": { + "list": "Oem", + "description": "Dependency of YOYO Assistant and Honor AI ? Didn't notice anything when removed.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.hwresourceshare.storage": { + "list": "Oem", + "description": "Allows the storage on your phone, tablet, computer, and TV to connect so you can view and use files from one device on another without cables or downloads.\nThe service always runs in the background, and removing it has not caused any problems.\nhttps://r1.community.samsung.com/t5/tips-how-to/the-new-storage-share-feature/ba-p/36247598\nhttps://www.samsung.com/us/support/answer/ANS10004607/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.wallpaper.live": { + "list": "Oem", + "description": "Samsung official app for dynamic and live wallpapers with generative AI capabilities.\nBecause it provides a wallpaper service, it runs in the background and starts automatically when the phone boots.\nIf you remove it while using a wallpaper created by it, that wallpaper will be removed as well.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.nfc": { + "list": "Oem", + "description": "It’s the main NFC module on Samsung devices.\nIt handles contactless payments, card emulation for Samsung Pay, NFC tag reading and writing, and features like Wireless Power Sharing, and it also manages certain S Pen functions that rely on NFC.\nI assume NFC breaks when disabled.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.samsung.android.wifi.largetcpbuffer.resources": { + "list": "Oem", + "description": "It only provides configuration data with no executable code and adjusts Wi‑Fi TCP buffer sizes to optimized values\nDepending entirely on com.android.wifi.resources\nIn theory it shouldn’t negatively affect Wi‑Fi if deleted, but this hasn’t been tested. It isn’t required for basic Wi‑Fi functionality; it mainly improves performance on fast networks, so removing it may make Wi‑Fi slightly slower.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.android.onetimeinitializer": { + "list": "Aosp", + "description": "Needed for first time setup. Due to how UAD works, the package will be restored on factory reset, so it's safe to disable. No purpose to keep it after setup. Better to disable; not uninstall", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.insulet.myblue.pdm": { + "list": "Oem", + "description": "App to control OmniPod insulin pumps. Preinstalled on the OmniPod DASH and OmniPod 5 PDMs. If you're seeing this package you're probably on a modded PDM, so you almost certainly know what this is and it's absolutely unsafe to remove if you're actively using OmniPod.\nhttps://play.google.com/store/apps/details?id=com.insulet.myblue.pdm", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.insulet.myblue.pdmsystem": { + "list": "Oem", + "description": "Additional package needed to control pods on the OmniPod DASH PDM. Doesn't seem to be present on OmniPod 5. See com.insulet.myblue.pdm\n tl;dr: needed to control your insulin pump, absolutely do not remove this.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Unsafe" + }, + "com.nbbsw.compatiblemark": { + "list": "Oem", + "description": "Not exactly sure what this is. Trying to launch mainActivity, you get a Chinese error message, but you can see a java error saying it's trying to connect to s2.sv.wxjyun.cn, which is a non-existent URL. No issues when removing this so it's safe to remove.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "org.simalliance.openmobileapi.eseterminal": { + "list": "Aosp", + "description": "Needed for NFC payments (e.g. Google Wallet) on older Android versions.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.bell.ptt": { + "list": "Carrier", + "description": "Bell Push to Talk app. Apparently the 'most advanced carrier-grade Push-to-talk coomunicates technology available today.' (doubt). Realistically, no one is using this, safe to remove.\n https://play.google.com/store/apps/details?id=com.bell.ptt", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.A21.d01.wallpapermulti": { + "list": "Oem", + "description": "Dynamic lock screen wallpaper feature for the Samsung Galaxy A21. Why is this device specific? I have no idea!", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.sec.android.app.camera.sticker": { + "list": "Oem", + "description": "Samsung DECO PIC. Add things such as live stickers, AR masks, frames, and GIFs to your photos and videos.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.samsung.android.messageguardsync": { + "list": "Oem", + "description": "Handles synchronizing and updating Samsung Message Guard policies.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.samsung.android.mcf.autohotspot": { + "list": "Oem", + "description": "I believe this is not the Auto Hotspot feature itself, but a system module that manages the internal logic behind it.\nIts role is to coordinate automatic hotspot connections and handle the user‑facing network experience.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Expert" + }, + "com.blackview.systemmanager": { + "list": "Oem", + "description": "'System Manager'\nA pre-installed 'task killer', which ironically slows down the system. It also has internet and install apps permisions by default, making it a potential backdoor.\nAlthough 'systemmanager' might sound important, disabling it will significantly reduce scroll stuttering. Try disabling instead of uninstalling in case that breaks the App info Settings page.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.blackview.apkupgrade": { + "list": "Oem", + "description": "System Message\nAdware, sends unwanted promotional notifications.\nTry disabling instead of uninstalling in case that breaks the App info Settings page.\nhttps://www.reddit.com/r/blackview/comments/1mo441x/get_rid_of_system_notification_that_contains_ads/", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.huawei.localBackup": { + "list": "Oem", + "description": "Backup\nA hidden app, which has storage, location, contacts, SMS, call logs and calendar permissions. Can be uninstalled via Settings.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.huawei.aml": { + "list": "Oem", + "description": "Huawei AML\nA hidden app, which has phone, location and SMS permissions.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Recommended" + }, + "com.blackview.helper": { + "list": "Oem", + "description": "DKHelper\nTry disabling instead of uninstalling in case that breaks the App info Settings page.", + "dependencies": [], + "neededBy": [], + "labels": [], + "removal": "Advanced" + }, + "com.softwinner.dragonatt": { + "list": "Oem", + "description": "DragonAtt", "dependencies": [], "neededBy": [], "labels": [], diff --git a/resources/images/icon_clyde_blurple.svg b/resources/images/icon_clyde_blurple.svg new file mode 100644 index 0000000..b636d15 --- /dev/null +++ b/resources/images/icon_clyde_blurple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/images/icon_clyde_blurple_RGB.png b/resources/images/icon_clyde_blurple_RGB.png deleted file mode 100644 index e9dc50d..0000000 Binary files a/resources/images/icon_clyde_blurple_RGB.png and /dev/null differ diff --git a/src/core/helpers.rs b/src/core/helpers.rs deleted file mode 100644 index 01906e0..0000000 --- a/src/core/helpers.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::core::theme::Theme; -use crate::gui::style; -use iced::widget::button; -use iced::widget::button::Button; -use iced::{Element, Renderer}; - -/// Wrapper function for `iced::widget::button` with padding and style applied -pub fn button_primary<'a, Message>( - content: impl Into>, -) -> Button<'a, Message, Theme, Renderer> { - button(content) - .padding([5, 10]) - .style(style::Button::Primary) -} diff --git a/src/core/mod.rs b/src/core/mod.rs deleted file mode 100644 index 68c584e..0000000 --- a/src/core/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod adb; -pub mod config; -pub mod helpers; -pub mod save; -pub mod sync; -pub mod theme; -pub mod uad_lists; -pub mod update; -pub mod utils; diff --git a/src/core/sync.rs b/src/core/sync.rs deleted file mode 100644 index e28208d..0000000 --- a/src/core/sync.rs +++ /dev/null @@ -1,369 +0,0 @@ -use crate::core::{ - adb::{ACommand as AdbCommand, PM_CLEAR_PACK, to_trimmed_utf8}, - uad_lists::PackageState, -}; -use crate::gui::{views::list::PackageInfo, widgets::package_row::PackageRow}; -use regex::Regex; -use retry::{OperationResult, delay::Fixed, retry}; -use serde::{Deserialize, Serialize}; -use std::process::Command; -use std::sync::LazyLock; - -#[cfg(target_os = "windows")] -use std::os::windows::process::CommandExt; - -/// An Android device, typically a phone -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Phone { - /// Non-market name - pub model: String, // could be `Copy` - /// Android API level version - pub android_sdk: u8, - /// In theory, `len < u16::MAX` _should_ always be `true`. - /// In practice, `len <= u8::MAX`. - pub user_list: Vec, - /// Unique serial identifier - pub adb_id: String, // could be `Copy` -} - -impl Default for Phone { - fn default() -> Self { - Self { - model: "fetching devices...".to_string(), - android_sdk: 0, - user_list: vec![], - adb_id: String::default(), - } - } -} - -impl std::fmt::Display for Phone { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.model) - } -} - -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] -pub struct User { - pub id: u16, - pub index: usize, - pub protected: bool, -} - -impl std::fmt::Display for User { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "user {}", self.id) - } -} - -#[derive(Debug, Clone)] -pub enum CommandType { - PackageManager(PackageInfo), -} - -/// An enum to contain different variants for errors yielded by ADB. -#[derive(Debug, Clone)] -pub enum AdbError { - Generic(String), -} - -/// Runs an **arbitrary command** on the device's default `sh` implementation. -/// Typically MKSH, but could be Ash. -/// [More info](https://chromium.googlesource.com/aosp/platform/system/core/+/refs/heads/upstream/shell_and_utilities). -/// -/// If `serial` is empty, it lets ADB choose the default device. -#[deprecated = "Use [`adb::ACommand::shell`] with `async` blocks instead"] -pub async fn adb_shell_command>( - device_serial: S, - action: String, - command_type: CommandType, -) -> Result { - let serial = device_serial.as_ref(); - - let label = match &command_type { - CommandType::PackageManager(p) => &p.removal, - }; - - let mut cmd = Command::new("adb"); - if !serial.is_empty() { - cmd.args(["-s", serial]); - }; - cmd.arg("shell"); - // this works because `sh` splits spaces - cmd.arg(&action); - - #[cfg(target_os = "windows")] - let cmd = cmd.creation_flags(0x0800_0000); // do not open a cmd window - - match match cmd.output() { - Err(e) => { - error!("ADB: {}", e); - Err("Cannot run ADB, likely not found".to_string()) - } - Ok(o) => { - let stdout = to_trimmed_utf8(o.stdout); - if o.status.success() { - Ok(stdout) - } else { - let stderr = to_trimmed_utf8(o.stderr); - - // ADB does really weird things. Some errors are not redirected to stderr - let err = if stdout.is_empty() { stderr } else { stdout }; - Err(err) - } - } - } { - Ok(o) => { - // On old devices, adb commands can return the `0` exit code even if there - // is an error. On Android 4.4, ADB doesn't check if the package exists. - // It does not return any error if you try to `pm block` a non-existent package. - // Some commands are even killed by ADB before finishing and UAD-ng can't catch - // the output. - if ["Error", "Failure"].iter().any(|&e| o.contains(e)) { - return Err(AdbError::Generic(format!("[{label}] {action} -> {o}"))); - } - - info!("[{label}] {action} -> {o}"); - Ok(command_type) - } - Err(err) => { - if !err.contains("[not installed for") { - return Err(AdbError::Generic(format!("[{label}] {action} -> {err}"))); - } - Err(AdbError::Generic(err)) - } - } -} - -/// If `None`, returns an empty String, not " --user 0" -pub fn user_flag(user_id: Option) -> String { - user_id - .map(|user| format!(" --user {}", user.id)) - .unwrap_or_default() -} - -// Minimum information for processing adb commands -#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)] -pub struct CorePackage { - pub name: String, - pub state: PackageState, -} - -impl From<&mut PackageRow> for CorePackage { - fn from(pr: &mut PackageRow) -> Self { - Self { - name: pr.name.clone(), - state: pr.state, - } - } -} -impl From for CorePackage { - fn from(pr: PackageRow) -> Self { - Self { - name: pr.name.clone(), - state: pr.state, - } - } -} - -impl From<&PackageRow> for CorePackage { - fn from(pr: &PackageRow) -> Self { - Self { - name: pr.name.clone(), - state: pr.state, - } - } -} - -pub fn apply_pkg_state_commands( - package: &CorePackage, - wanted_state: PackageState, - selected_user: User, - phone: &Phone, -) -> Vec { - // https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/ADB-reference - // ALWAYS PUT THE COMMAND THAT CHANGES THE PACKAGE STATE FIRST! - let commands = match wanted_state { - PackageState::Enabled => match package.state { - PackageState::Disabled => vec!["pm enable"], - PackageState::Uninstalled => match phone.android_sdk { - i if i >= 23 => vec!["cmd package install-existing"], - 21 | 22 => vec!["pm unhide"], - 19 | 20 => vec!["pm unblock", PM_CLEAR_PACK], - _ => unreachable!("already prevented by the GUI"), - }, - _ => vec![], - }, - PackageState::Disabled => match package.state { - PackageState::Uninstalled | PackageState::Enabled => match phone.android_sdk { - sdk if sdk >= 23 => vec!["pm disable-user", "am force-stop", PM_CLEAR_PACK], - _ => vec![], - }, - _ => vec![], - }, - PackageState::Uninstalled => match package.state { - PackageState::Enabled | PackageState::Disabled => match phone.android_sdk { - sdk if sdk >= 23 => vec!["pm uninstall"], // > Android Marshmallow (6.0) - 21 | 22 => vec!["pm hide", PM_CLEAR_PACK], // Android Lollipop (5.x) - _ => vec!["pm block", PM_CLEAR_PACK], // Disable mode is unavailable on older devices because the specific ADB commands need root - }, - _ => vec![], - }, - PackageState::All => vec![], - }; // this should be a `tinyvec`, as `len <= 4` - - let user = supports_multi_user(phone).then_some(selected_user); - request_builder(&commands, &package.name, user) -} - -/// Build a command request to be sent via ADB to a device. -/// `commands` accepts one or more ADB shell commands -/// which act on a common `package` and `user`. -pub fn request_builder(commands: &[&str], package: &str, user: Option) -> Vec { - let maybe_user_flag = user_flag(user); - commands - .iter() - .map(|c| format!("{c}{maybe_user_flag} {package}")) - .collect() -} - -/// Get the model by querying the `ro.product.model` property. -/// -/// If `serial` is empty, it lets ADB choose the default device. -pub fn get_device_model(serial: &str) -> String { - AdbCommand::new() - .shell(serial) - .getprop("ro.product.model") - .unwrap_or_else(|err| { - eprintln!("ERROR: {err}"); - error!("{err}"); - if err.contains("adb: no devices/emulators found") { - "no devices/emulators found".to_string() - } else { - err - } - }) -} - -/// Get the brand by querying the `ro.product.brand` property. -/// -/// If `serial` is empty, it lets ADB choose the default device. -pub fn get_device_brand(serial: &str) -> String { - AdbCommand::new() - .shell(serial) - .getprop("ro.product.brand") - // `trim` is just-in-case - .map(|s| s.trim().to_string()) - .unwrap_or_default() -} - -/// Get Android SDK version by querying the -// `ro.build.version.sdk` property or defaulting to 0. -/// -/// If `device_serial` is empty, it lets ADB choose the default device. -pub fn get_android_sdk(device_serial: &str) -> u8 { - AdbCommand::new() - .shell(device_serial) - .getprop("ro.build.version.sdk") - .map_or(0, |sdk| { - sdk.parse().expect("SDK version numeral must be valid") - }) -} - -/// Minimum inclusive Android SDK version -/// that supports multi-user mode. -/// Lollipop 5.0 -pub const MULTI_USER_SDK: u8 = 21; - -/// Check if it might support multi-user mode, -/// by simply comparing SDK version. -/// `true` isn't reliable, you can only trust `false`. -/// -/// See: -/// - -/// - -#[must_use] -pub const fn supports_multi_user(dev: &Phone) -> bool { - dev.android_sdk >= MULTI_USER_SDK -} - -/// Check if a `user_id` is protected on a device by trying -/// to list associated packages. -/// -/// If `device_serial` is empty, it lets ADB choose the default device. -pub fn is_protected_user>(user_id: u16, device_serial: S) -> bool { - AdbCommand::new() - .shell(device_serial) - .pm() - .list_packages_sys(None, Some(user_id)) - .is_err() -} - -/// `pm list users` parsed into a vector with extra info -pub fn list_users_parsed(device_serial: &str) -> Vec { - // this could be thread-local (no lock overhead), - // but then each thread would compile its own clone of the regex, - // I guess? - static RE: LazyLock = - LazyLock::new(|| Regex::new(r"\{([0-9]+)").unwrap_or_else(|_| unreachable!())); - - AdbCommand::new() - .shell(device_serial) - .pm() - .list_users() - .map(|out| { - RE.find_iter(&out) - .enumerate() - .map(|(i, user)| { - let u = user.as_str()[1..] - .parse() - .unwrap_or_else(|_| unreachable!("User ID must always be a valid `u16`")); - User { - id: u, - index: i, - protected: is_protected_user(u, device_serial), - } - }) - .collect() - }) - .unwrap_or_default() -} - -/// This matches serials (`getprop ro.serialno`) -/// that are authorized by the user. -pub async fn get_devices_list() -> Vec { - retry( - Fixed::from_millis(500).take(if cfg!(debug_assertions) { 3 } else { 120 }), - || match AdbCommand::new().devices() { - Ok(devices) => { - let mut device_list: Vec = vec![]; - if devices.iter().all(|(_, stat)| stat != "device") { - return OperationResult::Retry(vec![]); - } - for device in devices { - let serial = &device.0; - device_list.push(Phone { - model: format!("{} {}", get_device_brand(serial), get_device_model(serial)), - android_sdk: get_android_sdk(serial), - user_list: list_users_parsed(serial), - adb_id: serial.to_string(), - }); - } - OperationResult::Ok(device_list) - } - Err(err) => { - error!("get_device_list() -> {}", err); - let test: Vec = vec![]; - OperationResult::Retry(test) - } - }, - ) - .unwrap_or_default() -} - -pub async fn initial_load() -> bool { - match AdbCommand::new().devices() { - Ok(_devices) => true, - Err(_err) => false, - } -} diff --git a/src/gui/style.rs b/src/gui/style.rs deleted file mode 100644 index d5b4579..0000000 --- a/src/gui/style.rs +++ /dev/null @@ -1,608 +0,0 @@ -use crate::core::theme::Theme; -use iced::overlay::menu; -use iced::widget::{ - button, checkbox, container, pick_list, radio, rule, scrollable, text, text_input, -}; -use iced::{Background, Border, Color, Shadow, application}; - -#[derive(Default, Debug, Clone, Copy)] -pub enum Application { - #[default] - Default, -} - -impl application::StyleSheet for Theme { - type Style = Application; - - fn appearance(&self, _style: &Self::Style) -> application::Appearance { - let p = self.palette(); - application::Appearance { - background_color: p.base.background, - text_color: p.bright.surface, - } - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub enum Container { - #[default] - Invisible, - Frame, - BorderedFrame, - Tooltip, - Background, -} - -impl container::StyleSheet for Theme { - type Style = Container; - - fn appearance(&self, style: &Self::Style) -> container::Appearance { - let pal = self.palette(); - match style { - Container::Invisible => container::Appearance::default(), - Container::Frame => container::Appearance { - background: Some(Background::Color(pal.base.foreground)), - text_color: Some(pal.bright.surface), - border: Border { - color: Color::TRANSPARENT, - width: 0.0, - radius: 5.0.into(), - }, - ..container::Appearance::default() - }, - Container::BorderedFrame => container::Appearance { - background: Some(Background::Color(pal.base.foreground)), - text_color: Some(pal.bright.surface), - border: Border { - color: pal.normal.error, - width: 1.0, - radius: 5.0.into(), - }, - shadow: Shadow::default(), - }, - Container::Tooltip => container::Appearance { - background: Some(Background::Color(pal.base.foreground)), - text_color: Some(pal.bright.surface), - border: Border { - color: pal.normal.primary, - width: 1.0, - radius: 8.0.into(), - }, - shadow: Shadow::default(), - }, - - Container::Background => container::Appearance { - background: Some(Background::Color(pal.base.background)), - text_color: Some(pal.bright.surface), - border: Border { - color: Color::TRANSPARENT, - width: 0.0, - radius: 5.0.into(), - }, - ..container::Appearance::default() - }, - } - } -} - -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] -pub enum Button { - #[default] - Primary, - Unavailable, - SelfUpdate, - UninstallPackage, - RestorePackage, - NormalPackage, - SelectedPackage, - Hidden, -} - -impl button::StyleSheet for Theme { - type Style = Button; - - fn active(&self, style: &Self::Style) -> button::Appearance { - let p = self.palette(); - - let appearance = button::Appearance { - border: Border { - color: p.normal.primary, - width: 1.0, - radius: 2.0.into(), - }, - ..button::Appearance::default() - }; - - let active_appearance = |bg: Option, mc| button::Appearance { - background: Some(Background::Color(bg.unwrap_or(p.base.foreground))), - border: Border { - color: Color { a: 0.5, ..mc }, - width: 1.0, - radius: 2.0.into(), - }, - text_color: mc, - ..appearance - }; - - match style { - Button::Primary | Button::SelfUpdate => active_appearance(None, p.bright.primary), - Button::RestorePackage => active_appearance(None, p.bright.secondary), - Button::NormalPackage => button::Appearance { - background: Some(Background::Color(p.base.foreground)), - text_color: p.bright.surface, - border: Border { - color: p.base.background, - width: 0.0, - radius: 5.0.into(), - }, - ..appearance - }, - Button::SelectedPackage => button::Appearance { - background: Some(Background::Color(Color { - a: 0.25, - ..p.normal.primary - })), - text_color: p.bright.primary, - border: Border { - color: p.normal.primary, - width: 0.0, - radius: 5.0.into(), - }, - ..appearance - }, - Button::Unavailable | Button::UninstallPackage => { - active_appearance(None, p.bright.error) - } - Button::Hidden => button::Appearance { - background: Some(Background::Color(Color::TRANSPARENT)), - text_color: Color::TRANSPARENT, - border: Border { - color: Color::TRANSPARENT, - width: 0.0, - radius: 5.0.into(), - }, - ..appearance - }, - } - } - - fn hovered(&self, style: &Self::Style) -> button::Appearance { - let active = self.active(style); - let p = self.palette(); - - let hover_appearance = |bg, tc: Option| button::Appearance { - background: Some(Background::Color(Color { a: 0.25, ..bg })), - text_color: tc.unwrap_or(bg), - ..active - }; - - match style { - Button::Primary | Button::SelfUpdate => hover_appearance(p.bright.primary, None), - Button::NormalPackage => hover_appearance(p.normal.primary, Some(p.bright.surface)), - Button::SelectedPackage => hover_appearance(p.normal.primary, None), - Button::RestorePackage => hover_appearance(p.bright.secondary, None), - Button::Unavailable | Button::UninstallPackage => { - hover_appearance(p.bright.error, None) - } - Button::Hidden => hover_appearance(Color::TRANSPARENT, None), - } - } - - fn pressed(&self, style: &Self::Style) -> button::Appearance { - self.active(style) - } - - fn disabled(&self, style: &Self::Style) -> button::Appearance { - let active = self.active(style); - let p = self.palette(); - - let disabled_appearance = |bg, tc: Option| button::Appearance { - background: Some(Background::Color(Color { a: 0.05, ..bg })), - text_color: Color { - a: 0.50, - ..tc.unwrap_or(bg) - }, - ..active - }; - - match style { - Button::RestorePackage => disabled_appearance(p.normal.primary, Some(p.bright.primary)), - Button::UninstallPackage => disabled_appearance(p.bright.error, None), - Button::Primary => disabled_appearance(p.bright.primary, Some(p.bright.primary)), - _ => active, - } - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub enum Scrollable { - #[default] - Description, - Packages, -} - -impl scrollable::StyleSheet for Theme { - type Style = Scrollable; - - fn active(&self, style: &Self::Style) -> scrollable::Appearance { - let from_appearance = |c: Color| scrollable::Appearance { - container: container::Appearance::default(), - gap: Some(Background::Color(Color::TRANSPARENT)), - scrollbar: scrollable::Scrollbar { - background: Some(Background::Color(Color::TRANSPARENT)), - border: Border { - color: Color::TRANSPARENT, - width: 0.0, - radius: 5.0.into(), - }, - scroller: scrollable::Scroller { - color: c, - border: Border { - color: Color::TRANSPARENT, - width: 1.0, - radius: 5.0.into(), - }, - }, - }, - }; - let p = self.palette(); - match style { - Scrollable::Description => from_appearance(p.normal.surface), - Scrollable::Packages => from_appearance(p.base.foreground), - } - } - - fn hovered(&self, style: &Self::Style, _mouse_over_scrollbar: bool) -> scrollable::Appearance { - scrollable::Appearance { - scrollbar: self.active(style).scrollbar, - ..self.active(style) - } - } - - fn dragging(&self, style: &Self::Style) -> scrollable::Appearance { - let hovered = self.hovered(style, true); - scrollable::Appearance { - scrollbar: hovered.scrollbar, - ..hovered - } - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub enum CheckBox { - #[default] - PackageEnabled, - PackageDisabled, - SettingsEnabled, - SettingsDisabled, -} - -impl checkbox::StyleSheet for Theme { - type Style = CheckBox; - - fn active(&self, style: &Self::Style, _is_checked: bool) -> checkbox::Appearance { - let pal = self.palette(); - match style { - CheckBox::PackageEnabled => checkbox::Appearance { - background: Background::Color(pal.base.background), - icon_color: pal.bright.primary, - border: Border { - color: pal.base.background, - width: 1.0, - radius: 5.0.into(), - }, - text_color: Some(pal.bright.surface), - }, - CheckBox::PackageDisabled => checkbox::Appearance { - background: Background::Color(Color { - a: 0.55, - ..pal.base.background - }), - - icon_color: pal.bright.primary, - border: Border { - color: pal.normal.primary, - width: 1.0, - radius: 5.0.into(), - }, - text_color: Some(pal.normal.primary), - }, - CheckBox::SettingsEnabled => checkbox::Appearance { - background: Background::Color(pal.base.background), - icon_color: pal.bright.primary, - border: Border { - color: pal.bright.primary, - width: 1.0, - radius: 5.0.into(), - }, - text_color: Some(pal.bright.surface), - }, - CheckBox::SettingsDisabled => checkbox::Appearance { - background: Background::Color(pal.base.foreground), - icon_color: pal.bright.primary, - border: Border { - color: pal.normal.primary, - width: 1.0, - radius: 5.0.into(), - }, - text_color: Some(pal.bright.surface), - }, - } - } - - fn hovered(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance { - let p = self.palette(); - let from_appearance = || checkbox::Appearance { - background: Background::Color(p.base.foreground), - icon_color: p.bright.primary, - border: Border { - color: p.bright.primary, - width: 2.0, - radius: 5.0.into(), - }, - text_color: Some(p.bright.surface), - }; - - match style { - CheckBox::PackageEnabled | CheckBox::SettingsEnabled => from_appearance(), - CheckBox::PackageDisabled | CheckBox::SettingsDisabled => { - self.active(style, is_checked) - } - } - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub enum TextInput { - #[default] - Default, -} - -impl text_input::StyleSheet for Theme { - type Style = TextInput; - - fn active(&self, _style: &Self::Style) -> text_input::Appearance { - let p = self.palette(); - text_input::Appearance { - background: Background::Color(p.base.foreground), - border: Border { - color: p.base.foreground, - width: 0.0, - radius: 5.0.into(), - }, - icon_color: Color { - a: 0.5, - ..p.normal.primary - }, - } - } - - fn focused(&self, _style: &Self::Style) -> text_input::Appearance { - let p = self.palette(); - text_input::Appearance { - background: Background::Color(p.base.foreground), - border: Border { - color: Color { - a: 0.5, - ..p.normal.primary - }, - width: 1.0, - radius: 2.0.into(), - }, - icon_color: Color { - a: 0.5, - ..p.normal.primary - }, - } - } - - fn disabled_color( - &self, - _: &::Style, - ) -> iced::Color { - todo!() - } - - fn disabled(&self, _style: &Self::Style) -> text_input::Appearance { - let p = self.palette(); - text_input::Appearance { - background: Background::Color(p.base.background), - border: Border { - color: Color { - a: 0.5, - ..p.base.foreground - }, - width: 1.0, - radius: 2.0.into(), - }, - icon_color: Color { - a: 0.5, - ..p.base.foreground - }, - } - } - - fn placeholder_color(&self, _style: &Self::Style) -> Color { - self.palette().normal.surface - } - - fn value_color(&self, _style: &Self::Style) -> Color { - self.palette().bright.primary - } - - fn selection_color(&self, _style: &Self::Style) -> Color { - self.palette().normal.primary - } - - /// Produces the style of an hovered text input. - fn hovered(&self, style: &Self::Style) -> text_input::Appearance { - self.focused(style) - } -} - -#[derive(Default, Debug, Clone, Copy)] -pub enum PickList { - #[default] - Default, -} - -impl menu::StyleSheet for Theme { - type Style = (); - - fn appearance(&self, _style: &Self::Style) -> menu::Appearance { - let p = self.palette(); - - menu::Appearance { - text_color: p.bright.surface, - background: p.base.background.into(), - border: Border { - color: p.base.background, - width: 1.0, - radius: 2.0.into(), - }, - selected_text_color: p.bright.surface, - selected_background: p.normal.primary.into(), - } - } -} - -impl pick_list::StyleSheet for Theme { - type Style = (); - - fn active(&self, _style: &()) -> pick_list::Appearance { - let p = self.palette(); - - pick_list::Appearance { - text_color: p.bright.surface, - background: p.base.background.into(), - border: Border { - color: Color { - a: 0.5, - ..p.normal.primary - }, - width: 1.0, - radius: 2.0.into(), - }, - handle_color: p.bright.surface, - placeholder_color: p.bright.surface, - } - } - - fn hovered(&self, style: &()) -> pick_list::Appearance { - let active = self.active(style); - pick_list::Appearance { - border: Border { - color: self.palette().normal.primary, - width: 1.0, - radius: 2.0.into(), - }, - ..active - } - } -} - -#[derive(Default, Clone, Copy)] -pub enum Text { - #[default] - Default, - Ok, - Danger, - Commentary, - Color(Color), -} - -impl From for Text { - fn from(color: Color) -> Self { - Self::Color(color) - } -} - -impl text::StyleSheet for Theme { - type Style = Text; - - fn appearance(&self, style: Self::Style) -> text::Appearance { - let p = self.palette(); - match style { - Text::Default => text::Appearance::default(), - Text::Ok => text::Appearance { - color: Some(p.bright.secondary), - }, - Text::Danger => text::Appearance { - color: Some(p.bright.error), - }, - Text::Commentary => text::Appearance { - color: Some(p.normal.surface), - }, - Text::Color(c) => text::Appearance { color: Some(c) }, - } - } -} - -impl radio::StyleSheet for Theme { - type Style = (); - - fn active(&self, _style: &Self::Style, _is_selected: bool) -> radio::Appearance { - let p = self.palette(); - radio::Appearance { - background: Color::TRANSPARENT.into(), - dot_color: p.bright.primary, - border_width: 1.0, - border_color: p.bright.primary, - text_color: None, - } - } - - fn hovered(&self, style: &Self::Style, _is_selected: bool) -> radio::Appearance { - let p = self.palette(); - let active = self.active(style, true); - - radio::Appearance { - dot_color: p.bright.primary, - border_color: p.bright.primary, - border_width: 2.0, - ..active - } - } -} - -#[derive(Default, Clone, Copy)] -pub enum Rule { - #[default] - Default, -} - -impl rule::StyleSheet for Theme { - type Style = Rule; - - fn appearance(&self, style: &Self::Style) -> rule::Appearance { - match style { - Rule::Default => rule::Appearance { - color: self.palette().bright.surface, - width: 2, - radius: 2.0.into(), - fill_mode: rule::FillMode::Full, - }, - } - } -} - -// Unit tests -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_palette() { - let palette = Theme::default().palette(); - - assert_ne!(palette.base.background, palette.base.foreground); - assert_ne!(palette.normal.primary, Color::BLACK); - assert_ne!(palette.normal.surface, Color::BLACK); - assert_ne!(palette.bright.primary, Color::BLACK); - // if `LIGHT` then this can be `BLACK` - // https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/pull/730#issuecomment-2525405134 - //assert_ne!(palette.bright.surface, Color::BLACK); - assert_ne!(palette.normal.error, Color::BLACK); - assert_ne!(palette.bright.error, Color::BLACK); - } -} diff --git a/src/gui/views/list.rs b/src/gui/views/list.rs deleted file mode 100644 index b07ba92..0000000 --- a/src/gui/views/list.rs +++ /dev/null @@ -1,1033 +0,0 @@ -use crate::core::config::DeviceSettings; -use crate::core::helpers::button_primary; -use crate::core::sync::{ - AdbError, CommandType, Phone, User, adb_shell_command, apply_pkg_state_commands, -}; -use crate::core::theme::Theme; -use crate::core::uad_lists::{ - Opposite, PackageHashMap, PackageState, Removal, UadList, UadListState, load_debloat_lists, -}; -use crate::core::utils::{EXPORT_FILE_NAME, NAME, export_selection, fetch_packages, open_url}; -use crate::gui::style; -use crate::gui::widgets::navigation_menu::ICONS; -use std::path::PathBuf; - -use crate::gui::views::settings::Settings; -use crate::gui::widgets::modal::Modal; -use crate::gui::widgets::package_row::{Message as RowMessage, PackageRow}; -use crate::gui::widgets::text; -use iced::widget::{ - Column, Space, button, checkbox, column, container, horizontal_space, pick_list, radio, row, - scrollable, text_input, tooltip, vertical_rule, -}; -use iced::{Alignment, Command, Element, Length, Renderer, alignment}; - -#[derive(Debug, Default, Clone)] -pub struct PackageInfo { - pub i_user: usize, - pub index: usize, - pub removal: String, -} - -#[derive(Default, Debug, Clone)] -pub enum LoadingState { - DownloadingList, - #[default] - FindingPhones, - LoadingPackages, - _UpdatingUad, - Ready, - RestoringDevice(String), - FailedToUpdate, -} - -#[derive(Default, Debug, Clone)] -#[allow(clippy::struct_excessive_bools, reason = "Not a state-machine")] -pub struct List { - pub loading_state: LoadingState, - pub uad_lists: PackageHashMap, - /// packages of all users of the phone - pub phone_packages: Vec>, - /// `phone_packages` indexes of the selected user (= what you see on screen) - filtered_packages: Vec, - /// Vec of `(user_index, pkg_index)` - selected_packages: Vec<(usize, usize)>, - selected_package_state: Option, - selected_removal: Option, - selected_list: Option, - pub selected_user: Option, - all_selected: bool, - pub input_value: String, - description: String, - selection_modal: bool, - error_modal: Option, - export_modal: bool, - current_package_index: usize, - is_adb_satisfied: bool, -} - -#[derive(Debug, Clone)] -pub enum Message { - LoadUadList(bool), - LoadPhonePackages((PackageHashMap, UadListState)), - RestoringDevice(Result), - ApplyFilters(Vec>), - SearchInputChanged(String), - ToggleAllSelected(bool), - ListSelected(UadList), - UserSelected(User), - PackageStateSelected(PackageState), - RemovalSelected(Removal), - ApplyActionOnSelection, - List(usize, RowMessage), - ChangePackageState(Result), - Nothing, - ModalHide, - ModalUserSelected(User), - ModalValidate, - ClearSelectedPackages, - ADBSatisfied(bool), - UpdateFailed, - GoToUrl(PathBuf), - ExportSelection, - SelectionExported(Result), -} - -pub struct SummaryEntry { - category: Removal, - discard: u8, - restore: u8, -} - -impl From for SummaryEntry { - fn from(category: Removal) -> Self { - Self { - category, - discard: 0, - restore: 0, - } - } -} - -impl List { - #[allow(clippy::too_many_lines)] - pub fn update( - &mut self, - settings: &mut Settings, - selected_device: &mut Phone, - list_update_state: &mut UadListState, - message: Message, - ) -> Command { - let i_user = self.selected_user.unwrap_or_default().index; - match message { - Message::ModalHide => { - self.selection_modal = false; - self.error_modal = None; - self.export_modal = false; - Command::none() - } - Message::ModalValidate => { - let mut commands = vec![]; - self.selected_packages.sort_unstable(); - self.selected_packages.dedup(); - for selection in &self.selected_packages { - commands.append(&mut build_action_pkg_commands( - &self.phone_packages, - selected_device, - &settings.device, - *selection, - )); - } - self.selection_modal = false; - Command::batch(commands) - } - Message::RestoringDevice(output) => { - if let Ok(res) = output { - if let CommandType::PackageManager(p) = res { - self.loading_state = LoadingState::RestoringDevice( - self.phone_packages[i_user][p.index].name.clone(), - ); - }; - } else { - self.loading_state = LoadingState::RestoringDevice("Error [TODO]".to_string()); - } - Command::none() - } - Message::LoadUadList(remote) => { - info!("{:-^65}", "-"); - info!( - "ANDROID_SDK: {} | DEVICE: {}", - selected_device.android_sdk, selected_device.model - ); - info!("{:-^65}", "-"); - self.loading_state = LoadingState::DownloadingList; - Command::perform( - Self::init_apps_view(remote, selected_device.clone()), - Message::LoadPhonePackages, - ) - } - Message::LoadPhonePackages((uad_list, list_state)) => { - self.loading_state = LoadingState::LoadingPackages; - self.uad_lists.clone_from(&uad_list); - *list_update_state = list_state; - Command::perform( - Self::load_packages( - uad_list, - selected_device.adb_id.clone(), - selected_device.user_list.clone(), - ), - Message::ApplyFilters, - ) - } - Message::ApplyFilters(packages) => { - self.phone_packages = packages; - self.filtered_packages = (0..self.phone_packages[i_user].len()).collect(); - self.selected_package_state = Some(PackageState::Enabled); - self.selected_removal = Some(Removal::Recommended); - self.selected_list = Some(UadList::All); - self.selected_user = Some(User::default()); - Self::filter_package_lists(self); - self.loading_state = LoadingState::Ready; - Command::none() - } - Message::ToggleAllSelected(selected) => { - for i in self.filtered_packages.clone() { - if self.phone_packages[i_user][i].selected != selected { - #[expect(unused_must_use, reason = "side-effect")] - self.update( - settings, - selected_device, - list_update_state, - Message::List(i, RowMessage::ToggleSelection(selected)), - ); - } - } - self.all_selected = selected; - Command::none() - } - Message::SearchInputChanged(letter) => { - self.input_value = letter; - Self::filter_package_lists(self); - Command::none() - } - Message::ListSelected(list) => { - self.selected_list = Some(list); - Self::filter_package_lists(self); - Command::none() - } - Message::PackageStateSelected(package_state) => { - self.selected_package_state = Some(package_state); - Self::filter_package_lists(self); - Command::none() - } - Message::RemovalSelected(removal) => { - self.selected_removal = Some(removal); - Self::filter_package_lists(self); - Command::none() - } - Message::List(i_package, row_message) => { - #[expect(unused_must_use, reason = "side-effect")] - { - self.phone_packages[i_user][i_package] - .update(&row_message) - .map(move |row_message| Message::List(i_package, row_message)); - } - - let package = &mut self.phone_packages[i_user][i_package]; - - match row_message { - RowMessage::ToggleSelection(toggle) => { - if package.removal == Removal::Unsafe && !settings.general.expert_mode { - package.selected = false; - return Command::none(); - } - - if settings.device.multi_user_mode { - for u in selected_device.user_list.iter().filter(|&u| !u.protected) { - self.phone_packages[u.index][i_package].selected = toggle; - if toggle { - self.selected_packages.push((u.index, i_package)); - } - } - if !toggle { - self.selected_packages.retain(|&x| x.1 != i_package); - } - } else { - package.selected = toggle; - if toggle { - self.selected_packages.push((i_user, i_package)); - } else { - self.selected_packages - .retain(|&x| x.1 != i_package || x.0 != i_user); - } - } - Command::none() - } - RowMessage::ActionPressed => { - self.phone_packages[i_user][i_package].selected = true; - Command::batch(build_action_pkg_commands( - &self.phone_packages, - selected_device, - &settings.device, - (i_user, i_package), - )) - } - RowMessage::PackagePressed => { - self.description = package.clone().description; - package.current = true; - if self.current_package_index != i_package { - self.phone_packages[i_user][self.current_package_index].current = false; - } - self.current_package_index = i_package; - Command::none() - } - } - } - Message::ApplyActionOnSelection => { - self.selection_modal = true; - Command::none() - } - Message::UserSelected(user) => { - self.selected_user = Some(user); - self.filtered_packages = (0..self.phone_packages[user.index].len()).collect(); - Self::filter_package_lists(self); - Command::none() - } - Message::ChangePackageState(res) => { - match res { - Ok(CommandType::PackageManager(p)) => { - let package = &mut self.phone_packages[p.i_user][p.index]; - package.state = package.state.opposite(settings.device.disable_mode); - package.selected = false; - self.selected_packages - .retain(|&x| x.1 != p.index && x.0 != p.i_user); - Self::filter_package_lists(self); - } - Err(AdbError::Generic(err)) => { - self.error_modal = Some(err); - } - } - Command::none() - } - Message::ModalUserSelected(user) => { - self.selected_user = Some(user); - self.update( - settings, - selected_device, - list_update_state, - Message::UserSelected(user), - ) - } - Message::ClearSelectedPackages => { - self.selected_packages = Vec::new(); - Command::none() - } - Message::ADBSatisfied(result) => { - self.is_adb_satisfied = result; - Command::none() - } - Message::UpdateFailed => { - self.loading_state = LoadingState::FailedToUpdate; - Command::none() - } - Message::GoToUrl(url) => { - open_url(url); - Command::none() - } - Message::ExportSelection => Command::perform( - export_selection(self.phone_packages[i_user].clone()), - Message::SelectionExported, - ), - Message::SelectionExported(export) => { - match export { - Ok(_) => self.export_modal = true, - Err(err) => error!("Failed to export current selection: {:?}", err), - }; - Command::none() - } - Message::Nothing => Command::none(), - } - } - - /// Builds the main view for the app list interface - pub fn view( - &self, - settings: &Settings, - selected_device: &Phone, - ) -> Element { - match &self.loading_state { - LoadingState::DownloadingList => waiting_view( - &format!("Downloading latest {NAME} lists from GitHub. Please wait..."), - Some(button("No internet?").on_press(Message::LoadUadList(false))), - style::Text::Default, - ), - LoadingState::FindingPhones => { - if self.is_adb_satisfied { - waiting_view("Finding connected devices...", None, style::Text::Default) - } else { - waiting_view( - "ADB is not installed on your system, install ADB and relaunch application.", - Some(button("Read on how to get started.") - .on_press(Message::GoToUrl(PathBuf::from( - "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/wiki/Getting-started", - )))), - style::Text::Danger, - ) - } - } - LoadingState::LoadingPackages => waiting_view( - "Pulling packages from the device. Please wait...", - None, - style::Text::Default, - ), - LoadingState::_UpdatingUad => waiting_view( - &format!("Updating {NAME}. Please wait..."), - None, - style::Text::Default, - ), - LoadingState::RestoringDevice(device) => waiting_view( - &format!("Restoring device: {device}"), - None, - style::Text::Default, - ), - LoadingState::Ready => self.ready_view(settings, selected_device), - LoadingState::FailedToUpdate => waiting_view( - "Failed to download update", - Some(button("Go back").on_press(Message::LoadUadList(false))), - style::Text::Danger, - ), - } - } - - fn control_panel(&self, selected_device: &Phone) -> Element { - let search_packages = text_input("Search packages...", &self.input_value) - .width(Length::Fill) - .on_input(Message::SearchInputChanged) - .padding([5, 10]); - - let select_all_checkbox = checkbox("", self.all_selected) - .on_toggle(Message::ToggleAllSelected) - .style(style::CheckBox::SettingsEnabled) - .spacing(0); // no label, so remove space entirely - - let col_sel_all = row![ - tooltip( - select_all_checkbox, - if self.all_selected { - "Deselect all" - } else { - "Select all" - }, - tooltip::Position::Top, - ) - .style(style::Container::Tooltip) - .gap(4) - ] - .padding(8); - - let user_picklist = pick_list( - selected_device.user_list.clone(), - self.selected_user, - Message::UserSelected, - ) - .width(85); - - let list_picklist = pick_list(UadList::ALL, self.selected_list, Message::ListSelected); - let package_state_picklist = pick_list( - PackageState::ALL, - self.selected_package_state, - Message::PackageStateSelected, - ); - - let removal_picklist = pick_list( - Removal::ALL, - self.selected_removal, - Message::RemovalSelected, - ); - - row![ - col_sel_all, - search_packages, - user_picklist, - removal_picklist, - package_state_picklist, - list_picklist, - ] - .width(Length::Fill) - .align_items(Alignment::Center) - .spacing(6) - .padding([0, 16, 0, 0]) - .into() - } - - #[allow(clippy::too_many_lines)] - fn ready_view( - &self, - settings: &Settings, - selected_device: &Phone, - ) -> Element { - let packages = self - .filtered_packages - .iter() - .fold(column![].spacing(6), |col, &i| { - col.push( - self.phone_packages[self.selected_user.unwrap_or_default().index][i] - .view(settings, selected_device) - .map(move |msg| Message::List(i, msg)), - ) - }); - - let packages_scrollable = scrollable(packages) - .height(Length::FillPortion(6)) - .style(style::Scrollable::Packages); - - let description_scroll = scrollable(text(&self.description).width(Length::Fill)) - .style(style::Scrollable::Description); - - let description_panel = container(description_scroll) - .padding(6) - .height(Length::FillPortion(2)) - .width(Length::Fill) - .style(style::Container::Frame); - - let review_selection = { - let tmp_widget = text(format!( - "Review selection ({})", - self.selected_packages.len() - )); - if self.selected_packages.is_empty() { - button(tmp_widget).padding([5, 10]) - } else { - button_primary(tmp_widget).on_press(Message::ApplyActionOnSelection) - } - }; - - let mut export_selection = button(text(format!( - "Export current selection ({})", - self.selected_packages.len() - ))) - .padding([5, 10]); - if !self.selected_packages.is_empty() { - export_selection = export_selection - .on_press(Message::ExportSelection) - .style(style::Button::Primary); - }; - // lock - let export_selection = export_selection; - - let action_row = row![ - export_selection, - Space::new(Length::Fill, Length::Shrink), - review_selection - ] - .width(Length::Fill) - .spacing(10) - .align_items(Alignment::Center); - - let unavailable = container( - column![ - text("ADB is not authorized to access this user!").size(20) - .style(style::Text::Danger), - text("The most likely reason is that it is the user of your work profile (also called Secure Folder on Samsung devices). There's really no solution, other than completely disabling your work profile in your device settings.") - .style(style::Text::Commentary) - .horizontal_alignment(alignment::Horizontal::Center), - ] - .spacing(6) - .align_items(Alignment::Center) - ) - .padding(10) - .center_x() - .style(style::Container::BorderedFrame); - - let control_panel = self.control_panel(selected_device); - let content = if selected_device.user_list.is_empty() - || match self.selected_user { - Some(u) => !self.phone_packages[u.index].is_empty(), - // If no user has been selected, - // then it could be considered as "equivalent" - // to the case where the `user_list` is empty? - // However, this is inconsistent, - // because other parts of the code simply use a `default` `User`. - None => true, - } { - column![ - control_panel, - packages_scrollable, - description_panel, - action_row, - ] - } else { - column![ - control_panel, - container(unavailable).height(Length::Fill).center_y(), - ] - } - .width(Length::Fill) - .spacing(10) - .align_items(Alignment::Center); - - if self.selection_modal { - return Modal::new( - content.padding(10), - self.apply_selection_modal( - selected_device, - settings, - &self.phone_packages[self.selected_user.unwrap_or_default().index], - ), - ) - .on_blur(Message::ModalHide) - .into(); - } - - if self.export_modal { - let title = container(row![text("Success").size(24)].align_items(Alignment::Center)) - .width(Length::Fill) - .style(style::Container::Frame) - .padding([10, 0, 10, 0]) - .center_y() - .center_x(); - - let text_box = row![ - text(format!("Exported current selection into file.\nFile is exported in same directory where {NAME} is located.")).width(Length::Fill), - ].padding(20); - - let file_row = row![text(EXPORT_FILE_NAME).style(style::Text::Commentary)].padding(20); - - let modal_btn_row = row![ - Space::new(Length::Fill, Length::Shrink), - button(text("Close").width(Length::Shrink)) - .width(Length::Shrink) - .on_press(Message::ModalHide), - Space::new(Length::Fill, Length::Shrink), - ]; - - let ctn = container(column![title, text_box, file_row, modal_btn_row]) - .height(Length::Shrink) - .width(500) - .padding(10) - .style(style::Container::Frame); - - return Modal::new(content.padding(10), ctn) - .on_blur(Message::ModalHide) - .into(); - } - - if let Some(err) = &self.error_modal { - error_view(err, content).into() - } else { - container(content).height(Length::Fill).padding(10).into() - } - } - - #[allow(clippy::too_many_lines)] - fn apply_selection_modal( - &self, - device: &Phone, - settings: &Settings, - packages: &[PackageRow], - ) -> Element { - const PACK_NO_USER_MSG: &str = "`selected_packages` implies a user must be selected"; - - // 5 element slice is cheap - let mut summaries = Removal::CATEGORIES.map(SummaryEntry::from); - for p in packages.iter().filter(|p| p.selected) { - let summary = &mut summaries[p.removal as usize]; - match p.state { - PackageState::Uninstalled | PackageState::Disabled => summary.restore += 1, - _ => summary.discard += 1, - } - } - - let radio_btn_users = device.user_list.iter().filter(|&u| !u.protected).fold( - row![].spacing(10), - |row, &user| { - row.push( - radio( - format!("{}", user.clone()), - user, - self.selected_user, - Message::ModalUserSelected, - ) - .size(24), - ) - }, - ); - - let title_ctn = - container(row![text("Review your selection").size(24)].align_items(Alignment::Center)) - .width(Length::Fill) - .style(style::Container::Frame) - .padding([10, 0, 10, 0]) - .center_y() - .center_x(); - - let users_ctn = container(radio_btn_users) - .padding(10) - .center_x() - .style(style::Container::Frame); - - let explaination_ctn = container( - row![ - text("The action for the selected user will be applied to all other users") - .style(style::Text::Danger), - tooltip( - text("\u{EA0C}") - .font(ICONS) - .width(22) - .horizontal_alignment(alignment::Horizontal::Center) - .style(style::Text::Commentary), - "Let's say you choose user 0. If a selected package on user 0\n\ - is set to be uninstalled and if this same package is disabled on user 10,\n\ - then the package on both users will be uninstalled.", - tooltip::Position::Top, - ) - .gap(20) - .padding(10) - .style(style::Container::Tooltip) - ] - .spacing(10), - ) - .center_x() - .padding(10) - .style(style::Container::BorderedFrame); - - let modal_btn_row = row![ - button(text("Cancel")).on_press(Message::ModalHide), - horizontal_space(), - button(text("Apply")).on_press(Message::ModalValidate), - ] - .padding([0, 15, 10, 10]); - - let recap_view = summaries - .iter() - .fold(column![].spacing(6).width(Length::Fill), |col, r| { - col.push(recap(settings, r)) - }); - - let selected_pkgs_ctn = container( - container( - scrollable( - container( - if self - .selected_packages - .iter() - .any(|s| s.0 == self.selected_user.expect(PACK_NO_USER_MSG).index) - { - self.selected_packages - .iter() - .filter(|s| { - s.0 == self.selected_user.expect(PACK_NO_USER_MSG).index - }) - .fold( - column![].spacing(6).width(Length::Fill), - |col, selection| { - col.push( - row![ - row![text( - self.phone_packages[selection.0][selection.1] - .removal - )] - .width(120), - row![text( - self.phone_packages[selection.0][selection.1] - .uad_list - )] - .width(50), - row![text( - self.phone_packages[selection.0][selection.1] - .name - .clone() - ),] - .width(540), - horizontal_space(), - row![match self.phone_packages[selection.0] - [selection.1] - .state - { - PackageState::Enabled => - if settings.device.disable_mode { - text("Disable") - .style(style::Text::Danger) - } else { - text("Uninstall") - .style(style::Text::Danger) - }, - PackageState::Disabled => - text("Enable").style(style::Text::Ok), - PackageState::Uninstalled => - text("Restore").style(style::Text::Ok), - PackageState::All => text("Impossible") - .style(style::Text::Danger), - },] - .width(70), - ] - .width(Length::Fill) - .spacing(20), - ) - }, - ) - } else { - column![text("No packages selected for this user")] - .align_items(Alignment::Center) - .width(Length::Fill) - }, - ) - .padding(10) - .width(Length::Fill), - ) - .style(style::Scrollable::Description), - ) - .width(Length::Fill) - .style(style::Container::Frame), - ) - .width(Length::Fill) - .max_height(150) - .padding([0, 10, 0, 10]); - - container( - if device.user_list.iter().filter(|&u| !u.protected).count() > 1 - && settings.device.multi_user_mode - { - column![ - title_ctn, - users_ctn, - row![explaination_ctn].padding([0, 10, 0, 10]), - container(recap_view).padding(10), - selected_pkgs_ctn, - modal_btn_row, - ] - .spacing(10) - .align_items(Alignment::Center) - } else if !settings.device.multi_user_mode { - column![ - title_ctn, - users_ctn, - container(recap_view).padding(10), - selected_pkgs_ctn, - modal_btn_row, - ] - .spacing(10) - .align_items(Alignment::Center) - } else { - column![ - title_ctn, - container(recap_view).padding(10), - selected_pkgs_ctn, - modal_btn_row, - ] - .spacing(10) - .align_items(Alignment::Center) - }, - ) - .width(900) - .height(Length::Shrink) - .max_height(700) - .style(style::Container::Background) - .into() - } - fn filter_package_lists(&mut self) { - let list_filter: UadList = self.selected_list.expect("UAD-list type must be selected"); - let package_filter: PackageState = self - .selected_package_state - .expect("pack-state must be selected"); - let removal_filter: Removal = self - .selected_removal - .expect("removal recommendation must be selected"); - - self.filtered_packages = self.phone_packages - [self.selected_user.expect("User must be selected").index] - .iter() - // we must filter the indices associated with pack-rows, - // that's why `enumerate` is before `filter`. - .enumerate() - .filter(|(_, p)| { - (list_filter == UadList::All || p.uad_list == list_filter) - && (package_filter == PackageState::All || p.state == package_filter) - && (removal_filter == Removal::All || p.removal == removal_filter) - && (self.input_value.is_empty() || p.name.contains(&self.input_value)) - }) - .map(|(i, _)| i) - .collect(); - } - #[expect(clippy::unused_async, reason = "1 call-site")] - async fn load_packages>( - uad_list: PackageHashMap, - device_serial: S, - user_list: Vec, - ) -> Vec> { - let serial = device_serial.as_ref(); - if user_list.len() <= 1 { - vec![fetch_packages(&uad_list, serial, None)] - } else { - user_list - .iter() - .map(|user| fetch_packages(&uad_list, serial, Some(user.id))) - .collect() - } - } - - #[expect(clippy::unused_async, reason = "1 call-site")] - async fn init_apps_view(remote: bool, phone: Phone) -> (PackageHashMap, UadListState) { - let uad_lists = load_debloat_lists(remote); - match uad_lists { - Ok(list) => { - if phone.adb_id.is_empty() { - warn!("AppsView ready but no phone found"); - } - (list, UadListState::Done) - } - Err(local_list) => { - error!( - "Error loading remote debloat list for the phone. Fallback to embedded (and outdated) list" - ); - (local_list, UadListState::Failed) - } - } - } -} - -fn error_view<'a>( - error: &'a str, - content: Column<'a, Message, Theme, Renderer>, -) -> Modal<'a, Message, Theme, Renderer> { - let title_ctn = container( - row![text("Failed to perform ADB operation").size(24)].align_items(Alignment::Center), - ) - .width(Length::Fill) - .style(style::Container::Frame) - .padding([10, 0, 10, 0]) - .center_y() - .center_x(); - - let modal_btn_row = row![ - button( - text("Close") - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) - .width(Length::Fill) - .on_press(Message::ModalHide) - ] - .padding([10, 0, 0, 0]); - - let text_box = scrollable(text(error).width(Length::Fill)).height(400); - - let ctn = container(column![title_ctn, text_box, modal_btn_row]) - .height(Length::Shrink) - .max_height(700) - .padding(10) - .style(style::Container::Frame); - - Modal::new(content, ctn).on_blur(Message::ModalHide) -} - -fn waiting_view<'a>( - displayed_text: &(impl ToString + ?Sized), - btn: Option>, - text_style: style::Text, -) -> Element<'a, Message, Theme, Renderer> { - let col = column![] - .spacing(10) - .align_items(Alignment::Center) - .push(text(displayed_text.to_string()).style(text_style).size(20)); - - let col = match btn { - Some(btn) => col.push(btn.style(style::Button::Primary).padding([5, 10])), - None => col, - }; - - container(col) - .width(Length::Fill) - .height(Length::Fill) - .center_y() - .center_x() - .style(style::Container::default()) - .into() -} - -fn build_action_pkg_commands( - packages: &[Vec], - device: &Phone, - settings: &DeviceSettings, - selection: (usize, usize), -) -> Vec> { - let pkg = &packages[selection.0][selection.1]; - let wanted_state = pkg.state.opposite(settings.disable_mode); - - let mut commands = vec![]; - for u in device.user_list.iter().filter(|&&u| { - !u.protected && (packages[u.index][selection.1].selected || settings.multi_user_mode) - }) { - let u_pkg = &packages[u.index][selection.1]; - let wanted_state = if settings.multi_user_mode { - wanted_state - } else { - u_pkg.state.opposite(settings.disable_mode) - }; - - let actions = apply_pkg_state_commands(&u_pkg.into(), wanted_state, *u, device); - for (j, action) in actions.into_iter().enumerate() { - let p_info = PackageInfo { - i_user: u.index, - index: selection.1, - removal: pkg.removal.to_string(), - }; - // In the end there is only one package state change - // even if we run multiple adb commands - commands.push(Command::perform( - adb_shell_command( - // this is typically small, - // so it's fine. - device.adb_id.clone(), - action, - CommandType::PackageManager(p_info), - ), - if j == 0 { - Message::ChangePackageState - } else { - |_| Message::Nothing - }, - )); - } - } - commands -} - -fn recap<'a>(settings: &Settings, recap: &SummaryEntry) -> Element<'a, Message, Theme, Renderer> { - container( - row![ - text(recap.category).size(19).width(Length::FillPortion(1)), - vertical_rule(5), - row![ - if settings.device.disable_mode { - text("Disable").style(style::Text::Danger) - } else { - text("Uninstall").style(style::Text::Danger) - }, - horizontal_space(), - text(recap.discard.to_string()).style(style::Text::Danger) - ] - .width(Length::FillPortion(1)), - vertical_rule(5), - row![ - if settings.device.disable_mode { - text("Enable").style(style::Text::Ok) - } else { - text("Restore").style(style::Text::Ok) - }, - horizontal_space(), - text(recap.restore.to_string()).style(style::Text::Ok) - ] - .width(Length::FillPortion(1)) - ] - .spacing(20) - .padding([0, 10, 0, 0]) - .width(Length::Fill) - .align_items(Alignment::Center), - ) - .padding(10) - .width(Length::Fill) - .height(45) - .style(style::Container::Frame) - .into() -} diff --git a/src/gui/views/settings.rs b/src/gui/views/settings.rs deleted file mode 100644 index 80f3e69..0000000 --- a/src/gui/views/settings.rs +++ /dev/null @@ -1,577 +0,0 @@ -use crate::core::{ - config::{BackupSettings, Config, DeviceSettings, GeneralSettings}, - helpers::button_primary, - save::{backup_phone, list_available_backup_user, list_available_backups, restore_backup}, - sync::{ - AdbError, CommandType, Phone, User, adb_shell_command, get_android_sdk, supports_multi_user, - }, - theme::Theme, - utils::{ - DisplayablePath, Error, NAME, export_packages, generate_backup_name, open_folder, open_url, - string_to_theme, - }, -}; -use crate::gui::{ - style, - views::list::{List as AppsView, PackageInfo}, - widgets::modal::Modal, - widgets::navigation_menu::ICONS, - widgets::package_row::PackageRow, - widgets::text, -}; -use iced::widget::{Space, button, checkbox, column, container, pick_list, radio, row, scrollable}; -use iced::{Alignment, Element, Length, Renderer, alignment}; -use std::path::PathBuf; - -#[derive(Debug, Clone)] -pub enum PopUpModal { - ExportUninstalled, -} - -#[derive(Debug, Clone)] -pub struct Settings { - pub general: GeneralSettings, - pub device: DeviceSettings, - is_loading: bool, - modal: Option, -} - -impl Default for Settings { - fn default() -> Self { - Self { - general: Config::load_configuration_file().general, - device: DeviceSettings::default(), - is_loading: false, - modal: None, - } - } -} - -#[derive(Debug, Clone)] -pub enum Message { - LoadDeviceSettings, - ExpertMode(bool), - DisableMode(bool), - MultiUserMode(bool), - ApplyTheme(Theme), - UrlPressed(PathBuf), - BackupSelected(DisplayablePath), - BackupDevice, - RestoreDevice, - RestoringDevice(Result), - DeviceBackedUp(Result), - ChooseBackUpFolder, - FolderChosen(Result), - ExportPackages, - PackagesExported(Result), - ModalHide, -} - -impl Settings { - #[allow(clippy::too_many_lines)] - pub fn update( - &mut self, - phone: &Phone, - packages: &[Vec], - nb_running_async_adb_commands: &mut u32, - msg: Message, - selected_user: Option, - ) -> iced::Command { - match msg { - Message::ModalHide => { - self.modal = None; - iced::Command::none() - } - Message::ExpertMode(toggled) => { - self.general.expert_mode = toggled; - debug!("Config change: {:?}", self); - Config::save_changes(self, &phone.adb_id); - iced::Command::none() - } - Message::DisableMode(toggled) => { - if phone.android_sdk >= 23 { - self.device.disable_mode = toggled; - debug!("Config change: {:?}", self); - Config::save_changes(self, &phone.adb_id); - } - iced::Command::none() - } - Message::MultiUserMode(toggled) => { - self.device.multi_user_mode = toggled; - debug!("Config change: {:?}", self); - Config::save_changes(self, &phone.adb_id); - iced::Command::none() - } - Message::ApplyTheme(theme) => { - self.general.theme = theme.to_string(); - debug!("Config change: {:?}", self); - Config::save_changes(self, &phone.adb_id); - iced::Command::none() - } - Message::UrlPressed(url) => { - open_url(url); - iced::Command::none() - } - Message::LoadDeviceSettings => { - let backups = - list_available_backups(&self.general.backup_folder.join(&phone.adb_id)); - let backup = BackupSettings { - backups: backups.clone(), - selected: backups.first().cloned(), - users: phone.user_list.clone(), - selected_user: phone.user_list.first().copied(), - backup_state: String::default(), - }; - match Config::load_configuration_file() - .devices - .iter() - .find(|d| d.device_id == phone.adb_id) - { - Some(device) => { - self.device.clone_from(device); - self.device.backup = backup; - } - None => { - self.device = DeviceSettings { - device_id: phone.adb_id.clone(), - multi_user_mode: supports_multi_user(phone), - disable_mode: false, - backup, - } - } - }; - iced::Command::none() - } - Message::BackupSelected(d_path) => { - self.device.backup.selected = Some(d_path.clone()); - self.device.backup.users = list_available_backup_user(d_path); - iced::Command::none() - } - Message::BackupDevice => iced::Command::perform( - backup_phone( - phone.user_list.clone(), - self.device.device_id.clone(), - packages.to_vec(), - ), - Message::DeviceBackedUp, - ), - Message::DeviceBackedUp(is_backed_up) => { - match is_backed_up { - Ok(_) => { - info!("[BACKUP] Backup successfully created"); - self.device.backup.backups = list_available_backups( - &self.general.backup_folder.join(phone.adb_id.clone()), - ); - self.device.backup.selected = self.device.backup.backups.first().cloned(); - } - Err(err) => { - error!("[BACKUP FAILED] Backup creation failed: {:?}", err); - } - } - iced::Command::none() - } - Message::RestoreDevice => match restore_backup(phone, packages, &self.device) { - Ok(r_packages) => { - let mut commands = vec![]; - *nb_running_async_adb_commands = 0; - for p in &r_packages { - let p_info = PackageInfo { - i_user: 0, - index: p.index, - removal: "RESTORE".to_string(), - }; - for command in p.commands.clone() { - *nb_running_async_adb_commands += 1; - commands.push(iced::Command::perform( - // WARNING: THIS IS INSECURE! - // If a user "A" restores a backup from a malicious user "B", - // then B could run arbitrary high-privilege cmds, - // on A's Android device! - adb_shell_command( - phone.adb_id.clone(), - command, - CommandType::PackageManager(p_info.clone()), - ), - Message::RestoringDevice, - )); - } - } - if r_packages.is_empty() { - if get_android_sdk(&phone.adb_id) == 0 { - self.device.backup.backup_state = "Device is not connected".to_string(); - } else { - self.device.backup.backup_state = - "Device state is already restored".to_string(); - } - } - info!( - "[RESTORE] Restoring backup {}", - self.device.backup.selected.as_ref().unwrap() - ); - iced::Command::batch(commands) - } - Err(e) => { - self.device.backup.backup_state.clone_from(&e); - error!("{} - {}", self.device.backup.selected.as_ref().unwrap(), e); - iced::Command::none() - } - }, - // Trigger an action in mod.rs (Message::SettingsAction(msg)) - Message::RestoringDevice(_) => iced::Command::none(), - Message::FolderChosen(result) => { - self.is_loading = false; - - if let Ok(path) = result { - self.general.backup_folder = path; - Config::save_changes(self, &phone.adb_id); - #[expect(unused_must_use, reason = "side-effect")] - { - self.update( - phone, - packages, - nb_running_async_adb_commands, - Message::LoadDeviceSettings, - selected_user, - ); - } - } - iced::Command::none() - } - Message::ChooseBackUpFolder => { - if self.is_loading { - iced::Command::none() - } else { - self.is_loading = true; - iced::Command::perform(open_folder(), Message::FolderChosen) - } - } - Message::ExportPackages => iced::Command::perform( - export_packages(selected_user.unwrap_or_default(), packages.to_vec()), - Message::PackagesExported, - ), - Message::PackagesExported(exported) => { - match exported { - Ok(_) => self.modal = Some(PopUpModal::ExportUninstalled), - Err(err) => error!("Failed to export list of uninstalled packages: {:?}", err), - } - iced::Command::none() - } - } - } - - #[allow(clippy::too_many_lines)] - pub fn view(&self, phone: &Phone, apps_view: &AppsView) -> Element { - let radio_btn_theme = Theme::ALL - .iter() - .fold(row![].spacing(10), |column, option| { - column.push( - radio( - format!("{}", option.clone()), - *option, - Some(string_to_theme(&self.general.theme)), - Message::ApplyTheme, - ) - .size(24), - ) - }); - let theme_ctn = container(radio_btn_theme) - .padding(10) - .width(Length::Fill) - .height(Length::Shrink) - .style(style::Container::Frame); - - let expert_mode_checkbox = checkbox( - "Allow to uninstall packages marked as \"unsafe\" (I KNOW WHAT I AM DOING)", - self.general.expert_mode, - ) - .on_toggle(Message::ExpertMode) - .style(style::CheckBox::SettingsEnabled); - - let expert_mode_descr = - text("Most unsafe packages are known to bootloop the device if removed.") - .style(style::Text::Commentary); - - let choose_backup_descr = text("Note: If you have previous backups, you will need to transfer them manually to newly changed backup folder to be able to use Restore functionality") - .style(style::Text::Commentary); - - let choose_backup_btn = button(text("\u{E930}").font(ICONS)) - .padding([5, 10]) - .on_press(Message::ChooseBackUpFolder) - .style(style::Button::Primary); - - let choose_backup_row = row![ - choose_backup_btn, - "Choose backup folder", - Space::new(Length::Fill, Length::Shrink), - "Current folder: ", - text(self.general.backup_folder.to_string_lossy()) - ] - .spacing(10) - .align_items(Alignment::Center); - - let general_ctn = container( - column![ - expert_mode_checkbox, - expert_mode_descr, - choose_backup_row, - choose_backup_descr, - ] - .spacing(10), - ) - .padding(10) - .width(Length::Fill) - .height(Length::Shrink) - .style(style::Container::Frame); - - let warning_ctn = container( - row![ - text("The following settings only affect the currently selected device:") - .style(style::Text::Danger), - text(phone.model.clone()), - Space::new(Length::Fill, Length::Shrink), - text(phone.adb_id.clone()).style(style::Text::Commentary) - ] - .spacing(7), - ) - .padding(10) - .width(Length::Fill) - .style(style::Container::BorderedFrame); - - let multi_user_mode_descr = row![ - text("This will not affect the following protected work profile users: ") - .style(style::Text::Commentary), - text( - phone - .user_list - .iter() - .filter(|&u| u.protected) - .map(|u| u.id.to_string()) - .collect::>() - .join(", ") - ) - .style(style::Text::Danger) - ]; - - let multi_user_mode_checkbox = checkbox( - "Affect all the users of the device (not only the selected user)", - self.device.multi_user_mode, - ) - .on_toggle(Message::MultiUserMode) - .style(style::CheckBox::SettingsEnabled); - - let disable_checkbox_style = if phone.android_sdk >= 23 { - style::CheckBox::SettingsEnabled - } else { - style::CheckBox::SettingsDisabled - }; - - let disable_mode_descr = - text("In some cases, it can be better to disable a package instead of uninstalling it") - .style(style::Text::Commentary); - - let unavailable_btn = button(text("Unavailable").size(14)) - .on_press(Message::UrlPressed(PathBuf::from( - "https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/FAQ#\ - why-is-the-disable-mode-setting-not-available-for-my-device", - ))) - .height(22) - .style(style::Button::Unavailable); - - // Disabling package without root isn't really possible before Android Oreo (8.0) - // see https://github.com/Universal-Debloater-Alliance/universal-android-debloater/wiki/ADB-reference - let disable_mode_checkbox = checkbox( - "Clear and disable packages instead of uninstalling them", - self.device.disable_mode, - ) - .on_toggle(Message::DisableMode) - .style(disable_checkbox_style); - - let disable_setting_row = if phone.android_sdk >= 23 { - row![ - disable_mode_checkbox, - Space::new(Length::Fill, Length::Shrink), - ] - .width(Length::Fill) - } else { - row![ - disable_mode_checkbox, - Space::new(Length::Fill, Length::Shrink), - unavailable_btn, - ] - .width(Length::Fill) - }; - - let device_specific_ctn = container( - column![ - multi_user_mode_checkbox, - multi_user_mode_descr, - disable_setting_row, - disable_mode_descr, - ] - .spacing(10), - ) - .padding(10) - .width(Length::Fill) - .height(Length::Shrink) - .style(style::Container::Frame); - - let backup_pick_list = pick_list( - self.device.backup.backups.clone(), - self.device.backup.selected.clone(), - Message::BackupSelected, - ) - .padding(6); - - let backup_btn = - button_primary(text("Backup").horizontal_alignment(alignment::Horizontal::Center)) - .on_press(Message::BackupDevice) - .width(77); - - let restore_btn = |enabled| { - if enabled { - button(text("Restore").horizontal_alignment(alignment::Horizontal::Center)) - .padding([5, 10]) - .on_press(Message::RestoreDevice) - .width(77) - } else { - button( - text("No backup") - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center), - ) - .padding([5, 10]) - .width(77) - } - }; - - let locate_backup_btn = if self.device.backup.backups.is_empty() { - button_primary("Open backup directory") - } else { - button_primary("Open backup directory").on_press(Message::UrlPressed( - self.general.backup_folder.join(phone.adb_id.clone()), - )) - }; - - let export_btn = button_primary("Export").on_press(Message::ExportPackages); - - let backup_row = row![ - backup_btn, - "Backup the current state of the phone", - Space::new(Length::Fill, Length::Shrink), - locate_backup_btn, - ] - .spacing(10) - .align_items(Alignment::Center); - - let restore_row = if self.device.backup.backups.is_empty() { - row![] - } else { - row![ - restore_btn(true), - "Restore the state of the device", - Space::new(Length::Fill, Length::Shrink), - text(self.device.backup.backup_state.clone()).style(style::Text::Danger), - backup_pick_list, - ] - .spacing(10) - .align_items(Alignment::Center) - }; - - let no_device_ctn = || { - container(text("No device detected").style(style::Text::Danger)) - .padding(10) - .width(Length::Fill) - .style(style::Container::BorderedFrame) - }; - - let content = if phone.adb_id.is_empty() { - column![ - text("Theme").size(26), - theme_ctn, - text("General").size(26), - general_ctn, - text("Current device").size(26), - no_device_ctn(), - text("Backup / Restore").size(26), - no_device_ctn(), - ] - .width(Length::Fill) - .spacing(20) - } else { - let export_row = row![ - export_btn, - "Export uninstalled packages with their description", - Space::new(Length::Fill, Length::Shrink), - text(format!( - "Selected: user {}", - apps_view.selected_user.unwrap_or_default().id - )), - ] - .spacing(10) - .align_items(Alignment::Center); - - let backup_restore_ctn = - container(column![backup_row, restore_row, export_row].spacing(10)) - .padding(10) - .width(Length::Fill) - .height(Length::Shrink) - .style(style::Container::Frame); - - column![ - text("Theme").size(26), - theme_ctn, - text("General").size(26), - general_ctn, - text("Current device").size(26), - warning_ctn, - device_specific_ctn, - text("Backup / Restore").size(26), - backup_restore_ctn, - ] - .width(Length::Fill) - .spacing(20) - }; - - if let Some(PopUpModal::ExportUninstalled) = self.modal { - let title = container(row![text("Success").size(24)].align_items(Alignment::Center)) - .width(Length::Fill) - .style(style::Container::Frame) - .padding([10, 0, 10, 0]) - .center_y() - .center_x(); - - let text_box = row![ - text(format!("Exported uninstalled packages into file.\nFile is exported in same directory where {NAME} is located.")).width(Length::Fill), - ].padding(20); - - let file_row = row![ - text(generate_backup_name(chrono::Local::now())).style(style::Text::Commentary) - ] - .padding(20); - - let modal_btn_row = row![ - Space::new(Length::Fill, Length::Shrink), - button(text("Close").width(Length::Shrink)) - .width(Length::Shrink) - .on_press(Message::ModalHide), - Space::new(Length::Fill, Length::Shrink), - ]; - - let ctn = container(column![title, text_box, file_row, modal_btn_row]) - .height(Length::Shrink) - .width(500) - .padding(10) - .style(style::Container::Frame); - - return Modal::new(content.padding(10), ctn) - .on_blur(Message::ModalHide) - .into(); - } - - container(scrollable(content)) - .padding(10) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} diff --git a/src/gui/widgets/text.rs b/src/gui/widgets/text.rs deleted file mode 100644 index 5e33a62..0000000 --- a/src/gui/widgets/text.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![allow( - clippy::disallowed_types, - reason = "this is the replacement that enforces advanced shaping for disallowed [`iced::widget::Text`]" -)] - -use std::borrow::Cow; - -use iced::widget::Text; - -// Creates a new Text widget with advanced shaping. -pub fn text<'a, Theme, Renderer>(text: impl Into>) -> Text<'a, Theme, Renderer> -where - Theme: iced::widget::text::StyleSheet, - Renderer: iced::advanced::text::Renderer, -{ - Text::new(text).shaping(iced::widget::text::Shaping::Advanced) -}