At a glance
Minimum Android Android 9 (API 28)
Targets API 37 for targetSdk, API 37 for compileSdk
Licence GPL-3.0-or-later
Languages English, Arabic, Chinese (Simplified), French, Spanish
Network access foss: one surface only — the optional Extension Store. store also links Google Play Billing
Trackers, ads, telemetry None

Privilege engines

Thor never talks to the system directly. Every privileged action goes through one SystemGateway interface with three interchangeable implementations, so a feature either works in your chosen mode or fails honestly. It never silently does something different.

Three ways to grant power

Root — Thor talks to your root shell through Odin, its own maintained fork of libsu. Works with Magisk, KernelSU, KernelSU Next and APatch. Your root manager shows the usual grant prompt the first time.

Shizuku — no root required. Install the Shizuku app, start its server over ADB or wireless debugging (Android 11 and newer can pair without a computer), then grant Thor permission when it asks. Thor runs as the shell user: everything adb shell can do, Thor can do.

Dhizuku — Device Owner mode, for people who want elevated control on a stock, unrooted, unpaired device. This is the most demanding setup: the device must have zero accounts on it when you enrol, because Android refuses dpm set-device-owner if even one account exists. Signing into Google afterwards also breaks it.

Automatic fallback

You can pin a preferred mode in Settings, or leave it on auto. Either way the resolution order is fixed:

Resolution order

your preference (if available) → Root → Shizuku → Dhizuku → no privilege

Thor re-probes when Shizuku’s binder arrives and when you answer its permission prompt, so granting Shizuku permission takes effect without restarting Thor. A binder that dies is logged but does not trigger a re-probe. The Work Mode selector only appears in Settings when more than one mode is actually available — there is nothing to choose between otherwise.

Settings, showing the Work Mode selector with more than one privilege engine available.
Work Mode is only offered when there is a real choice to make.

What each mode can do

Action Root Shizuku Dhizuku
Freeze and unfreeze Yes Yes Yes
Suspend and unsuspend Yes Yes Yes
Force stop Yes Yes Yes
Clear cache Yes Yes Yes
Clear app data Yes Yes Yes
Restrict background activity Yes Yes Yes
Uninstall Yes Yes Yes
Install and sideload Yes Yes Yes
Fix Store (reinstall as Play) Yes Yes Yes
Grant and revoke permissions Yes Yes Limited
Custom shell for extensions Yes Yes Yes
Reboot device Yes No No
Show per-app cache size Yes No No
Export split APKs Yes No No

Four rows are not uniform, and those are the ones worth stating plainly rather than burying:

  • Reboot is Root-only. Shizuku and Dhizuku return an explicit error rather than pretending.
  • Cache size reads as 0 under Shizuku and Dhizuku. Measuring it needs du on the app’s private directory, which only root can reach. The number is honest but useless in those modes.
  • Split-APK export and privileged file copy are Root-only and fail with “Root required” rather than producing a partial file.
  • Dhizuku permission grants can be refused on multi-user devices, because the Device Owner runs as user 0 and may not hold INTERACT_ACROSS_USERS. Thor surfaces the real failure rather than silently mutating the wrong user’s copy.

The hidden-API bypass

Shizuku and Dhizuku need Android’s hidden APIs (IPackageManager, IActivityManager, IAppOpsService) when a shell command is not enough. Thor unseals them with a small bypass module built on VMRuntime.setHiddenApiExemptions, scoped to four package prefixes and no more. Root does not need it at all.

Most privileged actions are shell-first with a reflection fallback, which is why Thor keeps working across OEM builds that move or remove framework internals. Two exceptions are deliberate: Shizuku tries reflection first when freezing a preinstalled app, because pm is ordinary userspace an OEM can lock down while the binder call names its target state explicitly; and Root suspends only through reflection, never through pm suspend, because a root-shell suspension records the suspender as a package that does not exist and the paused-app dialog then crashes.

App installer

Thor registers as an installer, so you can share or open a package file from anywhere — a browser, a file manager, another app — and Thor’s bottom sheet takes over.

Every bundle format, handled

