Compare commits

...
Author SHA1 Message Date
i-am-very-smart e78500e44e tools/helper.py: run() only detects error if return code is non-zero 2026-01-11 17:23:54 +11:00
ayasa520 d5289cfd89 Update libhoudini (#256)
* Update download link for Houdini version 13
2026-01-05 09:56:03 +01:00
NullBite ddaa6b190f Add Nix flake and improve derivation
This adds a Nix flake to the repo as well as updates the derivation so
that it includes `lzip` as a dependency
2025-11-17 10:08:53 +01:00
Gerry Bagaskoro Putro 15020ec20a fix(nodataperm): prevent crash when uninstalling on Android 13 2025-11-11 19:37:38 +01:00
Alessandro Astone fcb15624db Fix A13 widevine
Closes: https://github.com/casualsnek/waydroid_script/issues/236
2025-08-31 22:56:59 +02:00
Alessandro Astone db43c7c9cf main: Default to A13
Following Waydroid which now defaults to A13
2025-08-18 12:41:31 +02:00
Mio 3e344b360f fix https://github.com/casualsnek/waydroid_script/issues/229 2025-07-13 09:11:10 +02:00
金雄镕 5527d390eb Reorder ro.product.cpu.abilist to prioritize 64-bit ABIs 2025-07-11 19:43:32 +02:00
MasterKia 6f44d95070 Fix microg installation guide
The previous command returns an error ("ModuleNotFoundError: No module named 'InquirerPy'") even after installing the InquirerPy module using pip.
2025-07-04 10:43:21 +02:00
Alessandro Astone 32d21c8074 Change ndk_translation for A13 2025-05-30 18:36:04 +02:00
Alessandro Astone eb337a1351 Change houdini for A13
Even though this is extracted from an Android 14 image, it works better
including on AMD CPUs

Closes: #224
2025-05-21 21:40:38 +02:00
Alessandro Astone 48186df8af A13 ndk_translation 2025-05-20 00:02:29 +02:00
Alessandro Astone c14650010e A13 houdini 2025-05-20 00:02:29 +02:00
Casu Al Snek 1a2d3ad643 Merge pull request #143 from mistrmochov/patch-2
Update to Magisk Delta 26.3
2024-01-20 19:29:28 +05:45
mistrmochov 7cccf2b56d Maintainer of Magisk Delta, just deleted the repo for older Magisk Delta, so I put it on my repo 2024-01-10 19:16:24 +01:00
mistrmochov d31988a829 Update to Magisk Delta 26.3
Your script works fine with last Magisk Delta (before Kitsune Mask update).

Also with modified setup for bootanim
2024-01-09 16:44:57 +01:00
Casu Al Snek b12c06568c Merge pull request #132 from mkg20001/nix
Add nixos derivation
2024-01-09 09:12:53 +05:45
Casu Al Snek e0de64c047 Merge pull request #133 from mkg20001/fdroidpriv
Add fdroidpriv for installing f-droid privleged extension
2024-01-09 09:12:10 +05:45
Casu Al Snek bc3efd48c2 Merge pull request #131 from linyinfeng/fix-houdini
Fix binfmt_misc mounting for libhoudini
2024-01-09 09:11:33 +05:45
Casu Al Snek cd6239737a Downgrade magisk to Magisk_Delta_25210_canary_fdac22ba 2024-01-09 09:09:14 +05:45
Casu Al Snek 97293f3cc1 Merge pull request #140 from s1204IT/main
Update MindTheGapps package
2024-01-03 18:24:03 +05:45
Syuugo 76caf7e1d7 Fix filename 2023-12-22 12:49:35 +09:00
Syuugo 3527282950 Redirect user 2023-12-22 08:39:07 +09:00
Syuugo d2502086ed Update MTG package 2023-12-22 08:37:26 +09:00
Maciej Krüger c5110830f7 Add fdroidpriv for installing f-droid privleged extension 2023-11-20 03:35:08 +01:00
Maciej Krüger d81b72fed7 Add nixos derivation 2023-11-20 03:34:03 +01:00
Lin Yinfeng bd8d53906a Fix binfmt_misc mounting for libhoudini 2023-10-23 20:17:25 +08:00
Casu Al Snek acbb764ac5 Merge pull request #94 from mak448a/patch-1
Various grammar fixes
2023-09-26 19:06:34 +05:45
Casu Al Snek 45602d27c8 Merge pull request #122 from claui/mitm
Install self-signed CA cert into trust store
2023-09-25 19:47:04 +05:45
mak448a 6706f4b9d7 Merge branch 'main' into patch-1 2023-09-24 20:50:18 -05:00
Claudia b1c88db1ce Feature: install self-signed cacert to trust store
For analysis and reverse engineering, it can be helpful to insert a
custom CA certificate into Waydroid’s system-wide trust store.
Users used to be able to do that via Android’s settings but not anymore.

The `install mitm` command accepts a path to a file that contains a
– typically self-signed – CA certificate in PEM format.
It then renames [1] and copies the file into the overlay file system,
placing it into Waydroid’s trust store.

As a usage example, the following command lines enable your host to use
mitmproxy [2] to act as a proxy and to intercept [3] HTTP(S) connections
that come from the Waydroid container:

```sh
$ timeout --preserve-status 2 mitmdump -n                           # creates a CA cert in ~/.mitmproxy
$ sudo venv/bin/python3 main.py install mitm --ca-cert ~/.mitmproxy/mitmproxy-ca-cert.pem
INFO: Creating directory: /system/etc/security/cacerts
INFO: Copying /home/yourname/.mitmproxy/mitmproxy-ca-cert.pem to system trust store
INFO: Target file: /system/etc/security/cacerts/6320a7db.0
INFO: mitm installation finished
$ sudo waydroid shell -- ls -l /system/etc/security/cacerts         # double-check that it worked
[…]
-rw-r--r-- 1 root root 1191 2024-01-01 00:00 6320a7db.0
[…]
$ adb shell settings put global http_proxy ${YOUR_IP_HERE?}:3128    # tell Waydroid to use the proxy
                                                                    #     for all connections
$ mitmproxy -p 3128                                                 # start proxy and display a TUI
                                                                    #     with HTTP(S) connections
                                                                    #     coming from Waydroid
```

[1]: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/#2-rename-certificate

[2]: https://mitmproxy.org/

[3]: https://docs.mitmproxy.org/stable/mitmproxytutorial-interceptrequests/
2023-09-23 18:34:14 +02:00
Casu Al Snek 688c84fd58 Merge pull request #124 from Benjamin-Loison/main
Add `bash` syntax highlighting to `README.md`
2023-09-23 20:54:44 +05:45
Benjamin Loison 367697d59e Add bash syntax highlighting to README.md 2023-09-17 02:26:48 +02:00
Casu Al Snek 77e222fb16 Merge pull request #118 from ayasa520/main
Fix some issues that prevented scripts from working properly
2023-08-25 14:47:59 +05:45
Rikka 821c7c0bc2 Update prompt 2023-08-24 23:33:10 +08:00
Rikka 854b4b0a6c Use venv to avoid breaking Python installation or OS 2023-08-24 23:33:04 +08:00
Rikka 6d5af57ebc fix: Fix simlink path issue
https://github.com/casualsnek/waydroid_script/issues/101
Relative path fails when using symlink. Replace it with absolute path.
2023-08-24 23:22:20 +08:00
Rikka a80ff8e855 update hidestatusbar link 2023-08-24 23:22:16 +08:00
Rikka 3e51f7f56e update smartdock link 2023-08-24 23:22:05 +08:00
Rikka e1ee7f0b0c Fix capitalization of MicroG and update nodataperm 2023-08-24 23:21:53 +08:00
ayasa520 337d066eeb fix(microg): typos 2023-08-24 23:17:14 +08:00
Casu Al Snek 4db9bb3cba Merge pull request #110 from axolotlek/main
fix cli commands mistakes in readme
2023-08-19 00:13:01 +05:45
Casu Al Snek 489159c5f9 Merge pull request #111 from SUFandom/patch-1
[URGENT] Update nodataperm.py by changing MD5SUM hash to updated state
2023-07-25 23:48:31 +05:45
SUFandom 9c2d8fcd83 [URGENT] Update nodataperm.py
Change the MD5Sum Because trying it spams error because its invalid

Suggestion: Just add the main.zip to the Releases tag and let The script grab the 'stable' version there an just change it alongside with the python script library for update to not add issues
2023-07-25 20:09:05 +08:00
axolotlek 098036cca9 fixed mistakes in readme 2023-07-25 14:46:43 +03:00
axolotlek 212135d3c8 fixed mistakes in readme 2023-07-25 13:59:51 +03:00
mak448a 7b5c7f64c0 Update README.md 2023-06-15 13:53:47 -05:00
mak448a b80dcf171f Update README.md 2023-06-15 13:38:56 -05:00
Casu Al Snek 59547e7743 Merge pull request #70 from ayasa520/main
Uninstall function, microG installation and some hacks
2023-05-28 12:39:02 +05:45
ayasa520 ddcc581a9c Update README.md 2023-05-27 17:43:07 +08:00
Rikka 6db853e8d1 Update README.md 2023-05-27 17:35:47 +08:00
Rikka cb206cc8c0 libndk: fix libndk parameter 2023-05-27 16:55:31 +08:00
Rikka 910291ceb9 libndk: match the correct version of libndk 2023-05-27 16:55:31 +08:00
Alessandro Astone 2e693d03db Switch to a good verison of libndk_translation
The previous version targeted Android 12 if 64 bit, so native arm64 apks
are very likely to not work. Switch to a version targeting Android 11.
2023-05-27 16:55:31 +08:00
Rikka 4777296b34 smartdock: download from fdroid 2023-05-27 16:55:31 +08:00
Rikka cb9d2b4726 update: README.md 2023-05-27 16:55:30 +08:00
Rikka 6c6e651d79 rename _resetprop to resetprop 2023-05-27 16:55:30 +08:00
Rikka 4fce5db93e add x86 and arm resetprop 2023-05-27 16:55:30 +08:00
Rikka 0ab4b1c0f7 fix: ndk translation prop 2023-05-27 16:55:30 +08:00
Rikka ab334ebfc3 Remove unused imports 2023-05-27 16:55:30 +08:00
Rikka 4070ab8eb9 fix(SmartDock): update md5 2023-05-27 16:55:30 +08:00
Rikka 86aabfb2e2 refactor: set permission 2023-05-27 16:55:29 +08:00
Rikka 7fcfe62e66 Fix typing errors 2023-05-27 16:55:29 +08:00
Rikka 3900328b83 Add interactive command line interface 2023-05-27 16:55:29 +08:00
Rikka 48ea54fc3e refactor 2023-05-27 16:55:29 +08:00
Rikka 6922bdba0d microg: use MinMicroG 2023-05-27 16:55:29 +08:00
ayasa520 00714a5c0e Update README.md 2023-05-27 16:55:28 +08:00
Rikka ee8b9ef213 resetprop: Avoid conflict with magisk 2023-05-27 16:55:28 +08:00
Rikka c48b1df5cd support a13 image 2023-05-27 16:55:28 +08:00
Rikka 0b2afba187 change rc permission to 644 2023-05-27 16:55:28 +08:00
Rikka 43d8cfb18d prop: use waydroid upgrade -o to regenerate base prop 2023-05-27 16:55:28 +08:00
Rikka e305dd1dc4 Write prop to /var/lib/waydroid/waydroid.cfg 2023-05-27 16:55:28 +08:00
Rikka 556f277fec fix broken ndk link 2023-05-27 16:55:27 +08:00
ayasa520 7c31b838f6 Update requirements.txt 2023-05-27 16:55:27 +08:00
Rikka 8c66e7cf34 Update README 2023-05-27 16:55:27 +08:00
Rikka 5f6fc21c38 Use configparser to read waydroid config 2023-05-27 16:55:27 +08:00
Rikka d72bf018d1 Execute commands on waydroid shell with pipes 2023-05-27 16:55:27 +08:00
Rikka 0feb86ceef Fix incorrect keyword arguments 2023-05-27 16:55:27 +08:00
Rikka 553f48fa27 arm widevine
arm widevine
2023-05-27 16:55:26 +08:00
Rikka 53a4bad536 Add: hide status bar 2023-05-27 16:55:26 +08:00
Rikka ca932b90e1 fix: get google certified
https://github.com/waydroid/waydroid/commit/c49dfd272d994b1cdaa14107fee66be84b80c06b
2023-05-27 16:55:26 +08:00
Rikka 0d7681bccb add uninstall function 2023-05-27 16:55:24 +08:00
Rikka 4d15b6153c Fix resize error log 2023-05-27 16:53:16 +08:00
Rikka 9d9f504625 fix closing tag 2023-05-27 16:52:56 +08:00
Rikka 0bc2cedc2d add microG 2023-05-27 16:52:55 +08:00
Rikka d205812acb Remove magisk files in upperdir when overlayfs is enabled 2023-05-27 16:52:55 +08:00
Rikka fa9e89e868 HACK: granting full permission for apps data 2023-05-27 16:52:55 +08:00
Rikka 72e34c4a38 update README.md 2023-05-27 16:52:53 +08:00
Rikka 92f7e98749 update opengapps 2023-05-27 16:52:28 +08:00
Rikka dbf630ba7e update smartdock 2023-05-27 16:52:26 +08:00
Rikka 59ad317684 install smart dock 2023-05-27 16:46:13 +08:00
Casu Al Snek 0abfc4ef4b Merge pull request #73 from JamiKettunen/optional-dbus
container: Make missing dbus module non-fatal
2023-05-13 21:25:07 +05:45
Casu Al Snek 4f6410c3bb Merge pull request #84 from tutacat/patch-5
Allow CLI help without root
2023-04-26 12:49:21 +05:45
Casu Al Snek a621645e07 Merge pull request #61 from cobalt2727/patch-1
fix Widevine typo
2023-04-26 12:48:32 +05:45
cobalt2727 545e733566 fix widevine typo 2023-04-25 21:16:59 -04:00
tutacat 771b8d7224 Allow CLI help without root
Move helper.check_root to after argparse runs, so it can display the help without needing root.
2023-04-24 23:13:41 +01:00
Casu Al Snek a701ca8027 Merge pull request #80 from ayasa520/prop
prop: run 'waydroid upgrade -o' to regenerate base prop
2023-04-12 11:05:31 +05:45
Rikka abdc3b015d prop: run 'waydroid upgrade -o' to regenerate base prop 2023-04-11 01:24:22 +08:00
Casu Al Snek d770a95995 Merge pull request #79 from ayasa520/prop
prop: write prop to /var/lib/waydroid/waydroid.cfg
2023-04-10 21:05:42 +05:45
Rikka 1caafe57e6 prop: write prop to /var/lib/waydroid/waydroid.cfg 2023-04-10 11:50:13 +08:00
Casu Al Snek 6c78b793c8 Merge pull request #75 from claui/ndk-use-github
ndk: use GitHub source instead of Dropbox
2023-03-20 09:08:13 +05:45
Claudia 6b4bc0da47 ndk: use GitHub source instead of Dropbox
Fixes #74.

Reported-by: mac1202
Suggested-by: ayasa520
2023-03-19 16:02:01 +01:00
Jami Kettunen afa0180032 container: Make missing dbus module non-fatal
This is required to properly support Waydroid tool versions <=1.3.4
(which NixOS for example still has), or 1.4.0+ configured with
USE_DBUS_ACTIVATION=0 (basically non-systemd distributions which can't
supervise the container properly when it's launched via D-Bus)
2023-03-13 13:04:26 +02:00
Casu Al Snek 2f4f056fb1 Merge pull request #64 from ayasa520/1.4
Use WayDroid 1.4 features like dbus and overlayfs
2023-01-23 21:15:34 +05:45
Casu Al Snek 97020f99c1 Merge branch 'main' into 1.4 2023-01-23 11:25:14 +05:45
Rikka 62749bbb8e Refuse to install arm translation on x86 2023-01-20 12:05:43 +08:00
Rikka 8f8691423b Fix restart bug 2023-01-20 10:50:17 +08:00
Rikka 90fff773b2 Use a correct way to read overlayfs config 2023-01-20 10:22:16 +08:00
Rikka 62a460b2c3 Fix missing 'True' 2023-01-20 10:04:47 +08:00
Rikka da15751629 Update: README.md 2023-01-19 13:19:06 +08:00
Rikka df46ba8fed Refactor: Split into multiple small scripts 2023-01-19 13:14:45 +08:00
Rikka 4681bb48fe Update README 2023-01-12 14:53:24 +08:00
Rikka 7a27b8c193 Fix CPU architecture detection for Magisk installation 2023-01-12 12:58:36 +08:00
Rikka 325dbb472a Update *run* method 2023-01-12 12:13:43 +08:00
Rikka 4b83449e3b Update Magisk bootanim.rc 2023-01-11 17:58:46 +08:00
Rikka 43311707a3 Replace os.system with subprocess.run 2023-01-09 00:54:13 +08:00
Rikka 37c278dc52 Remove unnecessary code 2023-01-08 21:05:12 +08:00
Rikka af29dd0ddf restart WayDroid container after installation 2023-01-08 20:46:06 +08:00
Rikka faa7550c6a Use a fixed commit 2023-01-08 19:31:25 +08:00
Rikka 9f4a1280ce dbus 2023-01-08 19:04:45 +08:00
Rikka d27de7d4b5 Fix CPU architecture detection for Magisk installation 2023-01-08 13:57:36 +08:00
Casu Al Snek 15b1ac62ff Merge pull request #60 from LegacyGamerHD/main
Merge with original
2023-01-04 13:55:49 +05:45
ayasa520 7b70434f50 Update bootanim.rc 2023-01-02 21:18:29 +08:00
ayasa520 c19183f544 Clear residual files 2023-01-02 21:17:11 +08:00
LegacyGamerHD e77cd523a0 add Widevine to the readme 2023-01-02 13:15:11 +01:00
LegacyGamerHD 5453fae828 Merge pull request #2 from ayasa520/fix-magisk-zygisk
Update Magisk
2023-01-02 11:51:06 +01:00
ayasa520 8f1b6a2712 Merge remote-tracking branch 'waydroid_script/OverlayFS' into OverlayFS2 2023-01-02 17:55:03 +08:00
LegacyGamerHD e765a0c880 Update waydroid_extras.py 2023-01-02 15:39:53 +08:00
Rikka 2ac0285722 Fix installation for 32bit magisk 2023-01-02 01:18:35 +08:00
Rikka cbcd5365c8 Fix bootanim.rc being incorrectly patched after updating magisk 2023-01-02 01:02:57 +08:00
LegacyGamerHD 9af33d60f4 Update waydroid_extras.py 2022-12-31 20:17:56 +01:00
LegacyGamerHD 5cd4f746d6 Merge pull request #1 from ayasa520/fix-magisk-zygisk
Fix magisk zygisk
2022-12-31 20:15:37 +01:00
ayasa520 6b4ab03ba3 Update waydroid_extras.py 2022-12-31 21:50:21 +08:00
ayasa520 3cb971a4ae Update waydroid_extras.py 2022-12-31 21:47:21 +08:00
LegacyGamerHD 2bd9ca5d5a re upload my work and the others 2022-12-31 12:25:59 +01:00
Quackdoc e69aadaa94 ndk overlay 2022-11-25 05:08:45 -05:00
Mitchel Stewart dce577b931 Merge branch 'LegacyGamerHD:patch-1' into OverlayFS 2022-11-25 04:45:54 -05:00
LegacyGamerHD 472de72e50 Update waydroid_extras.py 2022-11-25 09:03:58 +01:00
LegacyGamerHD b90c148229 update libndk for amd 2022-11-25 09:01:35 +01:00
Quackdoc 1995d57e21 Houdini, doesn't work in the first place? 2022-11-14 21:54:50 -05:00
Quackdoc 45d5dbd12d update gaaps 2022-11-14 21:08:22 -05:00
Quackdoc a6dda23325 update houdini for overlayFS 2022-11-14 16:08:54 -05:00
Casu Al Snek 98f957626b Merge pull request #56 from tkkcc/main
Fix download_loc if XDG_CACHE_HOME is set
2022-11-12 22:08:58 +05:45
bilabila 4736a61136 Fix download_loc if XDG_CACHE_HOME is set 2022-11-11 16:03:02 +08:00
LegacyGamerHD 2ffd72c7d3 Update waydroid_extras.py 2022-11-09 21:01:22 +01:00
LegacyGamerHD 4849abf9cc fix my mestake 2022-11-08 17:01:22 +01:00
LegacyGamerHD c207028677 Update README.md 2022-11-06 18:19:10 +01:00
LegacyGamerHD fd732b5b03 lower the magisk version and some other tweaks 2022-11-06 18:15:26 +01:00
LegacyGamerHD be97f33bcd Test 2022-11-03 08:21:24 +01:00
LegacyGamerHD de2b5597e1 Update waydroid_extras.py 2022-11-03 08:18:33 +01:00
LegacyGamerHD aab34beaca new houdini and new magisk 2022-11-03 06:39:27 +01:00
Casu Al Snek ( Sabin ) 4bdb95aee0 Update README.md 2022-07-22 11:48:11 +05:45
LegacyGamerHD 44ffa7152b Update waydroid_extras.py 2022-06-26 17:39:24 +02:00
LegacyGamerHD c91ab576e2 Update waydroid_extras.py 2022-06-26 17:36:01 +02:00
LegacyGamerHD 8f28a3723d Update waydroid_extras.py 2022-06-26 17:33:43 +02:00
LegacyGamerHD b9390a7ebc fix 2022-06-26 17:08:47 +02:00
LegacyGamerHD 8ad6bb8283 Update README.md 2022-06-26 12:16:14 +02:00
LegacyGamerHD 9e6c8fd67f Update waydroid_extras.py 2022-06-26 12:14:48 +02:00
LegacyGamerHD 05f84916e7 Update waydroid_extras.py 2022-06-26 11:37:00 +02:00
Casu Al Snek e496d2ece8 Archive the repo 2022-05-01 12:54:04 +05:45
Casu Al Snek 1c6e6456e6 Update README.md 2022-05-01 12:53:29 +05:45
Casu Al Snek f49918dab6 Merge pull request #41 from brccabral/patch-2
Update README with umount instructions
2022-04-15 08:50:18 +05:45
Bruno Cabral 02811ad01d Update README with umount instructions
this solves issue #33
2022-04-14 10:11:26 -07:00
42 changed files with 2149 additions and 640 deletions
+111
View File
@@ -0,0 +1,111 @@
git
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
*.out
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
.vscode
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
.idea/
# celery beat schedule file
celerybeat-schedule
workspace.xml
# SageMath parsed files
*.sage.py
.idea/workspace.xml
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# nix
result*
test.py
+173 -46
View File
@@ -1,78 +1,205 @@
# Waydroid Extras Script
[![Visits Badge](https://badges.pufler.dev/visits/casualsnek/waydroid_script)](https://github.com/casualsnek)
Script to add gapps and other stuff to waydroid !
Script to add GApps and other stuff to Waydroid!
# Installation/Usage
"lzip" and "sqlite" is required for this script to work, install it using your distribution's package manager:
## Arch, Manjaro and EndeavourOS based distributions:
sudo pacman -S lzip sqlite
## Debian and Ubuntu based distributions:
sudo apt install lzip sqlite
## RHEL, Fedora and Rocky based distributions:
sudo dnf install lzip sqlite
## openSUSE based distributions:
sudo zypper install lzip sqlite
Then run:
git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script
sudo python3 -m pip install -r requirements.txt
sudo python3 waydroid_extras.py [-i/-g/-n/-h]
## Interactive terminal interface
```
git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script
python3 -m venv venv
venv/bin/pip install -r requirements.txt
sudo venv/bin/python3 main.py
```
![image-20230430013103883](assets/img/README/image-20230430013103883.png)
![image-20230430013119763](assets/img/README/image-20230430013119763.png)
![image-20230430013148814](assets/img/README/image-20230430013148814.png)
## Command Line
```bash
git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script
python3 -m venv venv
venv/bin/pip install -r requirements.txt
# install something
sudo venv/bin/python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg, mitm}
# uninstall something
sudo venv/bin/python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
# get Android device ID
sudo venv/bin/python3 main.py certified
# some hacks
sudo venv/bin/python3 main.py hack {nodataperm, hidestatusbar}
```
## Dependencies
"lzip" is required for this script to work, install it using your distribution's package manager:
### Arch, Manjaro and EndeavourOS based distributions:
sudo pacman -S lzip
### Debian and Ubuntu based distributions:
sudo apt install lzip
### RHEL, Fedora and Rocky based distributions:
sudo dnf install lzip
### openSUSE based distributions:
sudo zypper install lzip
## Install OpenGapps
Open terminal and switch to directory where "waydroid_extras.py" is located then run:
![](assets/1.png)
sudo python3 waydroid_extras.py -g
Then restart waydroid service with command below :
Open terminal and switch to the directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install gapps
sudo systemctl start waydroid-container.service
Then launch waydroid with:
waydroid show-full-ui
After waydroid has finished booting open terminal and switch to directory where "waydroid_extras.py" is located then run:
sudo python3 waydroid_extras.py -i
Copy the returned numeric ID open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1) enter the id and register it, you may need to wait upto 10-20 minutes for device to get registered, then clear Google Play Service's cache and try logging in !
After waydroid has finished booting, open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py google
Copy the returned numeric ID, then open ["https://google.com/android/uncertified/?pli=1"](https://google.com/android/uncertified/?pli=1). Enter the ID and register it. Wait 10-20 minutes for device to get registered. Then clear Google Play Service's cache and try logging in!
## Install Magisk
Open terminal and switch to directory where "waydroid_extras.py" is located then run:
![](assets/2.png)
sudo python3 waydroid_extras.py -m
Then restart waydroid service with command below :
Open terminal and switch to directory where "main.py" is located then run:
sudo systemctl start waydroid-container.service
Magisk will be installed on next boot !
Note That this is bootless installation and modules don't work as of now !
sudo venv/bin/python3 main.py install magisk
Magisk will be installed on next boot!
Zygisk and modules like LSPosed should work now.
If you want to update Magisk, Please use `Direct Install into system partition` or run this sript again.
This script only focuses on Magisk installation, if you need more management, please check https://github.com/nitanmarcel/waydroid-magisk
## Install libndk arm translation
This may or may not work properly and is only for testing:
Open terminal and switch to directory where "waydroid_extras.py" is located then run:
libndk_translation from guybrush firmware.
sudo python3 waydroid_extras.py -n
Then restart waydroid service with command below :
libndk seems to have better performance than libhoudini on AMD.
sudo systemctl start waydroid-container.service
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install libndk
## Install libhoudini arm translation
This may or may not work properly and is only for testing: ( Much stable than libndk ) and works on android 11 images
Open terminal and switch to directory where "waydroid_extras.py" is located then run:
Intel's libhoudini for intel/AMD x86 CPU, pulled from Microsoft's WSA 11 image
houdini version: 11.0.1b_y.38765.m
houdini64 version: 11.0.1b_z.38765.m
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install libhoudini
## Integrate Widevine DRM (L3)
![](assets/3.png)
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install widevine
## Install Smart Dock
![](assets/4.png)
![](assets/5.png)
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install smartdock
## Install a self-signed CA certificate
Open terminal and switch to directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install mitm --ca-cert mycert.pem
## Granting full permission for apps data (HACK)
This is a temporary hack to combat against the apps permission issue on Android 11. Whenever an app is open it will always enable a property (persist.sys.nodataperm) to make it execute a script to grant the data full permissions (777). The **correct** way is to use `sdcardfs` or `esdfs`, both need to recompile the kernel or WayDroid image.
Arknights, PUNISHING: GRAY RAVEN and other games won't freeze on the black screen.
![](assets/6.png)
Open terminal and switch to directory where "main.py" is located then run:
```
sudo venv/bin/python3 main.py hack nodataperm
```
**WARNING**: Tested on `lineage-18.1-20230128-VANILLA-waydroid_x86_64.img`. This script will replace `/system/framework/service.jar`, which may prevent WayDroid from booting. If so, run `sudo venv/bin/python3 main.py uninstall nodataperm` to remove it.
Or you can run the following commands directly in `sudo waydroid shell`. In this way, every time a new game is installed, you need to run it again, but it's much less risky.
```
chmod 777 -R /sdcard/Android
chmod 777 -R /data/media/0/Android
chmod 777 -R /sdcard/Android/data
chmod 777 -R /data/media/0/Android/obb
chmod 777 -R /mnt/*/*/*/*/Android/data
chmod 777 -R /mnt/*/*/*/*/Android/obb
```
- https://github.com/supremegamers/device_generic_common/commit/2d47891376c96011b2ee3c1ccef61cb48e15aed6
- https://github.com/supremegamers/android_frameworks_base/commit/24a08bf800b2e461356a9d67d04572bb10b0e819
## Install microG, Aurora Store and Aurora Droid
![](assets/7.png)
```
sudo venv/bin/python3 main.py install microg
```
## Hide Status Bar
Before
![Before](assets/8.png)
After
![After](assets/9.png)
```
sudo venv/bin/python3 main.py hack hidestatusbar
```
sudo python3 waydroid_extras.py -l
Then restart waydroid service with command below :
sudo systemctl start waydroid-container.service
## Get Android ID for device registration
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for google apps:
Open terminal and switch to directory where "waydroid_extras.py" is located then run:
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for Google apps:
Open terminal and switch to directory where "main.py" is located then run:
sudo python3 waydroid_extras.py -i
sudo venv/bin/python3 main.py certified
Star this repository if you find this useful, if you encounter problem create a issue on github !
Star this repository if you find this useful, if you encounter problem create an issue on GitHub!
## Error handling
- Magisk installed: N/A
Check [waydroid-magisk](https://github.com/nitanmarcel/waydroid-magisk)
## Credits
- [WayDroid](https://github.com/waydroid/waydroid)
- [Magisk Delta](https://huskydg.github.io/magisk-files/)
- [microG Project](https://microg.org)
- [Open GApps](https://opengapps.org)
- [Smart Dock](https://github.com/axel358/smartdock)
- [wd-scripts](https://github.com/electrikjesus/wd-scripts/)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 590 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
let
pkgs = import <nixpkgs> {};
in
pkgs.callPackage ./package.nix { }
Generated
+41
View File
@@ -0,0 +1,41 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1707650010,
"narHash": "sha256-dOhphIA4MGrH4ElNCy/OlwmN24MsnEqFjRR6+RY7jZw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "809cca784b9f72a5ad4b991e0e7bcf8890f9c3a6",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+21
View File
@@ -0,0 +1,21 @@
{
description = "Waydroid Extras Script";
inputs = {
systems.url = "github:nix-systems/default";
};
outputs = { self, nixpkgs, systems }:
let
inherit (nixpkgs) lib;
eachSystem = lib.genAttrs (import systems);
mkApp = program: { type = "app"; inherit program; };
in {
packages = eachSystem (system: rec {
waydroid_script = nixpkgs.legacyPackages."${system}".callPackage ./package.nix { };
default = waydroid_script;
});
apps = eachSystem (system: rec {
waydroid_script = mkApp "${self.outputs.packages.${system}.waydroid_script}/bin/waydroid_script";
default = waydroid_script;
});
};
}
Executable
+357
View File
@@ -0,0 +1,357 @@
#!/usr/bin/env python3
from InquirerPy import inquirer
from InquirerPy.base.control import Choice
from InquirerPy.separator import Separator
import argparse
import os
from typing import List
from stuff.android_id import AndroidId
from stuff.gapps import Gapps
from stuff.general import General
from stuff.hidestatusbar import HideStatusBar
from stuff.houdini import Houdini
from stuff.magisk import Magisk
from stuff.microg import MicroG
from stuff.mitm import Mitm
from stuff.ndk import Ndk
from stuff.nodataperm import Nodataperm
from stuff.smartdock import Smartdock
from stuff.widevine import Widevine
from stuff.fdroidpriv import FDroidPriv
import tools.helper as helper
from tools import container
from tools import images
import argparse
from tools.logger import Logger
def get_certified(args):
AndroidId().get_id()
def mount(partition, copy_dir):
img = os.path.join(images.get_image_dir(), partition+".img")
mount_point = ""
if partition == "system":
mount_point = os.path.join(copy_dir)
else:
mount_point = os.path.join(copy_dir, partition)
Logger.info("Mounting {} to {}".format(img, mount_point))
images.mount(img, mount_point)
def resize(partition):
img = os.path.join(images.get_image_dir(), partition+".img")
img_size = int(os.path.getsize(img)/(1024*1024))
new_size = "{}M".format(img_size+500)
Logger.info("Resizing {} to {}".format(img, new_size))
images.resize(img, new_size)
def umount(partition, copy_dir):
mount_point = ""
if partition == "system":
mount_point = os.path.join(copy_dir)
else:
mount_point = os.path.join(copy_dir, partition)
Logger.info("Umounting {}".format(mount_point))
images.umount(mount_point)
def install_app(args):
install_list: List[General] = []
app = args.app
if "gapps" in app:
install_list.append(Gapps(args.android_version))
if "libndk" in app and "houdini" not in app:
arch = helper.host()[0]
if arch == "x86_64":
install_list.append(Ndk(args.android_version))
else:
Logger.warn("libndk is not supported on your CPU")
if "libhoudini" in app and "ndk" not in app:
arch = helper.host()[0]
if arch == "x86_64":
install_list.append(Houdini(args.android_version))
else:
Logger.warn("libhoudini is not supported on your CPU")
if "magisk" in app:
install_list.append(Magisk())
if "widevine" in app:
install_list.append(Widevine(args.android_version))
if "smartdock" in app:
install_list.append(Smartdock())
if "microg" in app:
install_list.append(MicroG(args.android_version, args.microg_variant))
if "mitm" in app:
install_list.append(Mitm(args.ca_cert_file))
if "fdroidpriv" in app:
install_list.append(FDroidPriv(args.android_version))
if not container.use_overlayfs():
copy_dir = "/tmp/waydroid"
container.stop()
resize_system, resize_vendor = False, False
for item in install_list:
if item.partition == "system":
resize_system = True
elif item.partition == "vendor":
resize_vendor = True
if resize_system:
resize("system")
if resize_vendor:
resize("vendor")
mount("system", copy_dir)
mount("vendor", copy_dir)
for item in install_list:
item.install()
if not container.use_overlayfs():
umount("vendor", copy_dir)
umount("system", copy_dir)
container.upgrade()
def remove_app(args):
remove_list: List[General] = []
app = args.app
if "gapps" in app:
remove_list.append(Gapps(args.android_version))
if "libndk" in app and "houdini" not in app:
remove_list.append(Ndk(args.android_version))
if "libhoudini" in app and "ndk" not in app:
remove_list.append(Houdini(args.android_version))
if "magisk" in app:
remove_list.append(Magisk())
if "widevine" in app:
remove_list.append(Widevine(args.android_version))
if "smartdock" in app:
remove_list.append(Smartdock())
if "microg" in app:
remove_list.append(MicroG(args.android_version, args.microg_variant))
if "mitm" in app:
remove_list.append(Mitm())
if "fdroidpriv" in app:
remove_list.append(FDroidPriv(args.android_version))
if "nodataperm" in app:
remove_list.append(Nodataperm(args.android_version))
if "hidestatusbar" in app:
remove_list.append(HideStatusBar())
if not container.use_overlayfs():
copy_dir = "/tmp/waydroid"
container.stop()
for item in remove_list:
item.uninstall()
if not container.use_overlayfs():
umount("vendor", copy_dir)
umount("system", copy_dir)
container.upgrade()
def hack_option(args):
Logger.warning(
"If these hacks cause any problems, run `sudo python main.py remove <hack_option>` to remove")
hack_list: List[General] = []
options = args.option_name
if "nodataperm" in options:
hack_list.append(Nodataperm())
if "hidestatusbar" in options:
hack_list.append(HideStatusBar())
if not container.use_overlayfs():
copy_dir = "/tmp/waydroid"
container.stop()
resize_system, resize_vendor = False, False
for item in hack_list:
if item.partition == "system":
resize_system = True
elif item.partition == "vendor":
resize_vendor = True
if resize_system:
resize("system")
if resize_vendor:
resize("vendor")
mount("system", copy_dir)
mount("vendor", copy_dir)
for item in hack_list:
item.install()
if not container.use_overlayfs():
umount("vendor", copy_dir)
umount("system", copy_dir)
container.upgrade()
def interact():
os.system("clear")
args = argparse.Namespace()
android_version = inquirer.select(
message="Select Android version",
instruction="(\u2191\u2193 Select Item)",
choices=[
Choice(name="Android 11", value="11"),
Choice(name="Android 13", value="13"),
Choice(name="Exit", value=None)
],
default="13",
).execute()
if not android_version:
exit()
args.android_version = android_version
action = inquirer.select(
message="Please select an action",
choices=[
"Install",
"Remove",
"Hack",
"Get Google Device ID to Get Certified"
],
instruction="([↑↓]: Select Item)",
default=None,
).execute()
if not action:
exit()
install_choices = ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "fdroidpriv", "widevine",]
hack_choices = []
if android_version=="11":
hack_choices.extend(["nodataperm", "hidestatusbar"])
if action == "Install":
apps = inquirer.checkbox(
message="Select apps",
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
validate=lambda result: len(result) >= 1,
invalid_message="should be at least 1 selection",
choices=install_choices
).execute()
microg_variants = ["Standard", "NoGoolag",
"UNLP", "Minimal", "MinimalIAP"]
if "microg" in apps:
microg_variant = inquirer.select(
message="Select MicroG variant",
choices=microg_variants,
default="Standard",
).execute()
args.microg_variant = microg_variant
args.app = apps
install_app(args)
elif action == "Remove":
apps = inquirer.checkbox(
message="Select apps",
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
validate=lambda result: len(result) >= 1,
invalid_message="should be at least 1 selection",
choices=[*install_choices, *hack_choices]
).execute()
args.app = apps
args.microg_variant="Standard"
remove_app(args)
elif action == "Hack":
apps = inquirer.checkbox(
message="Select hack options",
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
validate=lambda result: len(result) >= 1,
invalid_message="should be at least 1 selection",
choices=hack_choices
).execute()
args.option_name = apps
hack_option(args)
elif action == "Get Google Device ID to Get Certified":
AndroidId().get_id()
def main():
parser = argparse.ArgumentParser(description='''
Does stuff like installing Gapps, installing Magisk, installing NDK Translation and getting Android ID for device registration.
Use -h flag for help!''')
subparsers = parser.add_subparsers(title="coomand", dest='command')
parser.add_argument('-a', '--android-version',
dest='android_version',
help='Specify the Android version',
default="13",
choices=["11", "13"])
# android command
certified = subparsers.add_parser(
'certified', help='Get device ID to obtain Play Store certification')
certified.set_defaults(func=get_certified)
install_choices = ["gapps", "microg", "libndk", "libhoudini",
"magisk", "mitm", "smartdock", "widevine"]
hack_choices = ["nodataperm", "hidestatusbar"]
micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"]
remove_choices = install_choices
arg_template = {
"dest": "app",
"type": str,
"nargs": '+',
# "metavar":"",
}
install_help = """
gapps: Install Open GApps (Android 11) or MindTheGapps (Android 13)
microg: Add microG, Aurora Store and Aurora Droid to WayDriod
libndk: Add libndk arm translation, better for AMD CPUs
libhoudini: Add libhoudini arm translation, better for Intel CPUs
magisk: Install Magisk Delta to WayDroid
mitm -c CA_CERT_FILE: Install root CA cert into system trust store
smartdock: A desktop mode launcher for Android
widevine: Add support for widevine DRM L3
"""
# install and its aliases
install_parser = subparsers.add_parser(
'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
install_parser.add_argument(
**arg_template, choices=install_choices, help=install_help)
install_parser.add_argument('-c', '--ca-cert',
dest='ca_cert_file',
help='[for mitm only] The CA certificate file (*.pem) to install',
default=None)
install_parser.set_defaults(func=install_app)
# remove and its aliases
remove_parser = subparsers.add_parser(
'remove', aliases=["uninstall"], help='Remove an app')
remove_parser.add_argument(
**arg_template, choices=[*remove_choices, * hack_choices], help='Name of app to remove')
remove_parser.set_defaults(func=remove_app)
# hack and its aliases
hack_parser = subparsers.add_parser('hack', help='Hack the system')
hack_parser.add_argument(
'option_name', nargs="+", choices=hack_choices, help='Name of hack option')
hack_parser.set_defaults(func=hack_option)
args = parser.parse_args()
args.microg_variant = "Standard"
if hasattr(args, 'func'):
args_dict = vars(args)
helper.check_root()
args.func(args)
else:
helper.check_root()
interact()
if __name__ == "__main__":
main()
+32
View File
@@ -0,0 +1,32 @@
{ lib,
stdenvNoCC,
lzip,
python3,
makeWrapper }:
let
wrappedPath = lib.makeBinPath [ lzip ];
in stdenvNoCC.mkDerivation {
name = "waydroid_script";
buildInputs = [
(python3.withPackages(ps: with ps; [ tqdm requests inquirerpy ]))
];
nativeBuildInputs = [
makeWrapper
];
src = ./.;
postPatch = ''
patchShebangs main.py
'';
installPhase = ''
mkdir -p $out/libexec
cp -r . $out/libexec/waydroid_script
mkdir -p $out/bin
makeShellWrapper $out/libexec/waydroid_script/main.py $out/bin/waydroid_script \
--prefix PATH : "${wrappedPath}"
'';
}
+1
View File
@@ -1,2 +1,3 @@
tqdm
requests
InquirerPy
+21
View File
@@ -0,0 +1,21 @@
from tools import container
from tools.helper import shell
from tools.logger import Logger
class AndroidId:
def get_id(self):
if container.is_running():
try:
queryout = shell(
arg="sqlite3 /data/data/com.google.android.gsf/databases/gservices.db \"select * from main where name = 'android_id';\"",
env="ANDROID_RUNTIME_ROOT=/apex/com.android.runtime ANDROID_DATA=/data ANDROID_TZDATA_ROOT=/apex/com.android.tzdata ANDROID_I18N_ROOT=/apex/com.android.i18n"
)
except:
return
else:
Logger.error("Please make sure Waydroid is running and Gapps has been installed!")
return
print(queryout.replace("android_id|", "").strip())
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
print(" Login with your google id then submit the form with id shown above")
+42
View File
@@ -0,0 +1,42 @@
import os
import shutil
from stuff.general import General
class FDroidPriv(General):
id = "fdroid priv"
dl_links = {"11": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
"6242cab56d197d80c598593a46da62e4"],
"13": ["https://f-droid.org/repo/org.fdroid.fdroid.privileged.ota_2130.zip",
"6242cab56d197d80c598593a46da62e4"]}
partition = "system"
dl_file_name = "org.fdroid.fdroid.privileged.ota_2130.zip"
dl_link = ...
act_md5 = ...
extract_to = "/tmp/fdroid_ota_2130"
files = [
"app/F-Droid.apk"
"app/F-Droid/F-Droid.apk"
"etc/permissions/permissions_org.fdroid.fdroid.privileged.xml"
"priv-app/F-DroidPrivilegedExtension.apk"
"priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk"
]
file_map = {
"permissions_org.fdroid.fdroid.privileged.xml": "etc/permissions/permissions_org.fdroid.fdroid.privileged.xml",
"F-Droid.apk": "app/F-Droid/F-Droid.apk",
"F-DroidPrivilegedExtension.apk": "priv-app/F-DroidPrivilegedExtension/F-DroidPrivilegedExtension.apk",
}
def __init__(self, android_version="11") -> None:
super().__init__()
self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self):
for f, d in self.file_map.items():
rro_file = os.path.join(
self.copy_dir, self.partition, d)
rro_dir = os.path.dirname(rro_file)
if not os.path.exists(rro_dir):
os.makedirs(rro_dir)
shutil.copyfile(os.path.join(self.extract_to, f), rro_file)
+172
View File
@@ -0,0 +1,172 @@
import os
import shutil
from stuff.general import General
from tools.helper import run
class Gapps(General):
id = ...
partition = "system"
dl_links = {
"11": {
"x86_64": ["https://sourceforge.net/projects/opengapps/files/x86_64/20220503/open_gapps-x86_64-11.0-pico-20220503.zip", "5a6d242be34ad1acf92899c7732afa1b"],
"x86": ["https://sourceforge.net/projects/opengapps/files/x86/20220503/open_gapps-x86-11.0-pico-20220503.zip", "efda4943076016d00b40e0874b12ddd3"],
"arm64-v8a": ["https://sourceforge.net/projects/opengapps/files/arm64/20220503/open_gapps-arm64-11.0-pico-20220503.zip", "7790055d34bbfc6fe610b0cd263a7add"],
"armeabi-v7a": ["https://sourceforge.net/projects/opengapps/files/arm/20220215/open_gapps-arm-11.0-pico-20220215.zip", "8719519fa32ae83a62621c6056d32814"]
},
"13": {
"x86_64": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86_64-20231028.zip", "63ccebbf93d45c384f58d7c40049d398"],
"x86": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-x86-20231028.zip", "f12b6a8ed14eedbb4b5b3c932a865956"],
"arm64-v8a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm64-20231028.zip", "11180da0a5d9f2ed2863882c30a8d556"],
"armeabi-v7a": ["https://github.com/s1204IT/MindTheGappsBuilder/releases/download/20231028/MindTheGapps-13.0.0-arm-20231028.zip", "d525c980bac427844aa4cb01628f8a8f"]
}
}
android_version = ...
dl_link = ...
act_md5 = ...
dl_file_name = "gapps.zip"
extract_to = "/tmp/gapps/extract"
non_apks = [
"defaultetc-common.tar.lz",
"defaultframework-common.tar.lz",
"googlepixelconfig-common.tar.lz",
"vending-common.tar.lz"
]
skip = [
"setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz"
]
files = [
"etc/default-permissions/default-permissions.xml",
"etc/default-permissions/opengapps-permissions-q.xml",
"etc/permissions/com.google.android.maps.xml",
"etc/permissions/com.google.android.media.effects.xml",
"etc/permissions/privapp-permissions-google.xml",
"etc/permissions/split-permissions-google.xml",
"etc/preferred-apps/google.xml",
"etc/sysconfig/google.xml",
"etc/sysconfig/google_build.xml",
"etc/sysconfig/google_exclusives_enable.xml",
"etc/sysconfig/google-hiddenapi-package-whitelist.xml",
"framework/com.google.android.maps.jar",
"framework/com.google.android.media.effects.jar",
"priv-app/AndroidMigratePrebuilt",
"priv-app/GoogleExtServices",
"priv-app/GoogleRestore",
"priv-app/CarrierSetup",
"priv-app/GoogleExtShared",
"priv-app/GoogleServicesFramework",
"priv-app/ConfigUpdater",
"priv-app/GoogleFeedback",
"priv-app/Phonesky",
"priv-app/GoogleBackupTransport",
"priv-app/GoogleOneTimeInitializer",
"priv-app/PrebuiltGmsCore",
"priv-app/GoogleContactsSyncAdapter",
"priv-app/GooglePartnerSetup",
"product/overlay/PlayStoreOverlay.apk",
"product/overlay/GmsOverlay.apk.apk",
"product/overlay/GmsSettingsProviderOverlay.apk",
"system_ext/etc/permissions/privapp-permissions-google-system-ext.xml",
"system_ext/priv-app/GoogleFeedback",
"system_ext/priv-app/GoogleServicesFramework",
"system_ext/priv-app/SetupWizard",
"product/priv-app/GmsCore",
"product/priv-app/AndroidAutoStub",
"product/priv-app/GoogleRestore",
"product/priv-app/Phonesky",
"product/priv-app/Velvet",
"product/priv-app/GooglePartnerSetup",
"product/app/GoogleCalendarSyncAdapter",
"product/app/PrebuiltExchange3Google",
"product/app/GoogleContactsSyncAdapter",
"product/framework/com.google.android.dialer.support.jar",
"product/lib64/libjni_latinimegoogle.so",
"product/etc/default-permissions/default-permissions-google.xml",
"product/etc/default-permissions/default-permissions-mtg.xml",
"product/etc/sysconfig/google.xml",
"product/etc/sysconfig/d2d_cable_migration_feature.xml",
"product/etc/sysconfig/google-hiddenapi-package-allowlist.xml",
"product/etc/sysconfig/google_build.xml",
"product/etc/permissions/privapp-permissions-google-product.xml",
"product/etc/permissions/com.google.android.dialer.support.xml",
"product/etc/security/fsverity/gms_fsverity_cert.der",
"product/lib/libjni_latinimegoogle.so",
]
def __init__(self, android_version="11") -> None:
super().__init__()
self.android_version = android_version
self.dl_link = self.dl_links[android_version][self.arch[0]][0]
self.act_md5 = self.dl_links[android_version][self.arch[0]][1]
if android_version == "11":
self.id = "OpenGapps"
else:
self.id = "MindTheGapps"
def copy(self):
if self.android_version == "11":
return self.copy_11()
elif self.android_version == "13":
return self.copy_13()
def copy_11(self):
if not os.path.exists(self.extract_to):
os.makedirs(self.extract_to)
if not os.path.exists(os.path.join(self.extract_to, "appunpack")):
os.makedirs(os.path.join(self.extract_to, "appunpack"))
for lz_file in os.listdir(os.path.join(self.extract_to, "Core")):
for d in os.listdir(os.path.join(self.extract_to, "appunpack")):
shutil.rmtree(os.path.join(self.extract_to, "appunpack", d))
if lz_file not in self.skip:
if lz_file not in self.non_apks:
print(" Processing app package : " +
os.path.join(self.extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(self.extract_to, "Core",
lz_file), "-C", os.path.join(self.extract_to, "appunpack")])
app_name = os.listdir(os.path.join(
self.extract_to, "appunpack"))[0]
xx_dpi = os.listdir(os.path.join(
self.extract_to, "appunpack", app_name))[0]
app_priv = os.listdir(os.path.join(
self.extract_to, "appunpack", app_name, "nodpi"))[0]
app_src_dir = os.path.join(
self.extract_to, "appunpack", app_name, xx_dpi, app_priv)
for app in os.listdir(app_src_dir):
shutil.copytree(os.path.join(app_src_dir, app), os.path.join(
self.copy_dir, self.partition, "priv-app", app), dirs_exist_ok=True)
for f in os.listdir(os.path.join(self.copy_dir, self.partition, "priv-app", app)):
dst_file_path = os.path.join(os.path.join(
self.copy_dir, self.partition, "priv-app", app), f)
if os.path.splitext(dst_file_path)[1].lower() == ".apk":
self.extract_app_lib(dst_file_path)
else:
print(" Processing extra package : " +
os.path.join(self.extract_to, "Core", lz_file))
run(["tar", "--lzip", "-xvf", os.path.join(self.extract_to, "Core",
lz_file), "-C", os.path.join(self.extract_to, "appunpack")])
app_name = os.listdir(os.path.join(
self.extract_to, "appunpack"))[0]
common_content_dirs = os.listdir(os.path.join(
self.extract_to, "appunpack", app_name, "common"))
for ccdir in common_content_dirs:
shutil.copytree(os.path.join(self.extract_to, "appunpack", app_name, "common", ccdir), os.path.join(
self.copy_dir, self.partition, ccdir), dirs_exist_ok=True)
def copy_13(self):
src_dir = os.path.join(self.extract_to, "system")
dst_dir = os.path.join(self.copy_dir, self.partition)
for root, dirs, files in os.walk(src_dir):
dir_name = os.path.basename(root)
# 遍历文件
for file in files:
src_file_path = os.path.join(root, file)
dst_file_path = os.path.join(dst_dir, os.path.relpath(
src_file_path, src_dir))
if not os.path.exists(os.path.dirname(dst_file_path)):
os.makedirs(os.path.dirname(dst_file_path))
# Logger.info(f"{src_file_path} -> {dst_file_path}")
shutil.copy2(src_file_path, dst_file_path)
if os.path.splitext(dst_file_path)[1].lower() == ".apk":
self.extract_app_lib(dst_file_path)
+190
View File
@@ -0,0 +1,190 @@
import configparser
import glob
import os
import shutil
import zipfile
import hashlib
from tools.helper import download_file, get_download_dir, host
from tools import container
from tools.logger import Logger
class General:
files = []
@property
def arch(self):
return host()
@property
def skip_extract(self):
return False
@property
def download_loc(self):
return os.path.join(get_download_dir(), self.dl_file_name)
@property
def copy_dir(self):
if container.use_overlayfs():
return "/var/lib/waydroid/overlay"
else:
return "/tmp/waydroid"
def download(self):
Logger.info("Downloading {} now to {} .....".format(
self.dl_file_name, self.download_loc))
loc_md5 = ""
if os.path.isfile(self.download_loc):
with open(self.download_loc, "rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
while not os.path.isfile(self.download_loc) or loc_md5 != self.act_md5:
if os.path.isfile(self.download_loc):
os.remove(self.download_loc)
Logger.warning(
"md5 mismatches, redownloading now ....")
loc_md5 = download_file(self.dl_link, self.download_loc)
def remove(self):
for f in self.files:
file = os.path.join(self.copy_dir, self.partition, f)
if "*" in file:
for wildcard_file in glob.glob(file):
if os.path.isdir(wildcard_file):
shutil.rmtree(wildcard_file)
elif os.path.isfile(wildcard_file):
os.remove(wildcard_file)
else:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
def extract(self):
Logger.info(f"Extracting {self.download_loc} to {self.extract_to}")
with zipfile.ZipFile(self.download_loc) as z:
z.extractall(self.extract_to)
def add_props(self):
bin_dir = os.path.join(self.copy_dir, "system", "etc")
resetprop_rc = os.path.join(
self.copy_dir, "system/etc/init/resetprop.rc")
if not os.path.isfile(os.path.join(bin_dir, "resetprop")):
if not os.path.exists(bin_dir):
os.makedirs(bin_dir)
shutil.copy(os.path.join(os.path.join(os.path.dirname(__file__), "..", "bin",
self.arch[0], "resetprop")), bin_dir)
os.chmod(os.path.join(bin_dir, "resetprop"), 0o755)
if not os.path.isfile(os.path.join(bin_dir, "resetprop.sh")):
with open(os.path.join(bin_dir, "resetprop.sh"), "w") as f:
f.write("#!/system/bin/sh\n")
f.write(
"while read line; do /system/etc/resetprop ${line%=*} ${line#*=}; done < /vendor/waydroid.prop\n")
os.chmod(os.path.join(bin_dir, "resetprop.sh"), 0o755)
if not os.path.isfile(resetprop_rc):
if not os.path.exists(os.path.dirname(resetprop_rc)):
os.makedirs(os.path.dirname(resetprop_rc))
with open(resetprop_rc, "w") as f:
f.write(
"on post-fs-data\n exec u:r:su:s0 root root -- /system/bin/sh /system/bin/resetprop.sh")
os.chmod(resetprop_rc, 0o644)
cfg = configparser.ConfigParser()
cfg.read("/var/lib/waydroid/waydroid.cfg")
for key in self.apply_props.keys():
if self.apply_props[key]:
cfg.set('properties', key, self.apply_props[key])
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
def extract_app_lib(self, apk_file_path):
lib_dest_dir = os.path.dirname(apk_file_path)
with zipfile.ZipFile(apk_file_path, "r") as apk:
for file_info in apk.infolist():
file_name = file_info.filename
file_path = os.path.join(lib_dest_dir, file_name)
if file_info.filename.startswith(f"lib/{self.arch[0]}/") and file_name.endswith(".so"):
os.makedirs(os.path.dirname(
file_path), exist_ok=True)
with apk.open(file_info.filename) as src_file, open(file_path, "wb") as dest_file:
# Logger.info(f"{src_file} -> {dest_file}")
shutil.copyfileobj(src_file, dest_file)
def set_path_perm(self, path):
if "bin" in path.split("/"):
perms = [0, 2000, 0o755, 0o777]
else:
perms = [0, 0, 0o755, 0o644]
mode = os.stat(path).st_mode
if os.path.isdir(path):
mode |= perms[2]
else:
mode |= perms[3]
os.chown(path, perms[0], perms[1])
os.chmod(path, mode)
def set_perm2(self, path, recursive=False):
if not os.path.exists(path):
return
if recursive and os.path.isdir(path):
for root, dirs, files in os.walk(path):
for dir in dirs:
self.set_path_perm(os.path.join(root, dir))
for file in files:
self.set_path_perm(os.path.join(root, file))
else:
self.set_path_perm(path)
def set_perm(self):
for f in self.files:
path = os.path.join(self.copy_dir, self.partition, f)
if "*" in path:
for wildcard_file in glob.glob(path):
self.set_perm2(wildcard_file, recursive=True)
else:
self.set_perm2(path, recursive=True)
def remove_props(self):
cfg = configparser.ConfigParser()
cfg.read("/var/lib/waydroid/waydroid.cfg")
for key in self.apply_props.keys():
cfg.remove_option('properties', key)
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
def copy(self):
pass
def extra1(self):
pass
def extra2(self):
pass
def install(self):
self.download()
if not self.skip_extract:
self.extract()
self.copy()
self.extra1()
if hasattr(self, "apply_props"):
self.add_props()
self.set_perm()
Logger.info(f"{self.id} installation finished")
def uninstall(self):
self.remove()
if hasattr(self, "apply_props"):
self.remove_props()
self.extra2()
self.set_perm()
Logger.info("Uninstallation finished")
+31
View File
@@ -0,0 +1,31 @@
import os
import shutil
from stuff.general import General
class HideStatusBar(General):
id = "hide status bar"
dl_links = {"11": ["https://github.com/ayasa520/hide-status-bar/releases/download/v0.0.2/app-release.apk",
"ff2fe63ddfb4b035e6720a1b195b2355"]}
partition = "system"
dl_file_name = "hidestatusbar.apk"
dl_link = ...
act_md5 = ...
files = [
"product/overlay/"+dl_file_name
]
def __init__(self, android_version="11") -> None:
super().__init__()
self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self):
rro_dir = os.path.join(
self.copy_dir, self.partition, "product", "overlay")
if not os.path.exists(rro_dir):
os.makedirs(rro_dir)
shutil.copyfile(self.download_loc, os.path.join(
rro_dir, "hidestatusbar.apk"))
def skip_extract(self):
return True
+66
View File
@@ -0,0 +1,66 @@
import os
import re
import shutil
from stuff.general import General
from tools.logger import Logger
class Houdini(General):
id = "libhoudini"
partition = "system"
dl_links = {
"11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"],
"13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/9e77896350caccd228b36b2e1b4a994aa4bd48da.zip", "3807fe029559db3037efe245d9e74270"]
}
act_md5 = ...
dl_link = ...
dl_file_name = "libhoudini.zip"
extract_to = "/tmp/houdiniunpack"
init_rc_component = """
on early-init
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x28::/system/bin/houdini:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
"""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libhoudini.so",
"ro.enable.native.bridge.exec": "1",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
files = [
"bin/arm",
"bin/arm64",
"bin/houdini",
"bin/houdini64",
"etc/binfmt_misc",
"etc/init/houdini.rc",
"lib/arm",
"lib/libhoudini.so",
"lib64/arm64",
"lib64/libhoudini.so"
]
def __init__(self, android_version="11") -> None:
super().__init__()
self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self):
Logger.info("Copying libhoudini library files ...")
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
shutil.copytree(os.path.join(self.extract_to, "vendor_intel_proprietary_houdini-" + name,
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
init_path = os.path.join(
self.copy_dir, self.partition, "etc", "init", "houdini.rc")
if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component)
+163
View File
@@ -0,0 +1,163 @@
import gzip
import os
import shutil
import re
from stuff.general import General
from tools.helper import download_file, get_data_dir, host
from tools.logger import Logger
from tools import container
class Magisk(General):
id = "magisk delta"
partition = "system"
dl_link = "https://github.com/mistrmochov/magiskdeltaorig/raw/main/app-release.apk"
dl_file_name = "magisk.apk"
extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk")
files = ["etc/init/magisk", "etc/init/bootanim.rc"]
oringinal_bootanim = """
service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
disabled
oneshot
ioprio rt 0
task_profiles MaxPerformance
"""
bootanim_component = f"""
on post-fs-data
start logd
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
exec u:r:magisk:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
exec u:r:update_engine:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk
mkdir /dev/magisk_iqeoVo2mDrO 700
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk64 --auto-selinux --setup-sbin /system/etc/init/magisk /dev/magisk_iqeoVo2mDrO
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --post-fs-data
on nonencrypted
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
on property:vold.decrypt=trigger_restart_framework
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --service
on property:sys.boot_completed=1
mkdir /data/adb/magisk 755
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --boot-complete
on property:init.svc.zygote=restarting
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
on property:init.svc.zygote=stopped
exec u:r:su:s0 root root -- /dev/magisk_iqeoVo2mDrO/magisk --auto-selinux --zygote-restart
"""
def download(self):
if os.path.isfile(self.download_loc):
os.remove(self.download_loc)
Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc))
download_file(self.dl_link, self.download_loc)
# require additional setup
def setup(self):
Logger.info("Additional setup")
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
data_dir = get_data_dir()
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True)
def copy(self):
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
if not os.path.exists(magisk_absolute_dir):
os.makedirs(magisk_absolute_dir, exist_ok=True)
if not os.path.exists(os.path.join(self.copy_dir, "sbin")):
os.makedirs(os.path.join(self.copy_dir, "sbin"), exist_ok=True)
Logger.info("Copying magisk libs now ...")
lib_dir = os.path.join(self.extract_to, "lib", self.arch[0])
for parent, dirnames, filenames in os.walk(lib_dir):
for filename in filenames:
o_path = os.path.join(lib_dir, filename)
filename = re.search('lib(.*)\.so', filename)
n_path = os.path.join(magisk_absolute_dir, filename.group(1))
shutil.copyfile(o_path, n_path)
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
shutil.copytree(os.path.join(self.extract_to, "assets", "chromeos"), os.path.join(magisk_absolute_dir, "chromeos"), dirs_exist_ok=True)
assets_files = [
"addon.d.sh",
"boot_patch.sh",
"stub.apk",
"util_functions.sh"
]
for f in assets_files:
shutil.copyfile(os.path.join(self.extract_to, "assets", f), os.path.join(magisk_absolute_dir, f))
# Updating Magisk from Magisk manager will modify bootanim.rc,
# So it is necessary to backup the original bootanim.rc.
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
gz_filename = os.path.join(bootanim_path)+".gz"
with gzip.open(gz_filename,'wb') as f_gz:
f_gz.write(self.oringinal_bootanim.encode('utf-8'))
with open(bootanim_path, "w") as initfile:
initfile.write(self.oringinal_bootanim+self.bootanim_component)
def set_path_perm(self, path):
if "magisk" in path.split("/"):
perms = [0, 2000, 0o755, 0o755]
else:
perms = [0, 0, 0o755, 0o644]
mode = os.stat(path).st_mode
if os.path.isdir(path):
mode |= perms[2]
else:
mode |= perms[3]
os.chown(path, perms[0], perms[1])
os.chmod(path, mode)
def extra1(self):
self.delete_upper()
self.setup()
# Delete the contents of upperdir
def delete_upper(self):
if container.use_overlayfs():
sys_overlay_rw = "/var/lib/waydroid/overlay_rw"
files = [
"system/system/etc/init/bootanim.rc",
"system/system/etc/init/bootanim.rc.gz",
"system/system/etc/init/magisk",
"system/system/addon.d/99-magisk.sh",
"vendor/etc/selinux/precompiled_sepolicy"
]
for f in files:
file = os.path.join(sys_overlay_rw, f)
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file) or os.path.exists(file):
os.remove(file)
def extra2(self):
self.delete_upper()
data_dir = get_data_dir()
files = [
os.path.join(data_dir, "adb/magisk.db"),
os.path.join(data_dir, "adb/magisk")
]
for file in files:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
if container.use_overlayfs():
if os.path.exists(bootanim_path):
os.remove(bootanim_path)
else:
with open(bootanim_path, "w") as initfile:
initfile.write(self.oringinal_bootanim)
+176
View File
@@ -0,0 +1,176 @@
import os
import shutil
from stuff.general import General
from tools.logger import Logger
class MicroG(General):
id = "MicroG"
partition = "system"
fdroid_repo_apks = {
"com.aurora.store_41.apk": "9e6c79aefde3f0bbfedf671a2d73d1be",
"com.etesync.syncadapter_20300.apk": "997d6de7d41c454d39fc22cd7d8fc3c2",
"com.aurora.adroid_8.apk": "0010bf93f02c2d18daf9e767035fefc5",
"org.fdroid.fdroid.privileged_2130.apk": "b04353155aceb36207a206d6dd14ba6a",
"org.microg.nlp.backend.ichnaea_20036.apk": "0b3cb65f8458d1a5802737c7392df903",
"org.microg.nlp.backend.nominatim_20042.apk": "88e7397cbb9e5c71c8687d3681a23383",
}
microg_apks= {
"com.google.android.gms-223616054.apk": "a945481ca5d33a03bc0f9418263c3228",
"com.google.android.gsf-8.apk": "b2b4ea3642df6158e14689a4b2a246d4",
"com.android.vending-22.apk": "6815d191433ffcd8fa65923d5b0b0573",
"org.microg.gms.droidguard-14.apk": "4734b41c1a6bc34a541053ddde7a0f8e"
}
priv_apps = ["com.google.android.gms", "com.android.vending"]
dl_links = {
"Standard": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Standard-2.11.1-20230429100529.zip",
"0fe332a9caa3fbb294f2e2b50f720c6b"
],
"NoGoolag": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-NoGoolag-2.11.1-20230429100545.zip",
"ff920f33f4c874eeae4c0444be427c68"
],
"UNLP": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-UNLP-2.11.1-20230429100555.zip",
"6136b383153c2a6797d14fb4d7ca3f97"
],
"Minimal": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-Minimal-2.11.1-20230429100521.zip"
"afb87eb64e7749cfd72c4760d85849da"
],
"MinimalIAP": [
"https://github.com/ayasa520/MinMicroG/releases/download/latest/MinMicroG-MinimalIAP-2.11.1-20230429100556.zip"
"cc071f4f776cbc16c4c1f707aff1f7fa"
]
}
dl_link = ...
act_md5 = ...
dl_file_name = ...
sdk = ...
extract_to = "/tmp/microg/extract"
rc_content = '''
on property:sys.boot_completed=1
start microg_service
service microg_service /system/bin/sh /system/bin/npem
user root
group root
oneshot
'''
files = [
"priv-app/GoogleBackupTransport",
"priv-app/MicroGUNLP",
"priv-app/MicroGGMSCore",
"priv-app/MicroGGMSCore/lib/x86_64/libmapbox-gl.so",
"priv-app/MicroGGMSCore/lib/x86_64/libconscrypt_gmscore_jni.so",
"priv-app/MicroGGMSCore/lib/x86_64/libcronet.102.0.5005.125.so",
"priv-app/PatchPhonesky",
"priv-app/PatchPhonesky/lib/x86_64/libempty_x86_64.so",
"priv-app/AuroraServices",
"bin/npem",
"app/GoogleCalendarSyncAdapter",
"app/NominatimNLPBackend",
"app/MicroGGSFProxy",
"app/LocalGSMNLPBackend",
"app/DejaVuNLPBackend",
"app/MozillaUnifiedNLPBackend",
"app/AppleNLPBackend",
"app/AuroraDroid",
"app/LocalWiFiNLPBackend",
"app/GoogleContactsSyncAdapter",
"app/MicroGGSFProxy/MicroGGSFProxy",
"framework/com.google.widevine.software.drm.jar",
"framework/com.google.android.media.effects.jar",
"framework/com.google.android.maps.jar",
"lib64/libjni_keyboarddecoder.so",
"lib64/libjni_latinimegoogle.so",
"etc/default-permissions/microg-permissions.xml",
"etc/default-permissions/microg-permissions-unlp.xml",
"etc/default-permissions/gsync.xml",
"etc/sysconfig/nogoolag.xml",
"etc/sysconfig/nogoolag-unlp.xml",
"etc/init/microg.rc",
"etc/permissions/com.google.android.backuptransport.xml",
"etc/permissions/com.android.vending.xml",
"etc/permissions/foss-permissions.xml",
"etc/permissions/com.google.android.gms.xml",
"etc/permissions/com.aurora.services.xml",
"etc/permissions/com.google.android.maps.xml",
"etc/permissions/com.google.widevine.software.drm.xml",
"etc/permissions/com.google.android.media.effects.xml",
"lib/libjni_keyboarddecoder.so",
"lib/libjni_latinimegoogle.so",
]
def __init__(self, android_version="11", variant="Standard") -> None:
super().__init__()
self.dl_link = self.dl_links[variant][0]
self.act_md5 = self.dl_links[variant][1]
self.id = self.id+f"-{variant}"
self.dl_file_name = f'MinMicroG-{variant}.zip'
if android_version == "11":
self.sdk = 30
elif android_version == "13":
self.sdk = 33
def copy(self):
Logger.info("Copying libs and apks...")
dst_dir = os.path.join(self.copy_dir, self.partition)
src_dir = os.path.join(self.extract_to, "system")
if "arm" in self.arch[0]:
sub_arch = "arm"
else:
sub_arch = "x86"
if 64 == self.arch[1]:
arch = f"{sub_arch}{'' if sub_arch=='arm' else '_'}64"
for root, dirs, files in os.walk(src_dir):
flag = False
dir_name = os.path.basename(root)
# 遍历文件
if dir_name.startswith('-') and dir_name.endswith('-'):
archs, sdks = [], []
for i in dir_name.split("-"):
if i.isdigit():
sdks.append(i)
elif i:
archs.append(i)
if len(archs) != 0 and arch not in archs and sub_arch not in archs or len(sdks) != 0 and str(self.sdk) not in sdks:
continue
else:
flag = True
for file in files:
src_file_path = os.path.join(root, file)
if not flag:
dst_file_path = os.path.join(dst_dir, os.path.relpath(
src_file_path, src_dir))
else:
dst_file_path = os.path.join(dst_dir, os.path.relpath(
os.path.join(os.path.dirname(root), file), src_dir))
if not os.path.exists(os.path.dirname(dst_file_path)):
os.makedirs(os.path.dirname(dst_file_path))
# Logger.info(f"{src_file_path} -> {dst_file_path}")
shutil.copy2(src_file_path, dst_file_path)
if os.path.splitext(dst_file_path)[1].lower() == ".apk":
self.extract_app_lib(dst_file_path)
rc_dir = os.path.join(dst_dir, "etc/init/microg.rc")
if not os.path.exists(os.path.dirname(rc_dir)):
os.makedirs(os.path.dirname(rc_dir))
with open(rc_dir, "w") as f:
f.write(self.rc_content)
def extra2(self):
system_dir = os.path.join(self.copy_dir, self.partition)
files = [key.split("_")[0] for key in self.fdroid_repo_apks.keys()]
files += [key.split("-")[0] for key in self.microg_apks.keys()]
for f in files:
if f in self.priv_apps:
file = os.path.join(system_dir, "priv-app", f)
else:
file = os.path.join(system_dir, "app", f)
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)
+40
View File
@@ -0,0 +1,40 @@
import os
import shutil
from stuff.general import General
from tools.helper import run
from tools.logger import Logger
class Mitm(General):
id = "mitm"
partition = "system"
def __init__(self, ca_cert_file: str=None) -> None:
super().__init__()
self.ca_cert_file = ca_cert_file
def download(self):
pass
def skip_extract(self):
return True
def copy(self):
file_hash = run([
'openssl', 'x509', '-noout', '-subject_hash_old', '-in',
self.ca_cert_file,
]).stdout.decode("ascii").strip()
target_dir = os.path.join(
self.copy_dir, self.partition, "etc", "security", "cacerts")
Logger.info(f"Creating directory: {target_dir}")
os.makedirs(target_dir, exist_ok=True)
target_path = os.path.join(target_dir, f'{file_hash}.0')
Logger.info(f"Copying {self.ca_cert_file} to system trust store")
Logger.info(f"Target file: {target_path}")
shutil.copyfile(self.ca_cert_file, target_path)
os.chmod(target_path, 0o644)
def install(self):
if not self.ca_cert_file:
raise ValueError(
"This command requires the --ca-cert switch and a *.pem file")
super().install()
+52
View File
@@ -0,0 +1,52 @@
import os
import re
import shutil
from stuff.general import General
from tools.logger import Logger
class Ndk(General):
id = "libndk"
partition = "system"
dl_links = {
"11": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/9324a8914b649b885dad6f2bfd14a67e5d1520bf.zip", "c9572672d1045594448068079b34c350"],
"13": ["https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/68734c52556d3d7a6db34c603dd9276915c29f2f.zip", "0b2207c490fcb400aa5c87fcf0d52d38"]
}
dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack"
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
"ro.enable.native.bridge.exec": "1",
"ro.vendor.enable.native.bridge.exec": "1",
"ro.vendor.enable.native.bridge.exec64": "1",
"ro.ndk_translation.version": "0.2.3",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
files = [
"bin/arm",
"bin/arm64",
"bin/ndk_translation_program_runner_binfmt_misc",
"bin/ndk_translation_program_runner_binfmt_misc_arm64",
"etc/binfmt_misc",
"etc/ld.config.arm.txt",
"etc/ld.config.arm64.txt",
"etc/init/ndk_translation.rc",
"lib/arm",
"lib64/arm64",
"lib/libndk*",
"lib64/libndk*"
]
def __init__(self, android_version="11") -> None:
super().__init__()
self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self):
Logger.info("Copying libndk library files ...")
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_ndk_translation-prebuilt-" + name,
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
+79
View File
@@ -0,0 +1,79 @@
import os
import re
import shutil
from stuff.general import General
from tools.helper import backup, restore
from tools.logger import Logger
from tools import container
class Nodataperm(General):
id = "nodataperm"
dl_links = {
"11": {
"x86_64": [
"https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
"b0e3908ffcf5df8ea62f4929aa680f1a"
],
},
"13": {
"x86_64": [
"https://github.com/ayasa520/hack_full_data_permission/archive/d4beab7780eb792059d33e77d865579c9ee41546.zip",
"b0e3908ffcf5df8ea62f4929aa680f1a"
],
},
}
dl_file_name = "nodataperm.zip"
extract_to = "/tmp/nodataperm"
dl_link = None
act_md5 = None
partition = "system"
files = [
"etc/nodataperm.sh",
"etc/init/nodataperm.rc",
"framework/services.jar",
"framework/services.jar.prof",
"framework/services.jar.bprof",
]
def __init__(self, android_version="11") -> None:
super().__init__()
print("ok")
arch = self.arch[0]
if android_version not in self.dl_links:
raise KeyError(f"No download links for Android version '{android_version}'")
if arch not in self.dl_links[android_version]:
raise KeyError(f"No download links for architecture '{arch}' in Android version '{android_version}'")
self.dl_link = self.dl_links[android_version][arch][0]
self.act_md5 = self.dl_links[android_version][arch][1]
def copy(self):
name = re.findall(r"([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
extract_path = os.path.join(
self.extract_to, f"hack_full_data_permission-{name}")
if not container.use_overlayfs():
services_jar = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar")
services_jar_prof = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar.prof")
services_jar_bprof = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar.bprof")
backup(services_jar)
backup(services_jar_prof)
backup(services_jar_bprof)
Logger.info(f"Copying {self.id} library files ...")
shutil.copytree(extract_path, os.path.join(
self.copy_dir, self.partition), dirs_exist_ok=True)
def extra2(self):
if not container.use_overlayfs():
services_jar = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar")
services_jar_prof = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar.prof")
services_jar_bprof = os.path.join(
self.copy_dir, self.partition, "framework", "services.jar.bprof")
restore(services_jar)
restore(services_jar_prof)
restore(services_jar_bprof)
+67
View File
@@ -0,0 +1,67 @@
import os
import shutil
from stuff.general import General
class Smartdock(General):
id = "smartdock"
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_1100.apk"
partition = "system"
dl_file_name = "smartdock.apk"
act_md5 = "f4087d34218eac902a5cca98ee03d215"
apply_props = { "qemu.hw.mainkeys" : "1" }
skip_extract = True
permissions = """<?xml version="1.0" encoding="utf-8"?>
<permissions>
<privapp-permissions package="cu.axel.smartdock">
<permission name="android.permission.SYSTEM_ALERT_WINDOW" />
<permission name="android.permission.GET_TASKS"/>
<permission name="android.permission.REORDER_TASKS"/>
<permission name="android.permission.REMOVE_TASKS" />
<permission name="android.permission.ACCESS_WIFI_STATE"/>
<permission name="android.permission.CHANGE_WIFI_STATE"/>
<permission name="android.permission.ACCESS_NETWORK_STATE"/>
<permission name="android.permission.ACCESS_FINE_LOCATION"/>
<permission name="android.permission.READ_EXTERNAL_STORAGE"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.BLUETOOTH_ADMIN"/>
<permission name="android.permission.BLUETOOTH_CONNECT"/>
<permission name="android.permission.BLUETOOTH"/>
<permission name="android.permission.REQUEST_DELETE_PACKAGES"/>
<permission name="android.permission.ACCESS_SUPERUSER"/>
<permission name="android.permission.PACKAGE_USAGE_STATS" />
<permission name="android.permission.QUERY_ALL_PACKAGES" />
</privapp-permissions>
</permissions>
"""
files = [
"etc/permissions/permissions_cu.axel.smartdock.xml",
"priv-app/SmartDock",
"etc/init/smartdock.rc"
]
rc_content = '''
on property:sys.boot_completed=1
start set_home_activity
service set_home_activity /system/bin/sh -c "cmd package set-home-activity cu.axel.smartdock/.activities.LauncherActivity"
user root
group root
oneshot
'''
def copy(self):
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")):
os.makedirs(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock"))
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "etc", "permissions")):
os.makedirs(os.path.join(self.copy_dir, self.partition, "etc", "permissions"))
shutil.copyfile(os.path.join(self.download_loc),
os.path.join(self.copy_dir, self.partition, "priv-app/SmartDock/smartdock.apk"))
with open(os.path.join(self.copy_dir, self.partition, "etc", "permissions", "permissions_cu.axel.smartdock.xml"), "w") as f:
f.write(self.permissions)
rc_dir = os.path.join(self.copy_dir, self.partition, "etc/init/smartdock.rc")
if not os.path.exists(os.path.dirname(rc_dir)):
os.makedirs(os.path.dirname(rc_dir))
self.extract_app_lib(os.path.join(self.copy_dir, self.partition, "priv-app/SmartDock/smartdock.apk"))
with open(rc_dir, "w") as f:
f.write(self.rc_content)
+57
View File
@@ -0,0 +1,57 @@
import os
import re
import shutil
from stuff.general import General
from tools.logger import Logger
class Widevine(General):
id = "widevine"
partition = "vendor"
dl_links = {
# "x86": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/94c9ee172e3d78fecc81863f50a59e3646f7a2bd.zip", "a31f325453c5d239c21ecab8cfdbd878"],
"x86_64": {
"11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/48d1076a570837be6cdce8252d5d143363e37cc1.zip",
"f587b8859f9071da4bca6cea1b9bed6a"],
"13": ["https://github.com/WayDroid-ATV/vendor_google_proprietary_widevine-prebuilt/archive/679552343d8b2e8d7a19b6df61c7a03963d0c75b.zip",
"80ab79ea85c7b2556baedb371a54e01c"]
},
# "armeabi-v7a": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip", "fed6898b5cfd2a908cb134df97802554"],
"arm64-v8a": {
"11": ["https://github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a1a19361d36311bee042da8cf4ced798d2c76d98.zip",
"fed6898b5cfd2a908cb134df97802554"]
}
}
dl_file_name = "widevine.zip"
extract_to = "/tmp/widevineunpack"
files = [
"bin/hw/*widevine",
"bin/move_widevine_data.sh",
"etc/init/*widevine.rc",
"etc/vintf/manifest/*widevine.xml",
"lib/libwvhidl.so",
"lib/libwvaidl.so",
"lib/mediadrm",
"lib64/libwvhidl.so",
"lib64/libwvaidl.so",
"lib64/mediadrm"
]
def __init__(self, android_version) -> None:
super().__init__()
self.dl_link = self.dl_links[self.arch[0]][android_version][0]
self.act_md5 = self.dl_links[self.arch[0]][android_version][1]
self.android_version = android_version
self.libdir = "lib64" if self.arch[1] == 64 else "lib"
def copy(self):
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0]
Logger.info("Copying widevine library files ...")
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-"+name,
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
if self.android_version == "13":
try:
os.symlink("libprotobuf-cpp-lite-3.9.1.so",
os.path.join(self.copy_dir, self.partition, self.libdir, "libprotobuf-cpp-lite.so"))
except FileExistsError:
pass
+53
View File
@@ -0,0 +1,53 @@
import configparser
import os
import sys
# import dbus
from tools.helper import run
from tools.logger import Logger
# def DBusContainerService(object_path="/ContainerManager", intf="id.waydro.ContainerManager"):
# return dbus.Interface(dbus.SystemBus().get_object("id.waydro.Container", object_path), intf)
# def DBusSessionService(object_path="/SessionManager", intf="id.waydro.SessionManager"):
# return dbus.Interface(dbus.SessionBus().get_object("id.waydro.Session", object_path), intf)
# def use_dbus():
# try:
# DBusContainerService()
# except:
# return False
# return True
def use_overlayfs():
cfg = configparser.ConfigParser()
cfg_file = os.environ.get("WAYDROID_CONFIG", "/var/lib/waydroid/waydroid.cfg")
if not os.path.isfile(cfg_file):
Logger.error("Cannot locate waydroid config file, reinit wayland and try again!")
sys.exit(1)
cfg.read(cfg_file)
if "waydroid" not in cfg:
Logger.error("Required entry in config was not found, Cannot continue!")
if "mount_overlays" not in cfg["waydroid"]:
return False
if cfg["waydroid"]["mount_overlays"]=="True":
return True
return False
# def get_session():
# return DBusContainerService().GetSession()
def stop():
# if use_dbus():
# session = DBusContainerService().GetSession()
# if session:
# DBusContainerService().Stop(False)
# else:
run(["waydroid", "container", "stop"])
def is_running():
return "Session:\tRUNNING" in run(["waydroid", "status"]).stdout.decode()
def upgrade():
run(["waydroid", "upgrade", "-o"], ignore=r"\[.*\] Stopping container\n\[.*\] Starting container")
+146
View File
@@ -0,0 +1,146 @@
import gzip
import os
import re
import platform
import re
import subprocess
import sys
import requests
from tools.logger import Logger
from tqdm import tqdm
import hashlib
from typing import Optional
def get_download_dir():
download_loc = ""
if os.environ.get("XDG_CACHE_HOME", None) is None:
download_loc = os.path.join('/', "home", os.environ.get(
"SUDO_USER", os.environ["USER"]), ".cache", "waydroid-script", "downloads"
)
else:
download_loc = os.path.join(
os.environ["XDG_CACHE_HOME"], "waydroid-script", "downloads"
)
if not os.path.exists(download_loc):
os.makedirs(download_loc)
return download_loc
# not good
def get_data_dir():
return os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".local", "share", "waydroid", "data")
# execute on host
def run(args: list, env: Optional[str] = None, ignore: Optional[str] = None):
result = subprocess.run(
args=args,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# print(result.stdout.decode())
if result.returncode != 0 and result.stderr:
error = result.stderr.decode("utf-8")
if ignore and re.match(ignore, error):
return result
Logger.error(error)
raise subprocess.CalledProcessError(
returncode=result.returncode,
cmd=result.args,
stderr=result.stderr
)
return result
# execute on waydroid shell
def shell(arg: str, env: Optional[str] = None):
a = subprocess.Popen(
args=["sudo", "waydroid", "shell"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
subprocess.Popen(
args=["echo", "export BOOTCLASSPATH=/apex/com.android.art/javalib/core-oj.jar:/apex/com.android.art/javalib/core-libart.jar:/apex/com.android.art/javalib/core-icu4j.jar:/apex/com.android.art/javalib/okhttp.jar:/apex/com.android.art/javalib/bouncycastle.jar:/apex/com.android.art/javalib/apache-xml.jar:/system/framework/framework.jar:/system/framework/ext.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/framework-atb-backward-compatibility.jar:/apex/com.android.conscrypt/javalib/conscrypt.jar:/apex/com.android.media/javalib/updatable-media.jar:/apex/com.android.mediaprovider/javalib/framework-mediaprovider.jar:/apex/com.android.os.statsd/javalib/framework-statsd.jar:/apex/com.android.permission/javalib/framework-permission.jar:/apex/com.android.sdkext/javalib/framework-sdkextensions.jar:/apex/com.android.wifi/javalib/framework-wifi.jar:/apex/com.android.tethering/javalib/framework-tethering.jar"],
stdout=a.stdin,
stdin=subprocess.PIPE
).communicate()
if env:
subprocess.Popen(
args=["echo", env],
stdout=a.stdin,
stdin=subprocess.PIPE
).communicate()
subprocess.Popen(
args=["echo", arg],
stdout=a.stdin,
stdin=subprocess.PIPE
).communicate()
a.stdin.close()
if a.stderr.read():
Logger.error(a.stderr.read().decode('utf-8'))
raise subprocess.CalledProcessError(
returncode=a.returncode,
cmd=a.args,
stderr=a.stderr
)
return a.stdout.read().decode("utf-8")
def download_file(url, f_name):
md5 = ""
response = requests.get(url, stream=True)
total_size_in_bytes = int(response.headers.get('content-length', 0))
block_size = 1024 # 1 Kibibyte
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
with open(f_name, 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
with open(f_name, "rb") as f:
bytes = f.read()
md5 = hashlib.md5(bytes).hexdigest()
if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
raise ValueError("Something went wrong while downloading")
return md5
def host():
machine = platform.machine()
mapping = {
"i686": ("x86", 32),
"x86_64": ("x86_64", 64),
"aarch64": ("arm64-v8a", 64),
"armv7l": ("armeabi-v7a", 32),
"armv8l": ("armeabi-v7a", 32)
}
if machine in mapping:
if mapping[machine] == "x86_64":
with open("/proc/cpuinfo") as f:
if "sse4_2" not in f.read():
Logger.warning("x86_64 CPU does not support SSE4.2, falling back to x86...")
return ("x86", 32)
return mapping[machine]
raise ValueError("platform.machine '" + machine + "'"
" architecture is not supported")
def check_root():
if os.geteuid() != 0:
Logger.error("This script must be run as root. Aborting.")
sys.exit(1)
def backup(path):
gz_filename = path+".gz"
with gzip.open(gz_filename, 'wb') as f_gz:
with open(path, "rb") as f:
f_gz.write(f.read())
def restore(path):
gz_filename = path+".gz"
with gzip.GzipFile(gz_filename) as f_gz:
with open(path, "wb") as f:
f.writelines(f_gz)
+41
View File
@@ -0,0 +1,41 @@
import configparser
import os
import subprocess
import sys
from tools.helper import run
from tools.logger import Logger
def mount(image, mount_point):
umount(mount_point, False)
if not os.path.exists(mount_point):
os.makedirs(mount_point)
run(["mount", "-o", "rw", image, mount_point])
def umount(mount_point, exists=True):
if not os.path.exists(mount_point):
if not exists:
return
Logger.error("{} does not exist!".format(mount_point))
raise FileNotFoundError()
if not run(["mountpoint", mount_point]).returncode:
run(["umount", mount_point])
else:
Logger.warning("{} is not a mount point".format(
mount_point))
def resize(img_file, size):
run(["sudo", "e2fsck", "-y", "-f", img_file], ignore="^e2fsck \d+\.\d+\.\d (.+)\n$")
run(["sudo", "resize2fs", img_file, size], ignore="^resize2fs \d+\.\d+\.\d (.+)\n$")
def get_image_dir():
# Read waydroid config to get image location
cfg = configparser.ConfigParser()
cfg_file = os.environ.get("WAYDROID_CONFIG", "/var/lib/waydroid/waydroid.cfg")
if not os.path.isfile(cfg_file):
Logger.error("Cannot locate waydroid config file, reinit wayland and try again!")
sys.exit(1)
cfg.read(cfg_file)
if "waydroid" not in cfg:
Logger.error("Required entry in config was not found, Cannot continue!") #magisk
sys.exit(1)
return cfg["waydroid"]["images_path"]
+13
View File
@@ -0,0 +1,13 @@
class Logger:
@staticmethod
def error(str):
print("\033[31m"+"ERROR: "+str+"\033[0m")
@staticmethod
def info(str):
print("\033[32m"+"INFO: "+"\033[0m"+str)
@staticmethod
def warning(str):
print("\033[33m"+"WARN: "+str+"\033[0m")
-594
View File
@@ -1,594 +0,0 @@
import configparser
import sys
import os
import hashlib
import shutil
import zipfile
import subprocess
import argparse
import platform
from tqdm import tqdm
import requests
import re
download_loc = ""
if os.environ.get("XDG_CACHE_HOME", None) is None:
download_loc = os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".cache", "waydroid_script", "downloads")
else:
os.path.join(os.environ["XDG_CACHE_HOME"], "waydroid_script", "downloads")
print(download_loc)
if not os.path.exists(download_loc):
os.makedirs(download_loc)
def stop_waydroid():
print("==> Stopping waydroid and unmounting already mounted images...")
os.system("waydroid container stop &> /dev/null")
os.system("umount /var/lib/waydroid/rootfs/vendor/waydroid.prop &> /dev/null")
os.system("umount /var/lib/waydroid/rootfs/vendor &> /dev/null")
os.system("umount /var/lib/waydroid/rootfs &> /dev/null")
def download_file(url, f_name):
md5 = ""
response = requests.get(url, stream=True)
total_size_in_bytes = int(response.headers.get('content-length', 0))
block_size = 1024 # 1 Kibibyte
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
with open(f_name, 'wb') as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
with open(f_name, "rb") as f:
bytes = f.read()
md5 = hashlib.md5(bytes).hexdigest()
if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
print("==> Something went wrong while downloading")
sys.exit(1)
return md5
def get_image_dir():
# Read waydroid config to get image location
cfg = configparser.ConfigParser()
cfg_file = os.environ.get("WAYDROID_CONFIG", "/var/lib/waydroid/waydroid.cfg")
if not os.path.isfile(cfg_file):
print("==> Cannot locate waydroid config file, reinit wayland and try again !")
sys.exit(1)
cfg.read(cfg_file)
if "waydroid" not in cfg:
print("==> Required entry in config was not found, Cannot continue !s")
sys.exit(1)
return cfg["waydroid"]["images_path"]
def mount_image(image, mount_point):
print("==> Unmounting .. ")
try:
subprocess.check_output(["losetup", "-D"], stderr=subprocess.STDOUT)
subprocess.check_output(["umount", mount_point], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Warning: umount failed.. {} ".format(str(e.output.decode())))
if not os.path.exists(mount_point):
os.makedirs(mount_point)
try:
subprocess.check_output(["mount", "-o", "rw", image, mount_point], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Failed to mount system image... ! {}".format(str(e.output.decode())))
sys.exit(1)
def resize_img(img_file, size):
# Resize the system image
print("==> Resizing system image....")
try:
subprocess.check_output(["e2fsck -y -f "+img_file], stderr=subprocess.STDOUT, shell=True)
subprocess.check_output(["resize2fs '{}' {}".format(img_file, size)], stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
print("==> Failed to resize image '{}' .. ! {}".format(img_file, str(e.output.decode())))
p = input("==> You can exit and retry with sudo or force continue (May fail installation !), Continue ? [y/N]: ")
if not p.lower() == "y":
sys.exit(1)
def install_gapps():
dl_links = {
"x86_64": ["https://master.dl.sourceforge.net/project/opengapps/x86_64/20220121/open_gapps-x86_64-10.0-pico-20220121.zip?viasf=1", "e8c9a7412f5712eea7948957a62a7d66"],
"x86": ["https://udomain.dl.sourceforge.net/project/opengapps/x86/20220122/open_gapps-x86-10.0-pico-20220122.zip", "9e39e45584b7ade4529e6be654af7b81"],
"aarch64": ["https://liquidtelecom.dl.sourceforge.net/project/opengapps/arm64/20220122/open_gapps-arm64-10.0-pico-20220122.zip", "8dfa6e76aeb2d1d5aed40b058e8a852c"],
"arm": ["https://nav.dl.sourceforge.net/project/opengapps/arm/20220122/open_gapps-arm-10.0-pico-20220122.zip", "a48ccbd25eb0a3c5e30f5db5435f5536"]
}
if platform.machine() not in dl_links.keys():
print("==> Unsupported architecture '{}' .. ".format(platform.machine()))
sys.exit(1)
google_apps_dl_link = dl_links[platform.machine()][0]
dl_file_name = os.path.join(download_loc, "open_gapps.zip")
act_md5 = dl_links[platform.machine()][1]
loc_md5 = ""
sys_image_mount = "/tmp/waydroidimage"
extract_to = "/tmp/ogapps/extract"
non_apks = [
"defaultetc-common.tar.lz",
"defaultframework-common.tar.lz",
"googlepixelconfig-common.tar.lz"
]
skip = [
"setupwizarddefault-x86_64.tar.lz",
"setupwizardtablet-x86_64.tar.lz"
]
if not os.path.exists(extract_to):
os.makedirs(extract_to)
if not os.path.exists(os.path.join(extract_to, "appunpack")):
os.makedirs(os.path.join(extract_to, "appunpack"))
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
print("==> Excepted hash: {} | File hash: {}".format(act_md5, loc_md5))
system_img = os.path.join(get_image_dir(), "system.img")
if not os.path.isfile(system_img):
print("The system image path '{}' from waydroid config is not valid !".format(system_img))
sys.exit(1)
print("==> Found system image: "+system_img)
img_size = int(os.path.getsize(system_img)/(1024*1024))
# Resize image to get some free space
resize_img(system_img, "{}M".format(img_size+500))
# Mount the system image
mount_image(system_img, sys_image_mount)
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> OpenGapps zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(google_apps_dl_link, dl_file_name)
# Extract opengapps
print("==> Extracting opengapps...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
# Now copy the files
for lz_file in os.listdir(os.path.join(extract_to, "Core")):
for d in os.listdir(os.path.join(extract_to, "appunpack")):
shutil.rmtree(os.path.join(extract_to, "appunpack", d))
if lz_file not in skip:
if lz_file not in non_apks:
print("==> Processing app package : "+os.path.join(extract_to, "Core", lz_file))
os.system("tar --lzip -xvf '{}' -C '{}'>/dev/null".format(os.path.join(extract_to, "Core", lz_file), os.path.join(extract_to, "appunpack")))
app_name = os.listdir(os.path.join(extract_to, "appunpack"))[0]
xx_dpi = os.listdir(os.path.join(extract_to, "appunpack", app_name))[0]
app_priv = os.listdir(os.path.join(extract_to, "appunpack", app_name, "nodpi"))[0]
app_src_dir = os.path.join(extract_to, "appunpack", app_name, xx_dpi, app_priv)
for app in os.listdir(app_src_dir):
shutil.copytree(os.path.join(app_src_dir, app), os.path.join(sys_image_mount, "system", "priv-app", app), dirs_exist_ok=True)
else:
print("==> Processing extra package : "+os.path.join(extract_to, "Core", lz_file))
os.system("tar --lzip -xvf '{}' -C '{}'>/dev/null".format(os.path.join(extract_to, "Core", lz_file), os.path.join(extract_to, "appunpack")))
app_name = os.listdir(os.path.join(extract_to, "appunpack"))[0]
common_content_dirs = os.listdir(os.path.join(extract_to, "appunpack", app_name, "common"))
for ccdir in common_content_dirs:
shutil.copytree(os.path.join(extract_to, "appunpack", app_name, "common", ccdir), os.path.join(sys_image_mount, "system", ccdir), dirs_exist_ok=True)
print("==> Unmounting .. ")
try:
subprocess.check_output(["umount", sys_image_mount], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Warning: umount failed.. {} ".format(str(e.output.decode())))
print("==> OpenGapps installation complete try re init /restarting waydroid")
print("==> Please note, google apps wont be usable without device registration !, Use --get-android-id for registration instructions")
def get_android_id():
try:
if not os.path.isfile("/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db"):
print("Cannot access gservices.db, make sure gapps is installed and waydroid was started at least once after installation and make sure waydroid is running !")
sys.exit(1)
sqs = """
SELECT * FROM main WHERE name='android_id'
"""
queryout = subprocess.check_output(["sqlite3", "/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db", sqs.strip()], stderr=subprocess.STDOUT)
print(queryout.decode().replace("android_id|", "").strip())
print(" ^----- Open https://google.com/android/uncertified/?pli=1")
print(" Login with your google id then submit the form with id shown above")
except subprocess.CalledProcessError as e:
print("==> Error getting id... '{}' ".format(str(e.output.decode())))
def install_ndk():
sys_image_mount = "/tmp/waydroidimage"
ndk_zip_url = "https://github.com/newbit1/libndk_translation_Module/archive/c6077f3398172c64f55aad7aab0e55fad9110cf3.zip"
dl_file_name = os.path.join(download_loc, "libndktranslation.zip")
extract_to = "/tmp/libndkunpack" #All catalog files will be marked as executable!
act_md5 = "5e8e0cbde0e672fdc2b47f20a87472fd"
loc_md5 = ""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,armeabi-v7a,armeabi", #arm64-v8a,
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64", #,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libndk_translation.so",
"ro.enable.native.bridge.exec": "1",
"ro.ndk_translation.version": "0.2.2",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
init_rc_component = """
on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm_exe > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm_dyn >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm64_exe >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "cat /system/etc/binfmt_misc/arm64_dyn >> /proc/sys/fs/binfmt_misc/register"
"""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
system_img = os.path.join(get_image_dir(), "system.img")
if not os.path.isfile(system_img):
print("The system image path '{}' from waydroid config is not valid !".format(system_img))
sys.exit(1)
print("==> Found system image: "+system_img)
# Resize rootfs
img_size = int(os.path.getsize(system_img)/(1024*1024))
# Resize image to get some free space
resize_img(system_img, "{}M".format(img_size+50))
# Mount the system image
mount_image(system_img, sys_image_mount)
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> NDK Translation zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(ndk_zip_url, dl_file_name)
# Extract ndk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
#Mark ndk files as executable
print("==> Chmodding...")
try: os.system("chmod +x "+extract_to+" -R")
except: print("==> Couldn't mark files as executable!")
# Copy library file
print("==> Copying library files ...")
shutil.copytree(os.path.join(extract_to, "libndk_translation_Module-c6077f3398172c64f55aad7aab0e55fad9110cf3", "system"), os.path.join(sys_image_mount, "system"), dirs_exist_ok=True)
# Add entries to build.prop
print("==> Adding arch in build.prop")
with open(os.path.join(sys_image_mount, "system", "build.prop"), "r") as propfile:
prop_content = propfile.read()
for key in apply_props:
if key not in prop_content:
prop_content = prop_content+"\n{key}={value}".format(key=key, value=apply_props[key])
else:
p = re.compile(r"^{key}=.*$".format(key=key), re.M)
prop_content = re.sub(p, "{key}={value}".format(key=key, value=apply_props[key]), prop_content)
with open(os.path.join(sys_image_mount, "system", "build.prop"), "w") as propfile:
propfile.write(prop_content)
# Add entry to init.rc
print("==> Adding entry to init.rc")
# Check if init.rc is located in Android 11's path
init_path = os.path.join(sys_image_mount, "system", "etc", "init", "hw", "init.rc")
if not os.path.isfile(init_path):
# init.rc not found, assuming it's located in the root folder (Android 10 and older)
init_path = os.path.join(sys_image_mount, "init.rc")
with open(init_path, "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(init_path, "w") as initfile:
initfile.write(initcontent)
# Unmount and exit
print("==> Unmounting .. ")
try:
subprocess.check_output(["umount", sys_image_mount], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Warning: umount failed.. {} ".format(str(e.output.decode())))
print("==> libndk translation installed ! Restart waydroid service to apply changes !")
def install_houdini():
sys_image_mount = "/tmp/waydroidimage"
houdini_zip_url = "https://raw.githubusercontent.com/casualsnek/miscpackages/main/libhoudini_a11.zip"
dl_file_name = os.path.join(download_loc, "libhoudini.zip")
extract_to = "/tmp/houdiniunpack" #All catalog files will be marked as executable!
act_md5 = "c9a80831641de8fd44ccf93a0ad8b585"
loc_md5 = ""
apply_props = {
"ro.product.cpu.abilist": "x86_64,x86,arm64-v8a,armeabi-v7a,armeabi",
"ro.product.cpu.abilist32": "x86,armeabi-v7a,armeabi",
"ro.product.cpu.abilist64": "x86_64,arm64-v8a",
"ro.dalvik.vm.native.bridge": "libhoudini.so",
"ro.enable.native.bridge.exec": "1",
"ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64"
}
init_rc_component = """
on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
exec -- /system/bin/sh -c "echo ':arm_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x28::/system/bin/houdini:P' > /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x01\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x28::/system/bin/houdini:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_exe:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
exec -- /system/bin/sh -c "echo ':arm64_dyn:M::\\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\xb7::/system/bin/houdini64:P' >> /proc/sys/fs/binfmt_misc/register"
"""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
system_img = os.path.join(get_image_dir(), "system.img")
if not os.path.isfile(system_img):
print("The system image path '{}' from waydroid config is not valid !".format(system_img))
sys.exit(1)
print("==> Found system image: "+system_img)
img_size = int(os.path.getsize(system_img)/(1024*1024))
# Resize image to get some free space
resize_img(system_img, "{}M".format(img_size+300))
# Mount the system image
mount_image(system_img, sys_image_mount)
# Download the file if hash mismatches or if file does not exist
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> libhoudini zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(houdini_zip_url, dl_file_name)
# Extract ndk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
# Mark libhoudini files as executable
print("==> Chmodding...")
try: os.system("chmod +x "+extract_to+" -R")
except: print("==> Couldn't mark files as executable!")
# Copy library file
print("==> Copying library files ...")
shutil.copytree(os.path.join(extract_to, "system"), os.path.join(sys_image_mount, "system"), dirs_exist_ok=True)
# Add entries to build.prop
print("==> Adding arch in build.prop")
with open(os.path.join(sys_image_mount, "system", "build.prop"), "r") as propfile:
prop_content = propfile.read()
for key in apply_props:
if key not in prop_content:
prop_content = prop_content+"\n{key}={value}".format(key=key, value=apply_props[key])
else:
p = re.compile(r"^{key}=.*$".format(key=key), re.M)
prop_content = re.sub(p, "{key}={value}".format(key=key, value=apply_props[key]), prop_content)
with open(os.path.join(sys_image_mount, "system", "build.prop"), "w") as propfile:
propfile.write(prop_content)
# Add entry to init.rc
print("==> Adding entry to init.rc")
# Check if init.rc is located in Android 11's path
init_path = os.path.join(sys_image_mount, "system", "etc", "init", "hw", "init.rc")
if not os.path.isfile(init_path):
# init.rc not found, assuming it's located in the root folder (Android 10 and older)
init_path = os.path.join(sys_image_mount, "init.rc")
with open(init_path, "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(init_path, "w") as initfile:
initfile.write(initcontent)
# Unmount and exit
print("==> Unmounting .. ")
try:
subprocess.check_output(["umount", sys_image_mount], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Warning: umount failed.. {} ".format(str(e.output.decode())))
print("==> libhoudini translation installed ! Restart waydroid service to apply changes !")
def install_magisk():
dl_link = "https://github.com/topjohnwu/Magisk/releases/download/v20.4/Magisk-v20.4.zip"
busybox_dl_link = "https://github.com/Gnurou/busybox-android/raw/master/busybox-android"
busybox_dl_file_name = os.path.join(download_loc, "busybox-android")
dl_file_name = os.path.join(download_loc, "magisk.zip")
extract_to = "/tmp/magisk_unpack"
act_md5 = "9503fc692e03d60cb8897ff2753c193f"
busybox_act_md5 = "2e43cc2e8f44b83f9029a6561ce5d8b9"
sys_image_mount = "/tmp/waydroidimage"
loc_md5 = ""
busybox_loc_md5 = ""
magisk_init = """#!/system/bin/sh
mount -o remount,rw /
rm /sbin/magisk /sbin/magiskpolicy /sbin/magiskinit
cp /magiskinit /sbin/magiskinit
ln -s /sbin/magiskinit /sbin/magisk
ln -s /sbin/magiskinit /sbin/magiskpolicy
mkdir -p /data/adb/magisk
cp /busybox /data/adb/magisk/busybox
cp /util_functions.sh /data/adb/magisk/util_functions.sh
cp /boot_patch.sh /data/adb/magisk/boot_patch.sh
cp /addon.d.sh /data/adb/magisk/addon.d.sh
magisk -c >&2
ln -sf /data /sbin/.magisk/mirror/data
ln -sf /vendor /sbin/.magisk/mirror/vendor
magisk --post-fs-data
sleep 1
magisk --service
magisk --boot-complete
mount -o remount,ro /
"""
init_rc_component = """on property:dev.bootcomplete=1
start magisk
service magisk /system/bin/init-magisk.sh
class main
user root
group root
oneshot
"""
if os.path.isfile(dl_file_name):
with open(dl_file_name,"rb") as f:
bytes = f.read()
loc_md5 = hashlib.md5(bytes).hexdigest()
if os.path.isfile(busybox_dl_file_name):
with open(busybox_dl_file_name,"rb") as f:
bytes = f.read()
busybox_loc_md5 = hashlib.md5(bytes).hexdigest()
system_img = os.path.join(get_image_dir(), "system.img")
if not os.path.isfile(system_img):
print("The system image path '{}' from waydroid config is not valid !".format(system_img))
sys.exit(1)
print("==> Found system image: " + system_img)
img_size = int(os.path.getsize(system_img)/(1024*1024))
# Resize image to get some free space
resize_img(system_img, "{}M".format(img_size+50))
# Mount the system image
mount_image(system_img, sys_image_mount)
# Download magisk
while not os.path.isfile(dl_file_name) or loc_md5 != act_md5:
if os.path.isfile(dl_file_name):
os.remove(dl_file_name)
print("==> Magisk zip not downloaded or hash mismatches, downloading now .....")
loc_md5 = download_file(dl_link, dl_file_name)
# Download busybox android binary
while not os.path.isfile(busybox_dl_file_name) or busybox_loc_md5 != busybox_act_md5:
if os.path.isfile(busybox_dl_file_name):
os.remove(busybox_dl_file_name)
print("==> BusyBox binary not downloaded or hash mismatches, downloading now .....")
busybox_loc_md5 = download_file(busybox_dl_link, busybox_dl_file_name)
# Extract magisk files
print("==> Extracting archive...")
with zipfile.ZipFile(dl_file_name) as z:
z.extractall(extract_to)
# Now setup and install magisk binary and app
print("==> Installing magisk now ...")
with open(os.path.join(sys_image_mount, "system", "bin", "init-magisk.sh"), "w") as imf:
imf.write(magisk_init)
os.system("chmod 755 {}".format(os.path.join(sys_image_mount, "system", "bin", "init-magisk.sh")))
arch_dir = "x86" if "x86" in platform.machine() else "arm"
arch = "64" if "64" in platform.machine() else ""
shutil.copyfile(os.path.join(extract_to, arch_dir, "magiskinit{arch}".format(arch=arch)),
os.path.join(sys_image_mount, "sbin", "magiskinit"))
shutil.copyfile(os.path.join(extract_to, arch_dir, "magiskinit{arch}".format(arch=arch)),
os.path.join(sys_image_mount, "magiskinit"))
os.system("chmod 755 {} & chmod 755 {}".format(os.path.join(sys_image_mount, "sbin", "magiskinit"), os.path.join(sys_image_mount, "magiskinit")))
# Copy busybox
print("==> Installing BusyBox")
shutil.copyfile(busybox_dl_file_name, os.path.join(sys_image_mount, "busybox"))
os.system("chmod 755 {}".format(os.path.join(sys_image_mount, "busybox")))
# Copy files from common directory
for file in ["util_functions.sh", "boot_patch.sh", "addon.d.sh"]:
shutil.copyfile(os.path.join(extract_to, "common", file),
os.path.join(sys_image_mount, file))
os.system("chmod 755 {}".format(os.path.join(sys_image_mount, file)))
# Create symlinks
print("==> Creating symlinks")
os.system("cd {root}/sbin && ln -sf magiskinit magiskinit >> /dev/null 2>&1".format(root=sys_image_mount))
os.system("cd {root}/sbin && ln -sf magiskinit magisk >> /dev/null 2>&1".format(root=sys_image_mount))
print("==> magiskinit -> magisk")
os.system("cd {root}/sbin && ln -sf /magiskinit magiskpolicy >> /dev/null 2>&1".format(root=sys_image_mount))
print("==> magiskinit -> magiskpolicy")
# Add entry to init.rc
print("==> Adding entry to init.rc")
with open(os.path.join(sys_image_mount, "init.rc"), "r") as initfile:
initcontent = initfile.read()
if init_rc_component not in initcontent:
initcontent=initcontent+init_rc_component
with open(os.path.join(sys_image_mount, "init.rc"), "w") as initfile:
initfile.write(initcontent)
# Install Magisk apk
if not os.path.exists(os.path.join(sys_image_mount, "system", "priv-app", "Magisk")):
os.makedirs(os.path.join(sys_image_mount, "system", "priv-app", "Magisk"))
shutil.copyfile(os.path.join(extract_to, "common", "magisk.apk"),
os.path.join(sys_image_mount, "system", "priv-app", "Magisk", "magisk.apk"))
# Unmount and exit
print("==> Unmounting .. ")
try:
subprocess.check_output(["umount", sys_image_mount], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print("==> Warning: umount failed.. {} ".format(str(e.output.decode())))
print("==> Magisk was installed ! Restart waydroid service to apply changes !")
def main():
about = """
WayDroid Helper script v0.3
Does stuff like installing Gapps, Installing NDK Translation and getting Android ID for device registration.
Use -h flag for help !
"""
parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-g', '--install-gapps',
dest='install',
help='Install OpenGapps to waydroid',
action='store_true')
parser.add_argument('-n', '--install-ndk-translation',
dest='installndk',
help='Install experimental libndk translation files',
action='store_true')
parser.add_argument('-i', '--get-android-id', dest='getid',
help='Displays your android id for manual registration',
action='store_true')
parser.add_argument('-m', '--install-magisk', dest='magisk',
help='Attempts to install Magisk ( Bootless )',
action='store_true')
parser.add_argument('-l', '--install-libhoudini', dest='houdini',
help='Install libhoudini for arm translation',
action='store_true')
args = parser.parse_args()
if args.install:
stop_waydroid()
install_gapps()
elif args.installndk:
stop_waydroid()
install_ndk()
elif args.getid:
get_android_id()
elif args.magisk:
install_magisk()
elif args.houdini:
install_houdini()
if __name__ == "__main__":
main()