Skip to content

feat: Magisk module install - #127

Closed
secp192k1 wants to merge 54 commits into
ReVanced:devfrom
secp192k1:feat/magisk-module
Closed

feat: Magisk module install#127
secp192k1 wants to merge 54 commits into
ReVanced:devfrom
secp192k1:feat/magisk-module

Conversation

@secp192k1

@secp192k1 secp192k1 commented Apr 7, 2026

Copy link
Copy Markdown

Closes #127

Note: I had to rollback the AGP version during local development and testing to 8.13.2 since there is a version mismatch. But this shouldn't be an issue once they match

Introduce Magisk-based installation support: add an abstract MagiskInstaller implementing install/uninstall/getInstallation logic for deploying patched APKs as Magisk modules (writes module.prop, copies patched APK to module, restarts/kills apps). Add platform-specific installers: AdbMagiskInstaller (ADB root) and LocalMagiskInstaller (local root via LocalShellCommandRunner, Closeable). Add Magisk-related constants (module paths, COPY_APK_TO_MODULE command, MAGISK_MODULE_PROP template) used by the installer.
@secp192k1
secp192k1 marked this pull request as ready for review April 7, 2026 15:28
@secp192k1
secp192k1 marked this pull request as draft April 7, 2026 16:13
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/module.prop Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
rm -f "$DIR/log"

