Run rooted Kotlin JVM code made super easy with coroutines and parcelize!
Check out demo at app to see just how easy it is.
Also check out more complicated demos:
- PoGo+LE
- VPN Hotspot (how this library started)
Use it now!
be.mygod.librootkotlinx:librootkotlinx:2.0.0+
(see Releases page for latest version)
- 100% Kotlin public API with coroutines and
Parcelize! Easy to use and virtually no boilerplate code/aidl - 100% event driven via coroutines, no blocking calls
- Persistent root session that closes itself on inactive (optional and configurable)
- Supports
IBinderandParcelFileDescriptorpassing via a Binder IPC backend
Comparison with libsu
librootkotlinx is inspired by and heavily borrows libsu's RootService backend design.
- librootkotlinx supports only API 23+ for nonblocking IO instead of 19+ for libsu.
- librootkotlinx exposes suspend functions and Kotlin Flow instead of requiring consumers to write AIDL.
- librootkotlinx uses content provider for Binder handoff, which is more robust and less prone to system broadcast pressure than libsu's broadcast path, and more lightweight and more secure compared to libsu's daemon service path.
- librootkotlinx supports more robust error surfacing, handling and recovery. In contrast, libsu quietly swallows Exceptions/failures, does not support app-provided logger, and may block retry until the entire process is restarted.
- librootkotlinx is cancellation aware whereas libsu provides no such path and has a fixed non-negotiable 10-second timeout as a workaround.
- librootkotlinx does not provide a root shell API and thus does not need to keep an unused root shell process hanging around.
- librootkotlinx is coroutine/Ktor-first and uses no blocking I/O.
- librootkotlinx uses Linux local socket to guarantee server death once the client process is gone, which is more reliable than Android APIs used by libsu.
- librootkotlinx is strict one client to one server. Multiple client processes/users are unsupported.
- libsu has additional APIs such as shell helpers and remote file system support.
a.k.a. things that can go wrong if root startup doesn't work.
This is a list of stuff that might impact this library's functionality if unavailable.
This is only meant to be an index.
You can read more in the source code.
API restrictions are updated up to SHA-256 checksum 9102af02fe6ab68b92464bdff5e5b09f3bd62c65d1130aaf85d3296f17d38074.
Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded or implicitly used)
- (API 26+)
Landroid/app/ActivityManager;->getService()Landroid/app/IActivityManager;,unsupported - (API 23-25)
Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;,unsupported Landroid/app/ActivityThread;->getSystemContext()Landroid/app/ContextImpl;,unsupportedLandroid/app/ActivityThread;->systemMain()Landroid/app/ActivityThread;,unsupported- (API 26+)
Landroid/app/ContentProviderHolder;->provider:Landroid/content/IContentProvider;,unsupported - (API 23-25)
Landroid/app/IActivityManager$ContentProviderHolder;->provider:Landroid/content/IContentProvider; - (API 29+)
Landroid/app/IActivityManager;->getContentProviderExternal(Ljava/lang/String;ILandroid/os/IBinder;Ljava/lang/String;)Landroid/app/ContentProviderHolder;,blocked - (API 23-28)
Landroid/app/IActivityManager;->removeContentProviderExternal(Ljava/lang/String;Landroid/os/IBinder;)V,max-target-r - (API 29+)
Landroid/app/IActivityManager;->removeContentProviderExternalAsUser(Ljava/lang/String;Landroid/os/IBinder;I)V,blocked - (API 31+)
Landroid/content/IContentProvider;->call(Landroid/content/AttributionSource;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;,blocked - (API 23-28)
Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;,max-target-q - (API 29)
Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle; - (API 30)
Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle; - (API 24+)
Landroid/content/res/Resources;->getImpl()Landroid/content/res/ResourcesImpl;,unsupported Landroid/content/res/Resources;->mSystem:Landroid/content/res/Resources;,unsupported- (API 24+)
Landroid/content/res/Resources;->setImpl(Landroid/content/res/ResourcesImpl;)V,unsupported - (API 23)
Ljava/lang/ProcessManager$ProcessInputStream;->fd:Ljava/io/FileDescriptor; - (API 23)
Ljava/lang/ProcessManager$ProcessOutputStream;->fd:Ljava/io/FileDescriptor; - (API 23)
Landroid/os/UserHandle;-><init>(I)V,unsupported Llibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V,core-platform-api,unsupported
Hidden whitelisted APIs: (same catch as above, however, things in this list are less likely to be broken)
Landroid/app/ContextImpl;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context;,sdk,system-api,test-apiLandroid/content/Context;->createPackageContextAsUser(Ljava/lang/String;ILandroid/os/UserHandle;)Landroid/content/Context;,sdk,system-api,test-api- (API 24+)
Landroid/os/UserHandle;->of(I)Landroid/os/UserHandle;,sdk,system-api,test-api
Optional hidden APIs used only for nonblocking optimization/optional helper methods:
- (API 31+)
Landroid/os/Process;->openPidFd(II)Ljava/io/FileDescriptor;,blocked - (API 24+)
Ljava/lang/UNIXProcess;->pid:I,unsupported - (API 23)
Ljava/lang/ProcessManager$ProcessImpl;->pid:I
Other:
- The root process calls the app-owned handoff provider through
ActivityManager.getService(),IActivityManager.getContentProviderExternal(...),IActivityManager.removeContentProviderExternalAsUser(...), andContentProviderHolder.provider, which isIActivityManager.ContentProviderHolder.provideron API 23-25 andContentProviderHolder.provideron API 26+. The API 23-28 external-provider acquisition/release signatures aregetContentProviderExternal(..., token)andremoveContentProviderExternal(...). On API 23-28, the release path usesUserHandle.getCallingUserId(), so secondary-user handoff is refused before external-provider acquisition. - Provider handoff uses
IContentProvider.call(AttributionSource, ...)withAttributionSource.myAttributionSource(), API 30IContentProvider.call(callingPkg, attributionTag, authority, ...), API 29IContentProvider.call(callingPkg, authority, ...), and the API 23-28IContentProvider.call(callingPkg, method, ...). API 29+ must pass authority becauseContentProvider.Transport.call(...)validates it before dispatch. - Root package context creation assumes
ActivityThread.systemMain(),ActivityThread.getSystemContext(),ContextImpl.createPackageContextAsUser(...), andContext.createPackageContextAsUser(...). - The LG
IntegrityManagerworkaround replacesResources.mSystemand preserves the originalResourcesImplthroughResources.getImpl()andResources.setImpl(...), matching libsu's root-service bootstrap. - Shell command construction keeps
libsu
RootServiceManager's app_process command contract, while replacing libsu's root-main jar,RootServerMain, and broadcast handoff with a base-APK bootstrap classpath shape derived from librootkotlinx v1AppProcess.launchString. ProcessPipes.startPipesusesProcessBuilder.redirectInput(File),redirectOutput(File), andredirectError(File)on API 24+, even though Android SDK metadata marks these APIs as 26+. The API 23 fallback duplicates descriptors from process streams. AOSP's API 23 implementation exposesProcessInputStream.fdandProcessOutputStream.fd; this library first uses the publicFileInputStream/FileOutputStreamdescriptor access when possible and keeps named-field reflection as the fallback for those API 23 stream classes.RootProcessBootstrapstarts from the base APK classpath, then asks the framework-created package context for the app class loader. That lets Android assemble base app code and native library paths through the normal package-loading path instead of duplicatingLoadedApk.makePaths(...). The root side does not support code or Parcelables packaged in split APKs or dynamic feature modules. Consumers must packagelibrootkotlinxand everyRootCommand,RootFlow,Parcelable, exception class, and dependency that may be loaded or unparceled in the root process in the base APK. This includes both ordinary and isolated feature splits.
System/root command assumptions:
The following Android system binaries or shell commands are assumed to be bundled and executable:
/system/bin/su,/system/xbin/su,/sbin/su,/debug_ramdisk/su,/data/adb/ksu/bin/su,/data/adb/ap/bin/su, orsu;/system/bin/app_processas the fallback rootapp_processexecutable in case discovery fails;mkdir,cp,chmod,printf, and shellexec.