You hand it Thor does
.apk Installs it directly
.xapk (APKPure) Reads manifest.json, picks the right splits, installs them as one session
.apkm (APKMirror) Extracts every inner APK, base first, installs as one session
.apks (bundletool) Sorts entries base-first and installs as one session
.apkp Recognised as a bundle and handled the same way

Bundle detection does not trust the file extension alone. Thor looks inside the zip for a top-level AndroidManifest.xml and for bundle sidecars, so an .apk that happens to contain a nested APK is not mistaken for a bundle, and a mislabelled bundle still installs.

Install options

  • Downgrade — install an older version over a newer one. Requires a privilege mode, and is blocked with a clear message on a plain unprivileged install, because the OS will simply refuse it.
  • Play attribution — with Auto Reinstall switched on, a privileged install records com.android.vending as the installing app. There is no free-text chooser; the switch is the whole control.
  • External installer — hand the file to any other installer app instead. This is the escape hatch when you have no privilege and want the system dialog.
  • No privilege at all — Thor still installs through the standard PackageInstaller. You just get Android’s own confirmation dialog, and no downgrade.

Fix Store

Fix Store makes Android believe an app came from the Play Store.

Thor reads the app’s own installed APK paths — the single APK, or every split if it is a bundle — straight off the device, then reinstalls those exact files with the installer record set to com.android.vending. Nothing is downloaded and nothing is replaced. It is the same app you already have, reinstalled from itself with a different name on the receipt.

Why that matters: plenty of apps ask Android who installed them and behave differently when the answer is not Play. Licence verification fails, expansion files will not download, some DRM refuses to start, and some apps simply decline to update. Fix Store makes the system record say what those checks expect.

It works in all three privilege modes. Thor refuses to do it to itself.

Auto Reinstall

Optional. When it is on, Thor watches for package installs and updates and reassigns the installer record to Play in the background — a lighter operation than Fix Store, since it only touches the record and never the APK. It needs a privilege mode, and it skips packages already attributed to Play.

Freezer and debloat

The part of Thor that does the most good and carries the most risk, so it is also the part with the most guardrails.

Freeze, suspend and force-stop are three different things

This is the single most common confusion, so here it is in a table:

Action What you see Survives reboot How to undo
Force stop Nothing. The icon is unchanged No — the app restarts on its next trigger It undoes itself
Freeze The app disappears from the launcher entirely Yes Unfreeze
Suspend The icon stays, greyed out; tapping shows Android’s “app paused” dialog Yes Unfreeze

Force-stop is momentary: an alarm, a job or a push message brings the app straight back. Freeze and Suspend are persistent states. Which of the two Thor uses is a single global Freezer setting.

Under the hood, freezing a user app disables it. Freezing a system app switches it off in place as well — the package stays installed and its data stays on disk. Some OEM builds refuse to let anything but root disable their own preinstalled packages; where Thor meets that refusal under Shizuku, it falls back to removing the app for your Android user with pm uninstall -k --user. The -k is the whole point: it is DELETE_KEEP_DATA, and the app’s data directories keep their inodes across the round trip. A runtime permission measured across the same round trip came back granted with its flags unchanged — one permission, granted from the shell rather than by tapping Allow, on one platform build, and app-ops were never measured, so read it for the scope it has. That fallback is reached only where the platform actually refused. Under Root it is never reached at all.

The watchlist

Add apps to the Freezer watchlist, then freeze or unfreeze the whole set in one action from the app, a launcher shortcut, or the Quick Settings tile. Up to five apps are processed at once, with a live progress counter.

The Freezer, with active apps and frozen apps listed side by side.
The watchlist is the unit most of the Freezer acts on.

Freeze profiles

Named groups of apps that freeze and unfreeze together, independently of the main watchlist. An app can belong to several profiles. Useful for “work”, “games”, or “the stuff that eats my battery on a trip”.

Auto-freeze on screen off

When this is enabled, Thor freezes the whole watchlist as soon as the screen turns off and the lock screen is engaged. The keyguard check is deliberate: freezing apps while you are still using the device would be actively harmful. While a run is still going, further screen-off events are ignored rather than stacked, so rapid on and off cycles cannot pile several batches onto the same privileged shell.

Quick Settings tile