{
echo "Induction check for $package_name"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does induction check mean

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically making sure that the system is ready for the app to be injected/introduced into the system by overlaying on top of the original app

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why "induction"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a mix of both, right now that whole name has been replaced by the watchdog and STAGE_APK variables

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
Comment thread library/src/androidMain/assets/root/service.sh Outdated
override suspend fun uninstall(packageName: String): RootInstallerResult {
logger.info("Uninstalling $packageName Magisk module")

val formattedPackageName = packageName.replace('.', '_')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case would . be unsafe to use here? Isnt

/my.pkg.name/ a valid folder name

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case would . be unsafe to use here? Isnt

/my.pkg.name/ a valid folder name

Yes its a valid folder name, but because formattedPackageName doubles as the Magisk module id in module.prop (id=revanced___FORMATTED_PKG__), which by convention should only contain alphanumeric characters and underscores
Since the module id must match the directory name under the modules dir (/data/adb/modules/), both are kept consistent and dot-free

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so magisk says alphanumeric -> therefore folder has to as well. Hm, is this convention something magisk mentioned anywhere? Whats the reason for this convention? Its an internal name, users dont see it. I would prefer us to break this convention on the magisk side if it doesnt cause any issues there, for the sake of not having to do this quirky operation here

@secp192k1 secp192k1 Apr 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this convention something magisk mentioned anywhere? Whats the reason for this convention?

Docs are located here, Magisk/docs/guides.md

id has to match this regular expression: ^[a-zA-Z][a-zA-Z0-9._-]+$
ex: ✓ a_module, ✓ a.module, ✓ module-101, ✗ a module, ✗ 1_module, ✗ -a-module
This is the unique identifier of your module. You should not change it once published.

So yeah dots are allowed... Missed it completely, since they're allowed anyways, I just removed the entire formatter logic (remove dots to underscore logic)
https://github.com/secp192k1/revanced-library/commit/d33b54c76e90f85f9b666fb0f59b7ed778c3f3b1

return RootInstallation(
INSTALLED_APK_PATH(packageName)().output.ifEmpty { null },
patchedApkPath,
MOUNT_GREP(patchedApkPath)().exitCode == 0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we still have the mounted boolean https://github.com/ReVanced/revanced-library/pull/127/changes#r3061197338

Lmao... 2d19f45
Also the val above as useless so I moved it inside the root installation call

#!/system/bin/sh
pm uninstall "__PATCHED_PKG__"
rm -f "/data/adb/revanced/__PKG_NAME__.apk"
rm -f "/data/adb/service.d/revanced_handle_disabled___FORMATTED_PKG__.sh"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt the module uninstall script delete itself too?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt the module uninstall script delete itself too?

Nope. Magisk runs the uninstall script and then removes the entire module directory itself, so the script is cleaned up automatically. The explicit rm -f for the handle-disabled script is necessary precisely because that file lives outside the module directory at /data/adb/service.d/ : Magisk will never touch it

cp /proc/sys/kernel/random/boot_id "${DIR}/.boot_token"

LOG="${DIR}/log"
MAX_LOG_LINES=200

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need logging here? Is it to display stuff in magisk manager?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its fine to not have any logging code for the module script, like logging to magisk manager is fine, but no dump to a log file

@secp192k1 secp192k1 Apr 18, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need logging here? Is it to display stuff in magisk manager?

No, this logging is strictly for the magisk module, since manager wouldn't be able to access the logs and to keep it organized by category (manager logs vs module logs) its also keeps the logs separated between multiple modules

I think its fine to not have any logging code for the module script, like logging to magisk manager is fine, but no dump to a log file

Any other alternative that comes to mind?
Also keep in mind, along side with my reply above, each log file has a MAX_LOG_LINES=200

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I would simply remove the log entirely, I understand its a nice to have for debugging purposes, but debugging code doesnt belong in production as a general rule of thumb principle. Debugging needs to be solved elsewise

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# (install-create/write/commit) and is less prone to early-boot binder failures.
# NOTE: On Xiaomi devices (MIUI/HyperOS), pm install may still fail due to
# package verification restrictions. Manual install via ReVanced Manager
# may be required in that case.

@oSumAtrIX oSumAtrIX Apr 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insane lol, how do we handle that in manager tbh or like how tf do you prompt the user to install the apk on Xiamoi programatically, ideally library can handle Xiomi installation business logic by itself

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside lol, how do we handle that in manager tbh or like how tf do you prompt the user to install the apk on Xiaomi programatically, ideally library can handle Xiomi installation business logic by itself

How basically everyone else solves this issue, by the phone props, for example:

[ro.fota.oem]: [Xiaomi]
[ro.product.bootimage.manufacturer]: [Xiaomi]
[ro.product.manufacturer]: [Xiaomi]
[ro.product.odm.manufacturer]: [Xiaomi]
[ro.product.product.brand]: [Xiaomi]
[ro.product.product.manufacturer]: [Xiaomi]
[ro.product.system.brand]: [Xiaomi]
[ro.product.system.manufacturer]: [Xiaomi]
[ro.product.system_ext.brand]: [Xiaomi]
[ro.product.system_ext.manufacturer]: [Xiaomi]
[ro.product.vendor.manufacturer]: [Xiaomi]
[ro.product.vendor_dlkm.manufacturer]: [Xiaomi]

Note: Remember that these are keys from my device with the value specifically being Xiaomi, some keys like ...vendor_dlkm... might not exist on other Xiaomi devices

Also this will almost always be a hassle to completely fix since there isnt a good and reliable way to tell MIUI and HyperOS apart (without a lot of checks)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could for example join all props and do a "contains Xiaomi" check.To be honest im not really fond of us handling xiaomi bugs in revanced, or even considering them here, its more of something xiaomi would have to solve on their side

*
* 3. Some potential issue is that writing to [system app's path]/lib would fail on read-only
* system partition (/system/app, /product/app, etc)
* Right now it's assuming it can write to it - Wrong!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cant we just mount to that directory instead of writing?

@secp192k1 secp192k1 Apr 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cant we just mount to that directory instead of writing?

https://github.com/secp192k1/revanced-library/commit/99afcc7ef549af95757f0a7089d39fada08db0c8
Like this?

@oSumAtrIX
oSumAtrIX self-requested a review May 21, 2026 22:47
@secp192k1 secp192k1 closed this by deleting the head repository Jul 19, 2026
@oSumAtrIX

Copy link
Copy Markdown
Member

Moved to #147

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.

4 participants