Thor is a modern, lightweight, and privacy-focused Android App Manager. It is free and open-source (FOSS), with no ads, trackers, or telemetry, providing advanced app management capabilities through Shizuku, Dhizuku, and Root access.
The project follows Clean Architecture principles combined with MVVM (Model-View-ViewModel) for the presentation layer.
app/: The core application module.- Presentation: Built with Jetpack Compose. ViewModels manage state using
StateFlowand Koin for dependency injection. - Domain: Pure Kotlin layer containing business logic, Use Cases, and repository interfaces. Platform-agnostic where possible.
- Data: Implementation of repositories, interacting with Android's
PackageManager,Shizuku/DhizukuAPIs,DataStorefor preferences, and Room (thor_database) for the app metadata cache, the freezer watchlist and extension data. - DI: Koin Annotations, generated by the Koin compiler plugin
(
io.insert-koin.compiler.plugin) — a Kotlin compiler plugin, not KSP.di/Modules.ktdeclares a single@Module @ComponentScan("com.valhalla.thor")root; classes opt in with@Single/@Factory/@KoinViewModelrather than being listed in a module. The root supplies only what scanning cannot infer — three@Nameddispatchers ("io"/"default"/"main"),PackageManager, the database and its DAOs, and Odin'sShellRepository.compileSafety,strictSafetyandunsafeDslChecksare all on, so a missing or ambiguous binding is a compile error, not a runtime crash.
- Presentation: Built with Jetpack Compose. ViewModels manage state using
- Odin (
com.trinadhthatakula:odin): Root shell management, consumed from Maven Central rather than built in-tree. A Kotlin-refactored version of thelibsucore module bytopjohnwu, optimized for modern Kotlin idioms and memory safety, now maintained as a standalone library. It replaced the formersuCore/module;settings.gradle.ktscan substitute a local checkout via-PodinDirfor cross-repo work. bypass/: A core utility module for bypassing Android's hidden API restrictions usingVMRuntimeexemptions and enhanced reflection.vm-runtime/: Compile-only Java stubs required for thebypassmodule to interface with internal Android classes likeVMRuntime. Intentionally a pure Java library (not Kotlin) to ensure correct class shadowing behaviour at compile time.
- Language: Kotlin (all modules except
vm-runtime, which is pure Java for stub compatibility) - UI Framework: Jetpack Compose with
MaterialExpressiveTheme+MotionScheme.expressive(). Static "Asgardian" color scheme by default; optional Material You dynamic color on Android 12+. Navigation uses a customThorNavigationBarwith spring animations +HorizontalPagerfor swipe-between-screens. - Dependency Injection: Koin Annotations via the Koin compiler plugin
- Asynchronous Programming: Kotlin Coroutines & Flow
- Image Loading: Coil 3
- Animation: Lottie + Compose
AnimatedVisibility/AnimatedContent - Persistence:
- Jetpack Room: High-performance caching of
AppInfometadata, invalidated vialastUpdateTime. - Jetpack DataStore: User preferences including theme, AMOLED mode, biometric lock, and preferred privilege mode.
- Jetpack Room: High-performance caching of
- Security: Android Biometrics via
BiometricPromptAPI directly (noandroidx.biometricdependency).HomeActivityextendsComponentActivity. - Elevated Privileges:
- Root (su): Via the Odin library (Kotlin-refactored fork of
libsu). - Shizuku: Shell-command-first (
am,pm,appops) with reflection fallback via:bypass. - Dhizuku: Device Owner API with reflection fallback via
:bypass. - Work Mode (
PrivilegeMode): User-selectable privilege engine (ROOT / SHIZUKU / DHIZUKU) with automatic fallback strategy (Root → Shizuku → Dhizuku). - Internal Bypass (
:bypass): Custom Kotlin implementation usingVMRuntimeexemptions and reflection, backed by Java stubs in:vm-runtime.
- Root (su): Via the Odin library (Kotlin-refactored fork of
- Build System: Gradle Kotlin DSL with Version Catalog (
libs.versions.toml). Exact tool and library versions defined inlibs.versions.toml; do not hardcode them in docs. - Distribution: Two product flavors:
store(Play Store compliant) andfoss(fully libre/open).
- App Management: Install, uninstall, freeze (disable/enable), suspend/unsuspend, and
background-restrict apps. Tracks
isSuspendedandisDebuggableflags directly onAppInfo. - Work Mode: User-selectable privilege engine (
PrivilegeMode: ROOT, SHIZUKU, DHIZUKU) stored inUserPreferences. Falls back automatically if the preferred mode is unavailable. - Batch Operations: Batch freeze/unfreeze, reinstall, uninstall, kill, suspend/unsuspend, and clear data — all logged in real time through the terminal logger dialog.
- App Suspension: Uses
IPackageManagerreflection to suspend apps, showing a custom "Thor" -branded system dialog. Supports Android 10 through 13+ with version-specific fallbacks. - Background Restriction: Restricts an app's background activity via
setAppRestricted. - Fix Store (Reinstall with Google): Reassigns installer to Play Store. Available in all privilege modes (Root, Shizuku, Dhizuku).
- Clear Data / Clear Cache: Available in all privilege modes;
clearAppDatausespm clearwith multi-user support. - Advanced Insights: Installer source (resolved from package labels, not hardcoded), split APK
indicators, version codes, SDK targets,
isSuspended,isDebuggable. - System App Support: Uninstall or freeze system apps (requires any privilege mode). A freeze
disables the package and keeps its data. Only where the platform actually refused the disable
does it fall back to
pm uninstall -k --user N— a per-user removal, not a real uninstall: the APK stays on the read-only partition, the package record survives, and-kkeeps both the data directories and the runtime permission grants, sopm install-existing --user Nrestores the app intact. That refusal is an OEM restriction, not an Android version. Dhizuku is the one exception still on the old path: its gateway is not yet converted, so it removes for the current user unconditionally and without-k. Note the fallback is unavailable to Shizuku at shell uid on API 37, which answers it withonly root can delete system app for a particular user.domain/model/FreezePolicy.ktowns the rule; every reader of freeze state must handle both mechanics, since devices carry system apps frozen the old way, when the removal ran first, unconditionally, and without-k. - Security: Biometric/device-credential lock for app access. Per-session authentication state.
- App Metadata Caching: Room DB cache for
AppInfo, invalidated vialastUpdateTime. - Preferences (
UserPreferences): theme, AMOLED, dynamic color, biometric lock, sort/filter state, privilege mode, and language — all persisted via DataStore. - Customization: Dark/Light/System + AMOLED themes. "Asgardian" static color scheme is the default; Material You dynamic color opt-in. Preferred privilege mode persisted across sessions.
- Search: Live search by app name or package name in App List and Freezer screens.
- Multi-language: Supports English, Spanish, French, Arabic, and Chinese. Runtime locale
switching via
LocaleManager(util/LocaleManager.kt); language preference stored inUserPreferences.language(null = system default). - Privacy: No ads, no trackers, no analytics, FOSS (GPL-3.0). The app declares
android.permission.INTERNET; the only network access is the optional Extensions store, which fetches its catalog and verified extension APKs over HTTPS. Every other feature works offline.
- Privilege Dependency: Advanced features (freeze, suspend, system app removal) require at least one of Root, Shizuku, or Dhizuku. Work Mode selection with automatic fallback mitigates partial availability.
- Suspension Compatibility:
setAppSuspendeduses reflection against internal APIs; behaviour may vary across Android 10–14+ due to API signature changes. - No Cloud Sync: No cloud backup or remote synchronization (by design, for privacy).
- Android Constraints: Subject to evolving Android security restrictions (hidden API policy, target SDK requirements).
- Feature Gap: App data backup is not yet implemented.
- Data Backup: Implementing local app data backup and restoration.
- Package Editing: Direct editing of
packages.xmlfor advanced users. - Batch Install: Installing multiple APKs in one operation.
- Automation: Scheduled freezing/unfreezing or automated cleanup tasks.
- Installer Integration: Expanding support for third-party installers (e.g., F-Droid, Aurora Store).
- Play Store Policies: As an "App Manager" with elevated privileges, it faces strict scrutiny from Google Play.
- Android OS Changes: Future Android updates might further restrict Shizuku or root-level access methods.
- Competition: Several established open-source app managers exist; maintaining a niche in " lightweight & privacy-first" is key.