A one-tap freeze in the notification shade. Opening the shade counts how many watchlist apps are currently freezable and shows the number as the tile subtitle; tapping freezes them. The states are Checking, No privilege, Nothing to freeze, Ready and Working. The tile freezes only — unfreezing is done from the app or from a launcher shortcut.

Home-screen shortcuts

Freezing an app makes it vanish from the launcher. That is the point, and it is also the annoying part, because getting back into it means opening Thor, finding the app, unfreezing it, then finding it in the launcher again.

Pin a shortcut instead and that whole sequence becomes one tap.

How it works. From any user app’s info sheet, choose Add to Home screen. You get a normal launcher shortcut carrying that app’s own icon and name — no Thor badge, nothing to learn. Tap it and Thor unfreezes the app and opens it in one motion. There is no dialog and no visible Thor screen; the launching activity is transparent, so what you see is the app coming up.

Some details worth knowing:

  • The icon tells you the state. While the app is frozen its shortcut icon is drawn in greyscale. Once it is running again the colour comes back. The grey is not a broken icon — it is the app’s real icon, desaturated.
  • It does not re-freeze afterwards. Tapping a shortcut thaws the app and leaves it thawed. If you want it to go back on its own, that is what auto-freeze on screen off is for, and the shortcut icon greys itself again when that happens.
  • It works on unfrozen apps too. If the app is not frozen, the shortcut just launches it, with no privileged call at all.
  • Any user app can be pinned. It does not have to be on the Freezer watchlist. System apps cannot be pinned this way.
  • Two bulk shortcuts are available as well, Freeze all and Unfreeze all, which act on your whole watchlist. They sit on the same long-press menu as Thor’s own icon and can be pinned to the home screen too. They carry their own coloured tiles — blue for freeze, orange for unfreeze — so they are not mistaken for an app.
  • Remove an app from the watchlist and its shortcut is greyed out and deactivated, because Android will not let an app delete a shortcut you pinned. A live shortcut for an app Thor no longer manages could otherwise still drive a freeze from your home screen.
  • Turning the feature on is a single switch in Settings, Add Freezer to launcher, and it needs a privilege engine, since the whole point is unfreezing on tap.

The one requirement outside Thor’s control is your launcher. Pinning is a launcher capability, and a launcher that does not support it simply will not be offered the option.

Safety gating

Thor bundles the Universal Android Debloater package database and consults it before any freeze or uninstall of a system app:

UAD rating What Thor does
Recommended Proceeds normally
Advanced Proceeds normally
Expert Loud warning dialog; you can continue
Unsafe Blocked outright — no override anywhere in the app
Not listed Proceeds normally

The gate is enforced at all six places a freeze can start: single-app tap, adding to the watchlist, batch runs, profile runs, auto-freeze, and batch uninstall. It fails closed — if the UAD data cannot be read at all, every system app is treated as Unsafe and blocked rather than waved through.

Unfreezing is never gated. That is deliberate: if a failed UAD load blocked unfreezing too, one bad data file would strand every frozen system app on the device.

Thor refusing to freeze a system app rated Unsafe, with no way to continue.
Unsafe is blocked, not warned about.

Getting things back

  • User app, frozen — always recoverable, no data loss.
  • System app, frozen — switched off in place, so nothing is removed and nothing is lost. On devices that refuse to switch a preinstalled app off, Thor removes it for your Android user with the data kept on disk, and unfreezing reinstalls the same system APK and reattaches it. Under Root that fallback is never used at all; under Shizuku it is used only where the platform actually refused. Dhizuku has not been converted yet and still removes without keeping data.
  • System app, debloated — recoverable with pm install-existing, as long as the APK is still on the system partition. It is the same file that shipped with your phone, so this is the normal case.
  • The one real trap — an app suspended in one privilege mode cannot always be unsuspended in another. Android only lets the package that suspended an app lift that suspension, and the three engines register under different identities. If you suspend under Root and later switch to Shizuku, those apps may be stuck; switching back and unsuspending there clears it. Root’s unsuspend already clears several known identities, while Shizuku’s and Dhizuku’s clear only their own. This is a known limitation with an open follow-up. The candidate fix is to have every unsuspend path clear all known suspender identities, but no approach has been settled on and no release carries it yet.

