Compare commits

...
107 Commits
Author SHA1 Message Date
wbruno b20483dd9a Merge pull request 'Update SmartDock to new version' (#218) from rduttshukla/feat/smartdock-update-and-permission-fix into main
Reviewed-on: #218
2026-10-12 14:01:14 -04:00
wbruno 8020dbd8fc Merge pull request 'Fix forgotten commas in microg.py' (#270) from MarSoft/patch-1 into main
Reviewed-on: #270
2026-10-12 14:00:52 -04:00
wbruno b7e1c37e14 Merge pull request 'Fix /data/adb/magisk permissions so Zygisk can initialise' (#284) from MisterWizzard/fix/magisk-data-adb-permissions into main
Reviewed-on: #284
2026-10-12 14:00:19 -04:00
wbruno 2f6547f873 Merge pull request 'feat: add device spoof to fix Play Store device compatibility' (#275) from EsymDnB/main into main
Reviewed-on: #275
2026-10-12 13:59:31 -04:00
Suggon 48dbfaf34a Update houdini library with extended expiry date (July 1, 2028)
Intel's libhoudini library includes a built-in "expiry date" that
prevents execution after a certain date. The previous versions expired
on January 1, 2026 (#256) and September 1, 2026 respectively.

This update refreshes the library to a newer build per
https://github.com/supremegamers/vendor_intel_proprietary_houdini/issues/6
and has an extended expiry date of July 1, 2028.
2026-09-11 14:56:36 +02:00
MisterWizzardandClaude Opus 5 b09e018894 Fix /data/adb/magisk permissions so Zygisk can initialise
General.install() runs copy() -> extra1() -> set_perm(). set_perm() only walks
self.files, which are paths under copy_dir (the overlay), so the copy that
Magisk.setup() makes into <data_dir>/adb/magisk keeps the 0644 the binaries
inherit from the apk extraction.

A non-executable /data/adb/magisk/magisk64 makes magisk_env() abort at
post-fs-data. Root still works, because that runs from the overlay copy, but
Zygisk never initialises: the Magisk app reports "Zygisk: No" no matter what the
zygisk setting says, and no error is surfaced to explain why. This breaks every
Zygisk module (LSPosed, Shamiko, PlayIntegrityFix, ...).

Fix setup() to apply the same 0755 to its own destination that
Magisk.set_path_perm() already applies to magisk paths.

Adds a regression test that passes with the fix and fails without it. It needs no
Waydroid install, no root and no extra dependencies:

    python3 tests/test_magisk_setup_perms.py

Fixes #283

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 09:49:05 +10:00
mcheesemanandClaude Sonnet 4.6 3bc2b310a3 feat: add device spoof to fix Play Store device compatibility
Adds a device_spoof module that writes Android device identity
properties into waydroid.cfg, enabling games like Destiny Rising
that reject Waydroid's generic device profile. Includes Pixel 6
and Samsung Galaxy S21 profiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:03:41 +08:00
Семён Марьясин 963e3511fe Fix forgotten commas in microg.py
Choosing Minimal variants resulted in this without my fix:

  File "/nix/store/2a3cl1fvl0418qmkrvndx4si29w9yvv5-waydroid-script-0-unstable-2026-01-05/lib/python3.13/site-packages/stuff/microg.py", line 109, in __init__
    self.act_md5 = self.dl_links[variant][1]
                   ~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: list index out of range
2026-04-14 19:04:01 +03: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
Rishi 2d3bd9432f Update SmartDock to new version and add WRITE_SECURE_SETTINGS to fix bootloop 2025-03-22 17:09:09 +05:30
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
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
48 changed files with 2144 additions and 513 deletions
+5
View File
@@ -25,6 +25,7 @@ wheels/
.installed.cfg .installed.cfg
*.egg *.egg
MANIFEST MANIFEST
.vscode
# PyInstaller # PyInstaller
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template
@@ -104,3 +105,7 @@ venv.bak/
# mypy # mypy
.mypy_cache/ .mypy_cache/
# nix
result*
test.py
+143 -39
View File
@@ -1,51 +1,89 @@
# Waydroid Extras Script # 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 # 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:
## Interactive terminal interface
```
git clone https://github.com/casualsnek/waydroid_script git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script cd waydroid_script
sudo python3 -m pip install -r requirements.txt python3 -m venv venv
sudo python3 main.py [-i/-g/-n/-h/-w] 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 ## Install OpenGapps
Open terminal and switch to directory where "main.py" is located then run: ![](assets/1.png)
sudo python3 main.py -g Open terminal and switch to the directory where "main.py" is located then run:
sudo venv/bin/python3 main.py install gapps
Then launch waydroid with: Then launch waydroid with:
waydroid show-full-ui waydroid show-full-ui
After waydroid has finished booting open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py -i After waydroid has finished booting, open terminal and switch to directory where "main.py" is located then run:
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 !
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 ## Install Magisk
![](assets/2.png)
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py -m sudo venv/bin/python3 main.py install magisk
Magisk will be installed on next boot! Magisk will be installed on next boot!
Zygisk and modules like LSPosed should work now. Zygisk and modules like LSPosed should work now.
Please use `Direct Install into system partition` to update Magisk in Magisk manager. 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 ## Install libndk arm translation
@@ -55,7 +93,7 @@ libndk seems to have better performance than libhoudini on AMD.
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py -n sudo venv/bin/python3 main.py install libndk
## Install libhoudini arm translation ## Install libhoudini arm translation
@@ -67,35 +105,101 @@ houdini64 version: 11.0.1b_z.38765.m
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py -l sudo venv/bin/python3 main.py install libhoudini
## Integrate Widevine DRM (L3) ## Integrate Widevine DRM (L3)
![](assets/3.png)
Open terminal and switch to directory where "main.py" is located then run: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.py -w 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
```
## Get Android ID for device registration ## 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: 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: Open terminal and switch to directory where "main.py" is located then run:
sudo python3 main.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 ## Error handling
In case of error, if you retry immediately and it fails with this error - Magisk installed: N/A
```
==> Failed to resize image '/var/lib/waydroid/images/system.img' .. ! e2fsck 1.45.5 (07-Jan-2020) Check [waydroid-magisk](https://github.com/nitanmarcel/waydroid-magisk)
/var/lib/waydroid/images/system.img is mounted.
e2fsck: Cannot continue, aborting. ## Credits
``` - [WayDroid](https://github.com/waydroid/waydroid)
You need to get the mounting point using `df | grep waydroid`. It will be something like `/dev/loopXXX`. Then, unmount it - [Magisk Delta](https://huskydg.github.io/magisk-files/)
``` - [microG Project](https://microg.org)
sudo umount /dev/loopXXX - [Open GApps](https://opengapps.org)
``` - [Smart Dock](https://github.com/axel358/smartdock)
And re-run the script. - [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;
});
};
}
Regular → Executable
+363 -52
View File
@@ -1,63 +1,374 @@
#!/usr/bin/env python3
from InquirerPy import inquirer
from InquirerPy.base.control import Choice
from InquirerPy.separator import Separator
import argparse import argparse
from logging import Logger import os
from stuffs.android_id import Android_id from typing import List
from stuffs.gapps import Gapps from stuff.android_id import AndroidId
from stuffs.houdini import Houdini from stuff.gapps import Gapps
from stuffs.magisk import Magisk from stuff.general import General
from stuffs.ndk import Ndk from stuff.hidestatusbar import HideStatusBar
from stuffs.widevine import Widevine 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
from stuff.device_spoof import DeviceSpoof, PROFILES
import tools.helper as helper 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 "device_spoof" in app:
DeviceSpoof(getattr(args, "spoof_profile", "pixel6")).install()
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 "device_spoof" in app:
DeviceSpoof().uninstall()
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", "device_spoof"]
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
if "device_spoof" in apps:
spoof_profile = inquirer.select(
message="Select device profile to spoof",
choices=list(PROFILES.keys()),
default="pixel6",
).execute()
args.spoof_profile = spoof_profile
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(): def main():
about = """ parser = argparse.ArgumentParser(description='''
WayDroid Helper script v0.3 Does stuff like installing Gapps, installing Magisk, installing NDK Translation and getting Android ID for device registration.
Does stuff like installing Gapps, Installing NDK Translation and getting Android ID for device registration. Use -h flag for help!''')
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", "device_spoof"]
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
""" """
helper.check_root() # install and its aliases
parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawDescriptionHelpFormatter) install_parser = subparsers.add_parser(
parser.add_argument('-g', '--install-gapps', 'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
dest='gapps', install_parser.add_argument(
help='Install OpenGapps to waydroid', **arg_template, choices=install_choices, help=install_help)
action='store_true') install_parser.add_argument('-c', '--ca-cert',
parser.add_argument('-n', '--install-ndk-translation', dest='ca_cert_file',
dest='ndk', help='[for mitm only] The CA certificate file (*.pem) to install',
help='Install libndk translation for arm translation', default=None)
action='store_true') install_parser.add_argument('-p', '--spoof-profile',
parser.add_argument('-i', '--get-android-id', dest='getid', dest='spoof_profile',
help='Displays your android id for manual registration', help='[for device_spoof only] Device profile to spoof',
action='store_true') choices=list(PROFILES.keys()),
parser.add_argument('-m', '--install-magisk', dest='magisk', default="pixel6")
help='Attempts to install Magisk ( Bootless )', install_parser.set_defaults(func=install_app)
action='store_true')
parser.add_argument('-l', '--install-libhoudini', dest='houdini', # remove and its aliases
help='Install libhoudini for arm translation', remove_parser = subparsers.add_parser(
action='store_true') 'remove', aliases=["uninstall"], help='Remove an app')
parser.add_argument('-w', '--install-windevine', dest='widevine', remove_parser.add_argument(
help='Integrate Widevine DRM (L3)', **arg_template, choices=[*remove_choices, * hack_choices], help='Name of app to remove')
action='store_true') 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 = parser.parse_args()
if args.getid: args.microg_variant = "Standard"
Android_id().get_id() if hasattr(args, 'func'):
if args.gapps: args_dict = vars(args)
Gapps().install() helper.check_root()
if args.ndk and not args.houdini: args.func(args)
arch = helper.host()[0]
if arch == "x86_64":
Ndk().install()
else: else:
Logger.warn("libndk is not supported on your CPU") helper.check_root()
if args.houdini and not args.ndk: interact()
arch = helper.host()[0]
if arch == "x86_64":
Houdini().install()
else:
Logger.warn("libhoudini is not supported on your CPU")
if args.magisk:
Magisk().install()
if args.widevine:
Widevine().install()
if __name__ == "__main__": if __name__ == "__main__":
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 tqdm
requests 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")
+71
View File
@@ -0,0 +1,71 @@
import configparser
from tools.logger import Logger
PROFILES = {
"pixel6": {
"ro.product.brand": "google",
"ro.product.manufacturer": "Google",
"ro.product.model": "Pixel 6",
"ro.product.name": "oriole",
"ro.product.device": "oriole",
"ro.product.board": "oriole",
"ro.build.product": "oriole",
"ro.build.fingerprint": "google/oriole/oriole:13/TQ3A.230901.001/10750268:user/release-keys",
"ro.build.description": "oriole-user 13 TQ3A.230901.001 10750268 release-keys",
"ro.build.version.release": "13",
"ro.build.version.sdk": "33",
"ro.build.type": "user",
"ro.build.tags": "release-keys",
},
"samsung_s21": {
"ro.product.brand": "samsung",
"ro.product.manufacturer": "samsung",
"ro.product.model": "SM-G991B",
"ro.product.name": "o1sxeea",
"ro.product.device": "o1s",
"ro.product.board": "lahaina",
"ro.build.product": "o1s",
"ro.build.fingerprint": "samsung/o1sxeea/o1s:13/TP1A.220624.014/G991BXXU5EWCA:user/release-keys",
"ro.build.description": "o1sxeea-user 13 TP1A.220624.014 G991BXXU5EWCA release-keys",
"ro.build.version.release": "13",
"ro.build.version.sdk": "33",
"ro.build.type": "user",
"ro.build.tags": "release-keys",
},
}
PROP_KEYS = list(next(iter(PROFILES.values())).keys())
class DeviceSpoof:
id = "device_spoof"
def __init__(self, profile_name="pixel6") -> None:
if profile_name not in PROFILES:
raise ValueError(f"Unknown profile '{profile_name}'. Choose from: {list(PROFILES.keys())}")
self.profile_name = profile_name
self.apply_props = PROFILES[profile_name]
def _read_cfg(self):
cfg = configparser.ConfigParser()
cfg.read("/var/lib/waydroid/waydroid.cfg")
if not cfg.has_section("properties"):
cfg.add_section("properties")
return cfg
def install(self):
cfg = self._read_cfg()
for key, value in self.apply_props.items():
cfg.set("properties", key, value)
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
Logger.info(f"Device spoofed as '{self.profile_name}'. Restart Waydroid to apply.")
def uninstall(self):
cfg = self._read_cfg()
for key in PROP_KEYS:
cfg.remove_option("properties", key)
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
Logger.info("Device spoof properties removed. Restart Waydroid to apply.")
+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
+27 -10
View File
@@ -1,20 +1,24 @@
import os import os
import re import re
import shutil import shutil
from stuffs.general import General from stuff.general import General
from tools.helper import run
from tools.logger import Logger from tools.logger import Logger
class Houdini(General): class Houdini(General):
id = "libhoudini"
partition = "system" partition = "system"
dl_link = "https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip" dl_links = {
act_md5 = "fbff756612b4144797fbc99eadcb6653" "11": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/81f2a51ef539a35aead396ab7fce2adf89f46e88.zip", "fbff756612b4144797fbc99eadcb6653"],
"13": ["https://github.com/supremegamers/vendor_intel_proprietary_houdini/archive/2f8f088671182e17e67321e098e8411a3972a628.zip", "37fe0899f1e4da7f9a724cca1c1ab1ea"]
}
act_md5 = ...
dl_link = ...
dl_file_name = "libhoudini.zip" dl_file_name = "libhoudini.zip"
extract_to = "/tmp/houdiniunpack" extract_to = "/tmp/houdiniunpack"
init_rc_component = """ init_rc_component = """
on early-init on early-init
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1 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_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"
@@ -31,18 +35,31 @@ on property:ro.enable.native.bridge.exec=1
"ro.dalvik.vm.isa.arm": "x86", "ro.dalvik.vm.isa.arm": "x86",
"ro.dalvik.vm.isa.arm64": "x86_64" "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 download(self): def __init__(self, android_version="11") -> None:
Logger.info("Downloading libhoudini to {}now .....".format(self.download_loc)) super().__init__()
super().download() self.dl_link = self.dl_links[android_version][0]
self.act_md5 = self.dl_links[android_version][1]
def copy(self): def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libhoudini library files ...") Logger.info("Copying libhoudini library files ...")
name = re.findall("([a-zA-Z0-9]+)\.zip", self.dl_link)[0] 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, 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) "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") init_path = os.path.join(
self.copy_dir, self.partition, "etc", "init", "houdini.rc")
if not os.path.isfile(init_path): if not os.path.isfile(init_path):
os.makedirs(os.path.dirname(init_path), exist_ok=True) os.makedirs(os.path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile: with open(init_path, "w") as initfile:
+184
View File
@@ -0,0 +1,184 @@
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()
data_magisk_dir = os.path.join(data_dir, "adb", "magisk")
shutil.copytree(magisk_absolute_dir, data_magisk_dir, dirs_exist_ok=True)
# General.install() calls set_perm() only over self.files, which are paths
# under copy_dir (the overlay). This /data/adb copy is made here, before
# that runs, so it keeps the 0644 the binaries inherited from the apk
# extraction. A non-executable /data/adb/magisk/magisk64 makes magisk_env()
# abort at post-fs-data: root still works from the overlay copy, but Zygisk
# silently never initialises (Magisk reports "Zygisk: No" no matter what
# the zygisk setting says). Apply the same perms set_path_perm() gives
# magisk paths, to this copy too.
self.set_data_magisk_perm(data_magisk_dir)
def set_data_magisk_perm(self, data_magisk_dir):
if not os.path.isdir(data_magisk_dir):
return
os.chmod(data_magisk_dir, 0o755)
for root, dirnames, filenames in os.walk(data_magisk_dir):
for dirname in dirnames:
os.chmod(os.path.join(root, dirname), 0o755)
for filename in filenames:
os.chmod(os.path.join(root, filename), 0o755)
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)
+68
View File
@@ -0,0 +1,68 @@
import os
import shutil
from stuff.general import General
class Smartdock(General):
id = "smartdock"
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_1130.apk"
partition = "system"
dl_file_name = "smartdock.apk"
act_md5 = "6bfedb959ef5855c3782e8001cb67f86"
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" />
<permission name="android.permission.WRITE_SECURE_SETTINGS" />
</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
-18
View File
@@ -1,18 +0,0 @@
import os
import sys
from tools.helper import run
from tools.logger import Logger
class Android_id:
def get_id(self):
if not os.path.isfile("/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db"):
Logger.error("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 = run(["sqlite3", "/var/lib/waydroid/data/data/com.google.android.gsf/databases/gservices.db", sqs.strip()])
print(queryout.stdout.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")
-59
View File
@@ -1,59 +0,0 @@
import os
import shutil
from stuffs.general import General
from tools.helper import host, run
from tools.logger import Logger
class Gapps(General):
partition = "system"
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"],
"arm64-v8a": ["https://liquidtelecom.dl.sourceforge.net/project/opengapps/arm64/20220122/open_gapps-arm64-10.0-pico-20220122.zip", "8dfa6e76aeb2d1d5aed40b058e8a852c"],
"armeabi-v7a": ["https://nav.dl.sourceforge.net/project/opengapps/arm/20220122/open_gapps-arm-10.0-pico-20220122.zip", "a48ccbd25eb0a3c5e30f5db5435f5536"]
}
arch = host()
dl_link = dl_links[arch[0]][0]
dl_file_name = "open_gapps.zip"
act_md5 = dl_links[arch[0]][1]
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"
]
def download(self):
Logger.info("Downloading OpenGapps now to {} .....".format(self.download_loc))
super().download()
def copy(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)
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)
-133
View File
@@ -1,133 +0,0 @@
import configparser
import os
import re
import zipfile
import hashlib
from tools import images
from tools.helper import download_file, get_download_dir, run
from tools.container import DBusContainerService
from tools.logger import Logger
class General:
@property
def download_loc(self):
return os.path.join(get_download_dir(), self.dl_file_name)
@property
def copy_dir(self):
if self.use_overlayfs:
return "/var/lib/waydroid/overlay"
else:
return "/tmp/waydroid"
@property
def use_dbus(self):
try:
DBusContainerService()
except:
return False
return True
@property
def use_overlayfs(self):
with open("/var/lib/waydroid/waydroid.cfg") as f:
cont=f.read()
if re.search("mount_overlays[ \t]*=[ \t]*True", cont):
return True
return False
def download(self):
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 extract(self):
Logger.info("Extracting archive...")
with zipfile.ZipFile(self.download_loc) as z:
z.extractall(self.extract_to)
def add_props(self):
cfg = configparser.ConfigParser()
cfg.read("/var/lib/waydroid/waydroid.cfg")
for key in self.apply_props.keys():
cfg.set('properties', key, self.apply_props[key])
with open("/var/lib/waydroid/waydroid.cfg", "w") as f:
cfg.write(f)
def mount(self):
img = os.path.join(images.get_image_dir(), self.partition+".img")
mount_point = ""
if self.partition == "system":
mount_point = os.path.join(self.copy_dir)
else:
mount_point = os.path.join(self.copy_dir, self.partition)
Logger.info("Mounting {} to {}".format(img, mount_point))
images.mount(img, mount_point)
def resize(self):
img = os.path.join(images.get_image_dir(), self.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(self):
mount_point = ""
if self.partition == "system":
mount_point = os.path.join(self.copy_dir)
else:
mount_point = os.path.join(self.copy_dir, self.partition)
Logger.info("Umounting {}".format(mount_point))
images.umount(mount_point)
def stop(self):
if self.use_dbus:
self.session = DBusContainerService().GetSession()
if self.session:
DBusContainerService().Stop(False)
else:
run(["waydroid", "container", "stop"])
def start(self):
if self.use_dbus and self.session:
DBusContainerService().Start(self.session)
else:
run(["systemctl", "restart", "waydroid-container.service"])
def restart(self):
self.stop()
self.start()
def copy(self):
pass
def install(self):
if self.use_overlayfs:
self.download()
self.extract()
self.copy()
if hasattr(self, "apply_props"):
self.add_props()
self.restart()
else:
self.stop()
self.download()
self.extract()
self.resize()
self.mount()
self.copy()
if hasattr(self, "apply_props"):
self.add_props()
self.umount()
self.start()
Logger.info("Installation finished")
-89
View File
@@ -1,89 +0,0 @@
import gzip
import os
import shutil
import re
from stuffs.general import General
from tools.helper import download_file, host, run
from tools.logger import Logger
class Magisk(General):
partition = "system"
dl_link = "https://huskydg.github.io/magisk-files/app-release.apk"
dl_file_name = "magisk.apk"
extract_to = "/tmp/magisk_unpack"
magisk_dir = os.path.join(partition, "etc", "init", "magisk")
machine = host()
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 = """
on post-fs-data
start logd
exec u:r:su:s0 root root -- /system/etc/init/magisk/magisk{arch} --auto-selinux --setup-sbin /system/etc/init/magisk
exec u:r:su:s0 root root -- /system/etc/init/magisk/magiskpolicy --live --magisk "allow * magisk_file lnk_file *"
mkdir /sbin/.magisk 700
mkdir /sbin/.magisk/mirror 700
mkdir /sbin/.magisk/block 700
copy /system/etc/init/magisk/config /sbin/.magisk/config
rm /dev/.magisk_unblock
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --post-fs-data
wait /dev/.magisk_unblock 40
rm /dev/.magisk_unblock
on zygote-start
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --service
on property:sys.boot_completed=1
mkdir /data/adb/magisk 755
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --boot-complete
exec -- /system/bin/sh -c "if [ ! -e /data/data/io.github.huskydg.magisk ] ; then pm install /system/etc/init/magisk/magisk.apk ; fi"
on property:init.svc.zygote=restarting
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
on property:init.svc.zygote=stopped
exec u:r:su:s0 root root -- /sbin/magisk --auto-selinux --zygote-restart
""".format(arch=machine[1])
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)
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.machine[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)
run(["chmod", "+x", n_path])
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
# 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)
-57
View File
@@ -1,57 +0,0 @@
from os import path, makedirs
import shutil
from stuffs.general import General
from tools.helper import run
from tools.logger import Logger
class Ndk(General):
partition = "system"
dl_link = "https://github.com/supremegamers/vendor_google_proprietary_ndk_translation-prebuilt/archive/181d9290a69309511185c4417ba3d890b3caaaa8.zip"
dl_file_name = "libndktranslation.zip"
extract_to = "/tmp/libndkunpack"
act_md5 = "0beff55f312492f24d539569d84f5bfb"
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 = """
# Enable native bridge for target executables
on early-init
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm_dyn /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm64_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm64_dyn /proc/sys/fs/binfmt_misc/register
"""
def download(self):
Logger.info("Downloading libndk to {} now .....".format(self.download_loc))
super().download()
def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying libndk library files ...")
archive_url, commit_sha = path.split(path.splitext(self.dl_link)[0])
zipped_basepath, _ = path.split(archive_url)
prebuilts_sourcedir = path.join(
self.extract_to,
f"{path.basename(zipped_basepath)}-{commit_sha}",
"prebuilts")
shutil.copytree(
prebuilts_sourcedir,
path.join(self.copy_dir, self.partition),
dirs_exist_ok=True)
init_path = path.join(self.copy_dir, self.partition, "etc", "init", "libndk.rc")
if not path.isfile(init_path):
makedirs(path.dirname(init_path), exist_ok=True)
with open(init_path, "w") as initfile:
initfile.write(self.init_rc_component)
-23
View File
@@ -1,23 +0,0 @@
import os
import shutil
from stuffs.general import General
from tools.helper import run
from tools.logger import Logger
class Widevine(General):
partition = "vendor"
dl_link = "https://codeload.github.com/supremegamers/vendor_google_proprietary_widevine-prebuilt/zip/94c9ee172e3d78fecc81863f50a59e3646f7a2bd"
dl_file_name = "widevine.zip"
extract_to = "/tmp/widevineunpack"
act_md5 = "a31f325453c5d239c21ecab8cfdbd878"
def download(self):
Logger.info("Downloading widevine to {} now .....".format(self.download_loc))
super().download()
def copy(self):
run(["chmod", "+x", self.extract_to, "-R"])
Logger.info("Copying widevine library files ...")
shutil.copytree(os.path.join(self.extract_to, "vendor_google_proprietary_widevine-prebuilt-94c9ee172e3d78fecc81863f50a59e3646f7a2bd",
"prebuilts"), os.path.join(self.copy_dir, self.partition), dirs_exist_ok=True)
+179
View File
@@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""Regression test for Magisk.setup() permissions on the /data/adb/magisk copy.
install() runs copy() -> extra1() -> set_perm(). set_perm() only walks self.files,
which are paths under copy_dir (the overlay), so the copy that setup() makes into
<data>/adb/magisk keeps the 0644 the binaries inherit from the apk extraction.
A non-executable /data/adb/magisk/magisk64 makes magisk_env() abort at post-fs-data.
Root still works (it runs from the overlay copy), but Zygisk never initialises and
the Magisk app reports "Zygisk: No" with no error explaining why.
Runs as an ordinary user, needs no Waydroid install and no extra dependencies:
python3 tests/test_magisk_setup_perms.py
"""
import os
import shutil
import stat
import sys
import tempfile
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import stuff.magisk as magisk_module
from stuff.magisk import Magisk
MAGISK_BINARIES = [
"magisk64",
"magiskinit",
"magiskboot",
"magiskpolicy",
"busybox",
"util_functions.sh",
]
def make_overlay(base):
"""Mimic the tree copy() leaves behind: binaries written 0644 by shutil.copyfile."""
magisk_dir = os.path.join(base, "system", "etc", "init", "magisk")
os.makedirs(os.path.join(magisk_dir, "chromeos"), exist_ok=True)
for name in MAGISK_BINARIES:
path = os.path.join(magisk_dir, name)
with open(path, "wb") as f:
f.write(b"\x7fELF placeholder")
os.chmod(path, 0o644)
nested = os.path.join(magisk_dir, "chromeos", "futility")
with open(nested, "wb") as f:
f.write(b"placeholder")
os.chmod(nested, 0o644)
return magisk_dir
def file_modes(root):
modes = {}
for dirpath, _dirnames, filenames in os.walk(root):
for name in filenames:
path = os.path.join(dirpath, name)
modes[os.path.relpath(path, root)] = stat.S_IMODE(os.stat(path).st_mode)
return modes
def test_plain_copytree_loses_exec_bit():
"""Document the original behaviour: a bare copytree leaves the binaries 0644."""
base = tempfile.mkdtemp()
try:
src = make_overlay(base)
dst = os.path.join(base, "data", "adb", "magisk")
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.copytree(src, dst, dirs_exist_ok=True)
modes = file_modes(dst)
assert modes["magisk64"] == 0o644, (
"expected the pre-fix behaviour to reproduce, got %o" % modes["magisk64"]
)
finally:
shutil.rmtree(base, ignore_errors=True)
def test_setup_makes_data_copy_executable():
"""setup() must leave every file and dir in <data>/adb/magisk executable."""
base = tempfile.mkdtemp()
try:
make_overlay(base)
data_dir = os.path.join(base, "data")
os.makedirs(data_dir, exist_ok=True)
original_get_data_dir = magisk_module.get_data_dir
original_info = magisk_module.Logger.info
magisk_module.get_data_dir = lambda: data_dir
magisk_module.Logger.info = lambda *a, **k: None
class StubMagisk(Magisk):
@property
def copy_dir(self):
return base
try:
StubMagisk().setup()
finally:
magisk_module.get_data_dir = original_get_data_dir
magisk_module.Logger.info = original_info
dst = os.path.join(data_dir, "adb", "magisk")
modes = file_modes(dst)
assert modes, "setup() copied nothing"
not_executable = {n: oct(m) for n, m in modes.items() if m != 0o755}
assert not not_executable, "files left non-0755: %s" % not_executable
assert stat.S_IMODE(os.stat(dst).st_mode) == 0o755
nested = os.path.join(dst, "chromeos")
assert stat.S_IMODE(os.stat(nested).st_mode) == 0o755, "nested dir not fixed"
finally:
shutil.rmtree(base, ignore_errors=True)
def test_setup_is_idempotent():
base = tempfile.mkdtemp()
try:
make_overlay(base)
data_dir = os.path.join(base, "data")
os.makedirs(data_dir, exist_ok=True)
original_get_data_dir = magisk_module.get_data_dir
original_info = magisk_module.Logger.info
magisk_module.get_data_dir = lambda: data_dir
magisk_module.Logger.info = lambda *a, **k: None
class StubMagisk(Magisk):
@property
def copy_dir(self):
return base
try:
StubMagisk().setup()
StubMagisk().setup()
finally:
magisk_module.get_data_dir = original_get_data_dir
magisk_module.Logger.info = original_info
dst = os.path.join(data_dir, "adb", "magisk")
assert all(m == 0o755 for m in file_modes(dst).values())
finally:
shutil.rmtree(base, ignore_errors=True)
def test_perm_helper_tolerates_missing_dir():
Magisk().set_data_magisk_perm(os.path.join(tempfile.gettempdir(), "definitely-not-here"))
def main():
tests = [
test_plain_copytree_loses_exec_bit,
test_setup_makes_data_copy_executable,
test_setup_is_idempotent,
test_perm_helper_tolerates_missing_dir,
]
failed = 0
for test in tests:
try:
test()
except AssertionError as exc:
failed += 1
print("FAIL %s: %s" % (test.__name__, exc))
except Exception as exc: # noqa: BLE001 - surface anything unexpected
failed += 1
print("ERROR %s: %r" % (test.__name__, exc))
else:
print("ok %s" % test.__name__)
if failed:
print("\n%d test(s) failed" % failed)
return 1
print("\nall %d tests passed" % len(tests))
return 0
if __name__ == "__main__":
sys.exit(main())
+51 -5
View File
@@ -1,7 +1,53 @@
import dbus 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"): # def DBusContainerService(object_path="/ContainerManager", intf="id.waydro.ContainerManager"):
return dbus.Interface(dbus.SystemBus().get_object("id.waydro.Container", object_path), intf) # return dbus.Interface(dbus.SystemBus().get_object("id.waydro.Container", object_path), intf)
def DBusSessionService(object_path="/SessionManager", intf="id.waydro.SessionManager"): # def DBusSessionService(object_path="/SessionManager", intf="id.waydro.SessionManager"):
return dbus.Interface(dbus.SessionBus().get_object("id.waydro.Session", object_path), intf) # 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")
+77 -5
View File
@@ -1,27 +1,50 @@
import gzip
import os import os
import re
import platform import platform
import re
import subprocess import subprocess
import sys import sys
import requests import requests
from tools.logger import Logger from tools.logger import Logger
from tqdm import tqdm from tqdm import tqdm
import hashlib import hashlib
from typing import Optional
def get_download_dir(): def get_download_dir():
download_loc = "" download_loc = ""
if os.environ.get("XDG_CACHE_HOME", None) is None: 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") download_loc = os.path.join('/', "home", os.environ.get(
"SUDO_USER", os.environ["USER"]), ".cache", "waydroid-script", "downloads"
)
else: else:
download_loc = os.path.join(os.environ["XDG_CACHE_HOME"], "waydroid-script", "downloads") download_loc = os.path.join(
os.environ["XDG_CACHE_HOME"], "waydroid-script", "downloads"
)
if not os.path.exists(download_loc): if not os.path.exists(download_loc):
os.makedirs(download_loc) os.makedirs(download_loc)
return download_loc return download_loc
def run(args): # not good
result = subprocess.run(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 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()) # print(result.stdout.decode())
if result.stderr: if result.stderr:
Logger.error(result.stderr.decode("utf-8")) error = result.stderr.decode("utf-8")
if ignore and re.match(ignore, error):
return result
Logger.error(error)
raise subprocess.CalledProcessError( raise subprocess.CalledProcessError(
returncode=result.returncode, returncode=result.returncode,
cmd=result.args, cmd=result.args,
@@ -29,6 +52,43 @@ def run(args):
) )
return result 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): def download_file(url, f_name):
md5 = "" md5 = ""
response = requests.get(url, stream=True) response = requests.get(url, stream=True)
@@ -72,3 +132,15 @@ def check_root():
if os.geteuid() != 0: if os.geteuid() != 0:
Logger.error("This script must be run as root. Aborting.") Logger.error("This script must be run as root. Aborting.")
sys.exit(1) 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)
+3 -9
View File
@@ -24,14 +24,8 @@ def umount(mount_point, exists=True):
mount_point)) mount_point))
def resize(img_file, size): def resize(img_file, size):
try: run(["sudo", "e2fsck", "-y", "-f", img_file], ignore="^e2fsck \d+\.\d+\.\d (.+)\n$")
run(["e2fsck", "-y", "-f", img_file]) run(["sudo", "resize2fs", img_file, size], ignore="^resize2fs \d+\.\d+\.\d (.+)\n$")
except subprocess.CalledProcessError:
pass
try:
run(["resize2fs", img_file, size])
except subprocess.CalledProcessError:
pass
def get_image_dir(): def get_image_dir():
# Read waydroid config to get image location # Read waydroid config to get image location
@@ -42,6 +36,6 @@ def get_image_dir():
sys.exit(1) sys.exit(1)
cfg.read(cfg_file) cfg.read(cfg_file)
if "waydroid" not in cfg: if "waydroid" not in cfg:
Logger.error("ERROR: Required entry in config was not found, Cannot continue!") #magisk Logger.error("Required entry in config was not found, Cannot continue!") #magisk
sys.exit(1) sys.exit(1)
return cfg["waydroid"]["images_path"] return cfg["waydroid"]["images_path"]