https://github.com/chickendrop89/hyperos-accessibility-fix
Stop HyperOS from randomly disabling accessibillity services
https://github.com/chickendrop89/hyperos-accessibility-fix
a11y accessibility activitymanager android hyperos ksu magisk magisk-module miui mksh xiaomi
Last synced: 2 days ago
JSON representation
Stop HyperOS from randomly disabling accessibillity services
- Host: GitHub
- URL: https://github.com/chickendrop89/hyperos-accessibility-fix
- Owner: chickendrop89
- License: gpl-2.0
- Created: 2026-06-07T18:05:18.000Z (8 days ago)
- Default Branch: main
- Last Pushed: 2026-06-07T18:34:52.000Z (8 days ago)
- Last Synced: 2026-06-07T20:03:32.633Z (8 days ago)
- Topics: a11y, accessibility, activitymanager, android, hyperos, ksu, magisk, magisk-module, miui, mksh, xiaomi
- Language: Shell
- Homepage:
- Size: 19.5 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# hyperos-accessibility-fix
Stop HyperOS from randomly disabling accessibility services
## What's happening
On Android, when an accessibility app is force-stopped via `ActivityManager`, the [accessibility permission of the app is stripped](https://cs.android.com/android/platform/superproject/+/android-16.0.0_r4:frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java;drc=7f9ce6b127e5d17d7a2ccef1ccc21db212f60084;l=1050).
```java
boolean onPackagesForceStoppedLocked(String[] packages, AccessibilityUserState userState) {
final Set packageSet = Set.of(packages);
final ArrayList continuousServices = userState.mInstalledServices.stream()
.filter(s -> (s.flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON) == FLAG_REQUEST_ACCESSIBILITY_BUTTON)
.map(AccessibilityServiceInfo::getComponentName)
.filter(name -> packageSet.contains(name.getPackageName()))
.collect(Collectors.toCollection(ArrayList::new));
final boolean enabledServicesChanged = userState.mEnabledServices.removeIf(comp -> {
if (packageSet.contains(comp.getPackageName())) {
userState.getBindingServicesLocked().remove(comp);
userState.getCrashedServicesLocked().remove(comp);
return true;
}
return false;
});
if (enabledServicesChanged) {
persistComponentNamesToSettingLocked(
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
userState.mEnabledServices, userState.mUserId);
}
}
...
```
And HyperOS is hardcoded to trigger a force-stop (not a kill) on
certain events like when the user is entering Ultra Battery Saver (`LockScreenClean`),
and others:
```log
I ActivityManager: Force stopping com.urbandroid.lux appid=10415 user=0: LockScreenClean
D ActivityManager: Force removing proc 8855:com.urbandroid.lux:background/u0a415 (com.urbandroid.lux:background/10415)
```
## How it works
This module installs a background script that monitors the `logcat` `event` stream for force stop events (`Force stopping.*($PKG_PATTERN)`, etc)
with minimal system overhead.
On boot, it checks what accessibility services are enabled, and writes them to `a11y_watchlist.txt`. It also listens for signs of manual
configuration changes (done by user in settings) and updates the watchlist automatically.
When a forced stop of a watched service is detected, the script performs a verification of enabled accessibility services against the local
`a11y_watchlist.txt`. And when the list doesn't match up, the changes (done by `system_server`) are reverted instantly.
This script also runs at `OOM` score `-800` to prevent `LMKD` from killing it in the background. And if it still gets killed under memory pressure,
another (monitor) script (that runs at `-900`) is running in background to restart it (provided it wasn't killed aswell lol)
## Why use background scripts, and not zygisk/xposed?
On my device, these two frameworks cause a range of problems for some reason, so i decided to follow this approach instead.
It's also more minimal this way, having almost no requirements.
## Do they really have minimal system overhead?
After 2 days of uptime, the scripts used only ~160 seconds of CPU time (`USER_HZ=100`) in total since they started.
These background scripts have negligible effect on performance and they won't slow the system down.
```bash
$ getconf CLK_TCK
100
```
```bash
$ cat /proc/7562/stat
7562 (sh) S 1 7562 7562 0 -1 4194560 1303 11306 82 0 3 181 7 25 20 0 1 0 4514 11082203136 720 18446744073709551615 391135674368 391135918392 549159233360 0 0 0 0 6 1208083705 1 0 0 17 0 0 0 0 0 0 391135936512 391135937152 391696969728 549159237033 549159237184 549159237184 549159243753 0
$ cat /proc/7563/stat
7563 (sh) S 1 7563 7563 0 -1 4194304 73566 952234 7750 8335 63 893 1169 3535 20 0 1 0 4515 11065425920 825 18446744073709551615 401645289472 401645533496 549315373280 0 0 0 0 6 1208083705 1 0 0 17 3 0 0 0 0 0 401645551616 401645552256 402234515456 549315376568 549315376704 549315376704 549315383273 0
```
```bash
$ uptime
02:20:46 up 2 days, 6:37, 0 users, load average: 24.01, 11.73, 8.87
```
## Note
- When Ultra Battery Saver is turned on, the accessibility services will still keep running in the background
- Force stopping an app via App Manager will not (permanently) remove it's accessibility permission anymore.
So be careful at what you enable
## Installation:
* [Download the module archive here](https://github.com/chickendrop89/hyperos-accessibility-fix/releases/latest/download/hyperos-accessibility-fix.zip)
* Flash it in magisk app, or using command line
## Requirements
- HyperOS 1.0+ (or any A14+ system)
- KernelSU 1.0.2+
- Magisk 28.0+