Batch operations

Anything Thor does to one app, it does to many.

  • Multi-select — long-press to enter selection mode anywhere in the app list or the Freezer.
  • Batch actions — freeze, unfreeze, suspend, unsuspend, force-stop, clear cache, uninstall, Fix Store, share APKs and export. In the Freezer the selection can also be saved as a profile. Clear data and background restriction are single-app actions only.
  • Live terminal log — most batch runs stream a real-time log that names each app with an X-of-Y counter, so you can see exactly which package failed instead of getting one summary toast. A clean run dismisses itself after two seconds; a run with failures stays open until you close it. Bulk freeze and unfreeze use a compact processed-of-total counter instead, which names no apps at all.
  • Reinstall All — a home-screen card offering to re-attribute, in one pass, every user app whose installer record is neither Play nor Android’s own package installer. Dismissible.
  • Concurrency and conflict handling — bulk freeze and unfreeze run five workers at a time. Starting a freeze while an unfreeze is running cancels the unfreeze first, rather than interleaving two contradictory operations. Multi-select batches from the app list run one app after another.

Blocked (UAD Unsafe) apps are filtered out before the total is counted, so the progress counter reflects what will actually be attempted.

App list, search and insight

Everything in this section works with no privilege at all. That is a selling point worth making loudly: install Thor, grant nothing, and it is still a better app browser than Settings.

Fast by construction

App metadata lives in a local Room database, so the list is on screen immediately at launch instead of waiting on a full PackageManager scan. A background reconciler diffs installs, uninstalls and updates, then applies surgical changes. Install sizes are cached so the expensive storage query does not repeat.

Icons get the same treatment: the full-resolution icon is written to disk once, keyed by package, and later loads decode that file in two passes down to the size actually being drawn instead of asking PackageManager to render the icon again — unless the app has been updated since the file was written.

Finding things

  • Search as you type, matching both display name and package name.
  • Sort by name, size, install date, last updated, version code, version name, target SDK or minimum SDK. Each one is reversible.
  • Filter by:
    • Source — chips generated from the installers actually present on your device (Play Store, F-Droid, sideloaded, and so on).
    • State — active, frozen, suspended.
    • Permission — every runtime permission group present on the device, so you can ask what here can request your camera. Permissions the platform does not treat as dangerous have no group and no chip.
  • Grid or list, remembered separately for the app list and the Freezer.

Status at a glance

Chips and icons mark apps that are frozen, suspended, split-APK installs, debuggable builds, and packages UAD flags as bloat. A system app that a freeze removed for your Android user reads as frozen rather than as a separate state, because Thor folds the installed flag into the same answer.

Home dashboard

Live counts of active, frozen and suspended apps, plus anything from an unknown installer; an install-source distribution chart; the current privilege mode; and quick-action tiles.

Thor's home screen: the active, frozen and suspended counts, the bento grid of quick actions below them, and the install-source chart below that.
The dashboard reads from the same cache the list does, so it is on screen at launch.

Unified app info sheet

Tap any app anywhere and the same sheet appears: icon, name, package, size, status chips, and the actions valid for that app in your current privilege mode. Frozen apps offer to thaw and launch in one tap, so you never land on the “app paused” dialog by accident.

Extensions

Thor can be extended by separate, signed APKs. This is the only Thor feature that uses the network, and only when you open it — the store build additionally links Google Play Billing, which connects to Play on its own. The extensions policy has the full terms.

  • In-app store — browse a catalog of published extensions with author, version, description and verified or LSPosed badges.
  • Verification chain — every downloaded extension passes a fixed sequence of checks before it can even reach the installer: the URL must be non-empty, it must be HTTPS, its host must be one GitHub actually serves releases from, the APK is streamed to disk while its SHA-256 is computed, that hash must match the catalog whenever the catalog pins one, and the APK’s signing certificate must match Thor’s pinned RSA-4096 key. Only then is it handed to the installer. The signer is checked again every time an extension is loaded.
  • Update detection — compares the installed version code against the catalog and offers updates.
  • Per-extension storage — each extension gets an isolated key-value store; extensions cannot read each other’s data.
  • Consent gate — the Extension Manager is locked behind a one-time disclaimer you have to actively acknowledge, including a small arithmetic check, so it cannot be tapped through.
  • Source-only entries — extensions published without a binary show “build it yourself” and have no install button.

Extensions that fail the signature check are listed but never loaded, and provide no functionality.

Personalisation and security

Feature Notes
Asgardian theme Thor’s own palette: green on near-black, a terminal aesthetic. The default. Ships in dark and light.
Material You Optional wallpaper-derived colours. Android 12 and newer.
Dark, light or system Applied instantly, no restart.
AMOLED mode Forces true #000000 backgrounds. Dark theme only — it has no effect in light.
Adaptive layout Bottom bar on phones; navigation rail from 600 dp; two-pane list-detail at 840 dp and above. Landscape phones get their own layout.
Grid or list Remembered independently per screen.
In-app language Switch Thor’s language without changing the device language.
Biometric lock Optional lock over the whole app — nothing inside is visible until you authenticate.

The biometric lock, precisely

It gates app launch, not individual actions, and the session lasts until the process ends. What counts as authentication depends on your Android version. Android 11 and newer accept a strong biometric or your PIN, pattern or password. Android 10 accepts a weak biometric or a device credential. Android 9 accepts a biometric only, because the API 28 prompt has no device-credential path at all — a screen lock on its own will not unlock Thor there.

Thor refuses to arm the lock on a device that cannot satisfy it and tells you exactly what is missing. If a restored backup ever brings the setting back to a device where nothing you could enrol would satisfy the prompt — API 28 with no biometric sensor is the case that exists — Thor turns the lock off itself rather than locking you out. Where enrolling a fingerprint or a screen lock would fix it, the lock stays armed and Thor sends you to enrol instead, because silently dropping a lock you can still open would be a downgrade.

Trust, licence and distribution

  • GPL-3.0-or-later. The full source is the app: no proprietary blob, no hidden module.
  • No ads, no trackers, no telemetry, no analytics SDK. Verifiable in Thor’s own code: exactly one file opens a network connection, and it is the extension store. The store build links Google Play Billing on top of that; the foss build ships a no-op stub in its place.
  • QUERY_ALL_PACKAGES is used for the one thing Thor exists to do — list your installed apps.
  • INTERNET is declared for the extension store, and the manifest comment directly above it says so. Thor’s own code uses it when you open the Extension Manager and at no other time.

Where to get it

Channel Build
Google Play store flavour
IzzyOnDroid foss-release.apk
GitHub Releases foss-release.apk

Thor is not in the main F-Droid repository yet. IzzyOnDroid is a separate repository you add to an F-Droid client, which is a common point of confusion and not something this page will blur. An F-Droid listing is planned. The download page has the details for each channel.

What differs between foss and store: in what the app does, the Support Developer flow. The store build carries Google Play Billing; the foss build ships a no-op stub with billing permanently unavailable and opens the donation links in a browser instead. The packaging differs too: foss takes a -foss version-name suffix, an extra ProGuard rules file, and a locale filter trimming it to the five languages Thor is translated into, while the benchmark build type exists only for store. Every app-management feature is the same code in both.

Reproducible builds

The foss variant is built to be reproducible, and IzzyOnDroid rebuilds it from this source to award its reproducibility badge. That is their check, not my claim. What Play distributes cannot be checked the same way: CI uploads an app bundle rather than an APK, so Play generates and signs the device APKs itself and there is no file of mine to compare against. Baseline profiles are deliberately kept out of the build entirely, because they change the emitted bytecode and would break that verification.

Supporting development

Thor is written by one person. Nothing here unlocks a feature, removes a limit or changes the app in any way. The store build lists four Play subscription tiers alongside the links below; they are donations too, and they unlock nothing either.

The in-app support sheet offers three of these — GitHub Sponsors, Patreon and PayPal — in both the foss and store builds. Ko-fi and Buy Me a Coffee are web-only on purpose: a page can afford five near-identical rows, and a bottom sheet the user opened to do one thing cannot.

Forks

Thor’s name and logo are trademarks; the code is free to fork, the identity is not. An unofficial build carrying Thor’s name could contain anything.