Skip to content

Add Android 10/11 (API 29/30) support - #5

Open
dsingenalted wants to merge 1 commit into
LinerSRT:masterfrom
dsingenalted:android_10-11_support
Open

Add Android 10/11 (API 29/30) support#5
dsingenalted wants to merge 1 commit into
LinerSRT:masterfrom
dsingenalted:android_10-11_support

Conversation

@dsingenalted

Copy link
Copy Markdown

Problem

The app required Android 12 (API 31) as minimum SDK because it relied exclusively on ISensorPrivacyManager, which only exists as a system service starting from Android 11 and was made a public API in Android 12.

Simply lowering minSdk to 29 is not sufficient - on stock Android 10, SystemServiceHelper.getSystemService("sensor_privacy") returns null, causing ShizukuBinderWrapper(null) to throw a NullPointerException on service startup. The app would crash immediately on first use.

This PR provides a proper compatibility implementation that handles each API level correctly.

Solution

SensorPrivacyCompat is implemented - a compatibility layer that selects the appropriate sensor-blocking mechanism based on the running Android version, with conditional initialization of ISensorPrivacyManager guarded by API version checks.


How it works per API level

API 31+ (Android 12+) - unchanged behavior. Uses ISensorPrivacyManager.setSensorPrivacy() via Shizuku for a true global sensor kill-switch.

API 30 (Android 11) - ISensorPrivacyManager exists as a hidden API but with a simpler 4-method interface where setSensorPrivacy(boolean) is at transaction code #4, different from the API 31 AIDL. Accessed via raw IBinder.transact() to avoid interface mismatch.

API 29 (Android 10) - two-tier fallback:

  1. First attempts the sensor_privacy system service via the same raw transact call (works on custom ROMs such as xiaomi.eu).
  2. If unavailable, falls back to IAppOpsService.setMode() (transaction #14 per AOSP android-10.0.0 source) to revoke camera, microphone, and location ops per package.

Implementation details

Op mode save/restore (API 29 AppOps path)
Before blocking, the current op mode of every package is read via IAppOpsService.checkOperation() (transaction #1) and saved to SharedPreferences as a JSON map. On restore, exact saved values are written back. This ensures permissions previously denied by the user are not accidentally re-granted after disabling sensor privacy.

Global vs per-app blocking on API 29

  • QS tile ("global" toggle): iterates all installed packages, saves their modes, sets MODE_IGNORED for all sensor ops. Runs on a background thread to avoid blocking the UI.
  • BlockingService (per-app): only modifies ops for the foreground package. Tracks the last blocked package to restore its ops when a non-blocked app comes to foreground.

I have tested on Android 10 and 11 - the sensors disabled successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant