Merge pull request #70 from ayasa520/main
Uninstall function, microG installation and some hacks
2
.gitignore
vendored
|
|
@ -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,4 @@ venv.bak/
|
||||||
# mypy
|
# mypy
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
|
||||||
|
test.py
|
||||||
158
README.md
|
|
@ -1,51 +1,83 @@
|
||||||
# Waydroid Extras Script
|
# Waydroid Extras 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:
|
## Interactive terminal interface
|
||||||
sudo pacman -S lzip sqlite
|
|
||||||
## Debian and Ubuntu based distributions:
|
```
|
||||||
sudo apt install lzip sqlite
|
git clone https://github.com/casualsnek/waydroid_script
|
||||||
## RHEL, Fedora and Rocky based distributions:
|
cd waydroid_script
|
||||||
sudo dnf install lzip sqlite
|
sudo python3 -m pip install -r
|
||||||
## openSUSE based distributions:
|
sudo python main.py
|
||||||
sudo zypper install lzip sqlite
|
```
|
||||||
Then run:
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Command Line
|
||||||
|
|
||||||
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
|
sudo python3 -m pip install -r requirements.txt
|
||||||
sudo python3 main.py [-i/-g/-n/-h/-w]
|
# install something
|
||||||
|
sudo python3 main.py install {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
|
||||||
|
# uninstall something
|
||||||
|
sudo python3 main.py uninstall {gapps, magisk, libndk, libhoudini, nodataperm, smartdock, microg}
|
||||||
|
# get Android device ID
|
||||||
|
sudo python main.py certified
|
||||||
|
# some hacks
|
||||||
|
sudo python3 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:
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py -g
|
sudo 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:
|
After waydroid has finished booting open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
sudo python3 main.py -i
|
sudo python3 main.py google
|
||||||
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 !
|
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 !
|
||||||
|
|
||||||
## Install Magisk
|
## Install Magisk
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
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 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 +87,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 python3 main.py install libndk
|
||||||
|
|
||||||
## Install libhoudini arm translation
|
## Install libhoudini arm translation
|
||||||
|
|
||||||
|
|
@ -67,14 +99,74 @@ 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 python3 main.py install libhoudini
|
||||||
|
|
||||||
## Integrate Widevine DRM (L3)
|
## Integrate Widevine DRM (L3)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
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 python3 main.py install widevine
|
||||||
|
|
||||||
|
## Install Smart Dock
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
|
sudo python3 main.py install smartdock
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Open terminal and switch to directory where "main.py" is located then run:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo 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 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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```
|
||||||
|
sudo python main.py install microg
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hide Status Bar
|
||||||
|
Before
|
||||||
|

|
||||||
|
|
||||||
|
After
|
||||||
|

|
||||||
|
|
||||||
|
```
|
||||||
|
sudo python3 main.py hack hidestatusbar
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Get Android ID for device registration
|
## Get Android ID for device registration
|
||||||
|
|
@ -82,20 +174,20 @@ Open terminal and switch to directory where "main.py" is located then run:
|
||||||
You need to register you device with its it before being able to use gapps, this will print out your Android ID which you can use for device registration required for google apps:
|
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 python3 main.py google
|
||||||
|
|
||||||
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 a 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
assets/1.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
BIN
assets/2.png
Normal file
|
After Width: | Height: | Size: 344 KiB |
BIN
assets/3.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
assets/4.png
Normal file
|
After Width: | Height: | Size: 321 KiB |
BIN
assets/5.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
assets/6.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
BIN
assets/7.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
assets/8.png
Normal file
|
After Width: | Height: | Size: 590 KiB |
BIN
assets/9.png
Normal file
|
After Width: | Height: | Size: 665 KiB |
BIN
assets/img/README/image-20230430013103883.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
assets/img/README/image-20230430013119763.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
assets/img/README/image-20230430013148814.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
bin/arm64-v8a/resetprop
Executable file
BIN
bin/armeabi-v7a/resetprop
Executable file
BIN
bin/x86/resetprop
Executable file
BIN
bin/x86_64/resetprop
Executable file
386
main.py
Normal file → Executable file
|
|
@ -1,63 +1,343 @@
|
||||||
|
#!/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.ndk import Ndk
|
||||||
|
from stuff.nodataperm import Nodataperm
|
||||||
|
from stuff.smartdock import Smartdock
|
||||||
|
from stuff.widevine import Widevine
|
||||||
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))
|
||||||
|
|
||||||
|
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 "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="11",
|
||||||
|
).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", "magisk", "smartdock",]
|
||||||
|
hack_choices = []
|
||||||
|
if android_version=="11":
|
||||||
|
install_choices.extend(["libhoudini", "widevine"])
|
||||||
|
hack_choices.extend(["nodataperm", "hidestatusbar"])
|
||||||
|
|
||||||
|
if action == "Install":
|
||||||
|
apps = inquirer.checkbox(
|
||||||
|
message="Select apps",
|
||||||
|
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
|
||||||
|
validate=lambda result: len(result) >= 1,
|
||||||
|
invalid_message="should be at least 1 selection",
|
||||||
|
choices=install_choices
|
||||||
|
).execute()
|
||||||
|
microg_variants = ["Standard", "NoGoolag",
|
||||||
|
"UNLP", "Minimal", "MinimalIAP"]
|
||||||
|
if "MicroG" in apps:
|
||||||
|
microg_variant = inquirer.select(
|
||||||
|
message="Select MicroG variant",
|
||||||
|
choices=microg_variants,
|
||||||
|
default="Standard",
|
||||||
|
).execute()
|
||||||
|
args.microg_variant = microg_variant
|
||||||
|
args.app = apps
|
||||||
|
install_app(args)
|
||||||
|
elif action == "Remove":
|
||||||
|
apps = inquirer.checkbox(
|
||||||
|
message="Select apps",
|
||||||
|
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
|
||||||
|
validate=lambda result: len(result) >= 1,
|
||||||
|
invalid_message="should be at least 1 selection",
|
||||||
|
choices=[*install_choices, *hack_choices]
|
||||||
|
).execute()
|
||||||
|
args.app = apps
|
||||||
|
args.microg_variant="Standard"
|
||||||
|
remove_app(args)
|
||||||
|
elif action == "Hack":
|
||||||
|
apps = inquirer.checkbox(
|
||||||
|
message="Select hack options",
|
||||||
|
instruction="([\u2191\u2193]: Select Item. [Space]: Toggle Choice), [Enter]: Confirm",
|
||||||
|
validate=lambda result: len(result) >= 1,
|
||||||
|
invalid_message="should be at least 1 selection",
|
||||||
|
choices=hack_choices
|
||||||
|
).execute()
|
||||||
|
args.option_name = apps
|
||||||
|
hack_option(args)
|
||||||
|
elif action == "Get Google Device ID to Get Certified":
|
||||||
|
AndroidId().get_id()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
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="11",
|
||||||
|
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", "smartdock", "widevine"]
|
||||||
|
hack_choices = ["nodataperm", "hidestatusbar"]
|
||||||
|
micrg_variants = ["Standard", "NoGoolag", "UNLP", "Minimal", "MinimalIAP"]
|
||||||
|
remove_choices = install_choices
|
||||||
|
|
||||||
|
arg_template = {
|
||||||
|
"dest": "app",
|
||||||
|
"type": str,
|
||||||
|
"nargs": '+',
|
||||||
|
# "metavar":"",
|
||||||
|
}
|
||||||
|
|
||||||
|
install_help = """
|
||||||
|
gapps: Install Open GApps (Android 11) or MindTheGapps (Android 13)
|
||||||
|
microg: Add microG, Aurora Store and Aurora Droid to WayDriod
|
||||||
|
libndk: Add libndk arm translation, better for AMD CPUs
|
||||||
|
libhoudini: Add libhoudini arm translation, better for Intel CPUs
|
||||||
|
magisk: Install Magisk Delta to WayDroid
|
||||||
|
smartdock: A desktop mode launcher for Android
|
||||||
|
widevine: Add support for widevine DRM L3
|
||||||
"""
|
"""
|
||||||
parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawDescriptionHelpFormatter)
|
# install and its aliases
|
||||||
parser.add_argument('-g', '--install-gapps',
|
install_parser = subparsers.add_parser(
|
||||||
dest='gapps',
|
'install', formatter_class=argparse.RawTextHelpFormatter, help='Install an app')
|
||||||
help='Install OpenGapps to waydroid',
|
install_parser.add_argument(
|
||||||
action='store_true')
|
**arg_template, choices=install_choices, help=install_help)
|
||||||
parser.add_argument('-n', '--install-ndk-translation',
|
install_parser.set_defaults(func=install_app)
|
||||||
dest='ndk',
|
|
||||||
help='Install libndk translation for arm translation',
|
# remove and its aliases
|
||||||
action='store_true')
|
remove_parser = subparsers.add_parser(
|
||||||
parser.add_argument('-i', '--get-android-id', dest='getid',
|
'remove', aliases=["uninstall"], help='Remove an app')
|
||||||
help='Displays your android id for manual registration',
|
remove_parser.add_argument(
|
||||||
action='store_true')
|
**arg_template, choices=[*remove_choices, * hack_choices], help='Name of app to remove')
|
||||||
parser.add_argument('-m', '--install-magisk', dest='magisk',
|
remove_parser.set_defaults(func=remove_app)
|
||||||
help='Attempts to install Magisk ( Bootless )',
|
|
||||||
action='store_true')
|
# hack and its aliases
|
||||||
parser.add_argument('-l', '--install-libhoudini', dest='houdini',
|
hack_parser = subparsers.add_parser('hack', help='Hack the system')
|
||||||
help='Install libhoudini for arm translation',
|
hack_parser.add_argument(
|
||||||
action='store_true')
|
'option_name', nargs="+", choices=hack_choices, help='Name of hack option')
|
||||||
parser.add_argument('-w', '--install-widevine', dest='widevine',
|
hack_parser.set_defaults(func=hack_option)
|
||||||
help='Integrate Widevine DRM (L3)',
|
|
||||||
action='store_true')
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
helper.check_root()
|
args.microg_variant = "Standard"
|
||||||
if args.getid:
|
if hasattr(args, 'func'):
|
||||||
Android_id().get_id()
|
args_dict = vars(args)
|
||||||
if args.gapps:
|
helper.check_root()
|
||||||
Gapps().install()
|
args.func(args)
|
||||||
if args.ndk and not args.houdini:
|
else:
|
||||||
arch = helper.host()[0]
|
helper.check_root()
|
||||||
if arch == "x86_64":
|
interact()
|
||||||
Ndk().install()
|
|
||||||
else:
|
|
||||||
Logger.warn("libndk is not supported on your CPU")
|
|
||||||
if args.houdini and not args.ndk:
|
|
||||||
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()
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
tqdm
|
tqdm
|
||||||
requests
|
requests
|
||||||
|
InquirerPy
|
||||||
|
|
|
||||||
21
stuff/android_id.py
Normal 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("WayDroid isn't running !")
|
||||||
|
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")
|
||||||
172
stuff/gapps.py
Normal 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/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86_64-20230323.zip", "aba427be1ddd0963121c87a4eda80299"],
|
||||||
|
"x86": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-x86-20230323.zip", "f02d2f1a3f0a084f13ab4c1b58ad7554"],
|
||||||
|
"arm64-v8a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm64-20230323.zip", "18484a5622eeccffcea2b43205655d8a"],
|
||||||
|
"armeabi-v7a": ["https://github.com/Howard20181/MindTheGappsBuilder/releases/download/20230323/MindTheGapps-13.0.0-arm-20230323.zip", "e4c00a7eb1e4dfca0fc6a3e447710264"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
stuff/general.py
Normal 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(
|
||||||
|
"./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
stuff/hidestatusbar.py
Normal 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.1/app-release.apk",
|
||||||
|
"ae6c4cc567d6f3de77068e54e43818e2"]}
|
||||||
|
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
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
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/978d8cba061a08837b7e520cd03b635af643ba08.zip", "1e139054c05034648fae58a1810573b4"]
|
||||||
|
}
|
||||||
|
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 = """
|
||||||
|
|
@ -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:
|
||||||
165
stuff/magisk.py
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
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://huskydg.github.io/magisk-files/app-debug.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/magisk{host()[1]} --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
|
||||||
|
"""
|
||||||
|
|
||||||
|
def download(self):
|
||||||
|
if os.path.isfile(self.download_loc):
|
||||||
|
os.remove(self.download_loc)
|
||||||
|
Logger.info("Downloading latest Magisk-Delta to {} now ...".format(self.download_loc))
|
||||||
|
download_file(self.dl_link, self.download_loc)
|
||||||
|
|
||||||
|
# require additional setup
|
||||||
|
def setup(self):
|
||||||
|
Logger.info("Additional setup")
|
||||||
|
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
||||||
|
data_dir = get_data_dir()
|
||||||
|
shutil.copytree(magisk_absolute_dir, os.path.join(data_dir, "adb", "magisk"), dirs_exist_ok=True)
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
magisk_absolute_dir = os.path.join(self.copy_dir, self.magisk_dir)
|
||||||
|
if not os.path.exists(magisk_absolute_dir):
|
||||||
|
os.makedirs(magisk_absolute_dir, exist_ok=True)
|
||||||
|
|
||||||
|
if not os.path.exists(os.path.join(self.copy_dir, "sbin")):
|
||||||
|
os.makedirs(os.path.join(self.copy_dir, "sbin"), exist_ok=True)
|
||||||
|
|
||||||
|
Logger.info("Copying magisk libs now ...")
|
||||||
|
|
||||||
|
lib_dir = os.path.join(self.extract_to, "lib", self.arch[0])
|
||||||
|
for parent, dirnames, filenames in os.walk(lib_dir):
|
||||||
|
for filename in filenames:
|
||||||
|
o_path = os.path.join(lib_dir, filename)
|
||||||
|
filename = re.search('lib(.*)\.so', filename)
|
||||||
|
n_path = os.path.join(magisk_absolute_dir, filename.group(1))
|
||||||
|
shutil.copyfile(o_path, n_path)
|
||||||
|
shutil.copyfile(self.download_loc, os.path.join(magisk_absolute_dir,"magisk.apk") )
|
||||||
|
shutil.copytree(os.path.join(self.extract_to, "assets", "chromeos"), os.path.join(magisk_absolute_dir, "chromeos"), dirs_exist_ok=True)
|
||||||
|
assets_files = [
|
||||||
|
"addon.d.sh",
|
||||||
|
"boot_patch.sh",
|
||||||
|
"stub.apk",
|
||||||
|
"util_functions.sh"
|
||||||
|
]
|
||||||
|
for f in assets_files:
|
||||||
|
shutil.copyfile(os.path.join(self.extract_to, "assets", f), os.path.join(magisk_absolute_dir, f))
|
||||||
|
|
||||||
|
# Updating Magisk from Magisk manager will modify bootanim.rc,
|
||||||
|
# So it is necessary to backup the original bootanim.rc.
|
||||||
|
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
|
||||||
|
gz_filename = os.path.join(bootanim_path)+".gz"
|
||||||
|
with gzip.open(gz_filename,'wb') as f_gz:
|
||||||
|
f_gz.write(self.oringinal_bootanim.encode('utf-8'))
|
||||||
|
with open(bootanim_path, "w") as initfile:
|
||||||
|
initfile.write(self.oringinal_bootanim+self.bootanim_component)
|
||||||
|
|
||||||
|
def set_path_perm(self, path):
|
||||||
|
if "magisk" in path.split("/"):
|
||||||
|
perms = [0, 2000, 0o755, 0o755]
|
||||||
|
else:
|
||||||
|
perms = [0, 0, 0o755, 0o644]
|
||||||
|
|
||||||
|
mode = os.stat(path).st_mode
|
||||||
|
|
||||||
|
if os.path.isdir(path):
|
||||||
|
mode |= perms[2]
|
||||||
|
else:
|
||||||
|
mode |= perms[3]
|
||||||
|
|
||||||
|
os.chown(path, perms[0], perms[1])
|
||||||
|
os.chmod(path, mode)
|
||||||
|
|
||||||
|
def extra1(self):
|
||||||
|
self.delete_upper()
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
# Delete the contents of upperdir
|
||||||
|
def delete_upper(self):
|
||||||
|
if container.use_overlayfs():
|
||||||
|
sys_overlay_rw = "/var/lib/waydroid/overlay_rw"
|
||||||
|
files = [
|
||||||
|
"system/system/etc/init/bootanim.rc",
|
||||||
|
"system/system/etc/init/bootanim.rc.gz",
|
||||||
|
"system/system/etc/init/magisk",
|
||||||
|
"system/system/addon.d/99-magisk.sh",
|
||||||
|
"vendor/etc/selinux/precompiled_sepolicy"
|
||||||
|
]
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
file = os.path.join(sys_overlay_rw, f)
|
||||||
|
if os.path.isdir(file):
|
||||||
|
shutil.rmtree(file)
|
||||||
|
elif os.path.isfile(file) or os.path.exists(file):
|
||||||
|
os.remove(file)
|
||||||
|
|
||||||
|
def extra2(self):
|
||||||
|
self.delete_upper()
|
||||||
|
data_dir = get_data_dir()
|
||||||
|
files = [
|
||||||
|
os.path.join(data_dir, "adb/magisk.db"),
|
||||||
|
os.path.join(data_dir, "adb/magisk")
|
||||||
|
]
|
||||||
|
for file in files:
|
||||||
|
if os.path.isdir(file):
|
||||||
|
shutil.rmtree(file)
|
||||||
|
elif os.path.isfile(file):
|
||||||
|
os.remove(file)
|
||||||
|
bootanim_path = os.path.join(self.copy_dir, self.partition, "etc", "init", "bootanim.rc")
|
||||||
|
if container.use_overlayfs():
|
||||||
|
if os.path.exists(bootanim_path):
|
||||||
|
os.remove(bootanim_path)
|
||||||
|
else:
|
||||||
|
with open(bootanim_path, "w") as initfile:
|
||||||
|
initfile.write(self.oringinal_bootanim)
|
||||||
176
stuff/microg.py
Normal 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)
|
||||||
52
stuff/ndk.py
Normal 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/a090003c60df53a9eadb2df09bd4fd2fa86ea629.zip", "e6f0d9fc28ebc427b59a3942a9a4ffc0"]
|
||||||
|
}
|
||||||
|
dl_file_name = "libndktranslation.zip"
|
||||||
|
extract_to = "/tmp/libndkunpack"
|
||||||
|
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.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)
|
||||||
53
stuff/nodataperm.py
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import gzip
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from stuff.general import General
|
||||||
|
from tools.logger import Logger
|
||||||
|
from tools import container
|
||||||
|
|
||||||
|
|
||||||
|
class Nodataperm(General):
|
||||||
|
id = "nodataperm"
|
||||||
|
dl_links = {
|
||||||
|
"11": ["https://github.com/ayasa520/hack_full_data_permission/archive/refs/heads/main.zip",
|
||||||
|
"eafd7b0986f3edaebaf1dd89f19d49bf"],
|
||||||
|
"13": ["", ""]
|
||||||
|
}
|
||||||
|
dl_file_name = "nodataperm.zip"
|
||||||
|
extract_to = "/tmp/nodataperm"
|
||||||
|
dl_link = ...
|
||||||
|
act_md5 = ...
|
||||||
|
partition = "system"
|
||||||
|
files = [
|
||||||
|
"etc/nodataperm.sh",
|
||||||
|
"etc/init/nodataperm.rc",
|
||||||
|
"framework/services.jar"
|
||||||
|
]
|
||||||
|
|
||||||
|
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):
|
||||||
|
extract_path = os.path.join(
|
||||||
|
self.extract_to, "hack_full_data_permission-main")
|
||||||
|
if not container.use_overlayfs():
|
||||||
|
services_jar = os.path.join(
|
||||||
|
self.copy_dir, self.partition, "framework", "services.jar")
|
||||||
|
gz_filename = services_jar+".gz"
|
||||||
|
with gzip.open(gz_filename, 'wb') as f_gz:
|
||||||
|
with open(services_jar, "rb") as f:
|
||||||
|
f_gz.write(f.read())
|
||||||
|
Logger.info("Copying widevine 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")
|
||||||
|
gz_filename = services_jar+".gz"
|
||||||
|
with gzip.GzipFile(gz_filename) as f_gz:
|
||||||
|
with open(services_jar, "wb") as f:
|
||||||
|
f.writelines(f_gz)
|
||||||
67
stuff/smartdock.py
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from stuff.general import General
|
||||||
|
|
||||||
|
class Smartdock(General):
|
||||||
|
id = "smartdock"
|
||||||
|
dl_link = "https://f-droid.org/repo/cu.axel.smartdock_198.apk"
|
||||||
|
partition = "system"
|
||||||
|
dl_file_name = "smartdock.apk"
|
||||||
|
act_md5 = "a8ce0bca5e1772796404602e0fa250a4"
|
||||||
|
apply_props = { "qemu.hw.mainkeys" : "1" }
|
||||||
|
skip_extract = True
|
||||||
|
permissions = """<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<permissions>
|
||||||
|
<privapp-permissions package="cu.axel.smartdock">
|
||||||
|
<permission name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<permission name="android.permission.GET_TASKS"/>
|
||||||
|
<permission name="android.permission.REORDER_TASKS"/>
|
||||||
|
<permission name="android.permission.REMOVE_TASKS" />
|
||||||
|
<permission name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
<permission name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
|
<permission name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
<permission name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<permission name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
<permission name="android.permission.MANAGE_USERS"/>
|
||||||
|
<permission name="android.permission.BLUETOOTH_ADMIN"/>
|
||||||
|
<permission name="android.permission.BLUETOOTH_CONNECT"/>
|
||||||
|
<permission name="android.permission.BLUETOOTH"/>
|
||||||
|
<permission name="android.permission.REQUEST_DELETE_PACKAGES"/>
|
||||||
|
<permission name="android.permission.ACCESS_SUPERUSER"/>
|
||||||
|
<permission name="android.permission.PACKAGE_USAGE_STATS" />
|
||||||
|
<permission name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
|
</privapp-permissions>
|
||||||
|
</permissions>
|
||||||
|
"""
|
||||||
|
files = [
|
||||||
|
"etc/permissions/permissions_cu.axel.smartdock.xml",
|
||||||
|
"priv-app/SmartDock",
|
||||||
|
"etc/init/smartdock.rc"
|
||||||
|
]
|
||||||
|
rc_content = '''
|
||||||
|
on property:sys.boot_completed=1
|
||||||
|
start set_home_activity
|
||||||
|
|
||||||
|
service set_home_activity /system/bin/sh -c "cmd package set-home-activity cu.axel.smartdock/.activities.LauncherActivity"
|
||||||
|
user root
|
||||||
|
group root
|
||||||
|
oneshot
|
||||||
|
'''
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock")):
|
||||||
|
os.makedirs(os.path.join(self.copy_dir, self.partition, "priv-app", "SmartDock"))
|
||||||
|
if not os.path.exists(os.path.join(self.copy_dir, self.partition, "etc", "permissions")):
|
||||||
|
os.makedirs(os.path.join(self.copy_dir, self.partition, "etc", "permissions"))
|
||||||
|
shutil.copyfile(os.path.join(self.download_loc),
|
||||||
|
os.path.join(self.copy_dir, self.partition, "priv-app/SmartDock/smartdock.apk"))
|
||||||
|
|
||||||
|
with open(os.path.join(self.copy_dir, self.partition, "etc", "permissions", "permissions_cu.axel.smartdock.xml"), "w") as f:
|
||||||
|
f.write(self.permissions)
|
||||||
|
|
||||||
|
rc_dir = os.path.join(self.copy_dir, self.partition, "etc/init/smartdock.rc")
|
||||||
|
if not os.path.exists(os.path.dirname(rc_dir)):
|
||||||
|
os.makedirs(os.path.dirname(rc_dir))
|
||||||
|
self.extract_app_lib(os.path.join(self.copy_dir, self.partition, "priv-app/SmartDock/smartdock.apk"))
|
||||||
|
with open(rc_dir, "w") as f:
|
||||||
|
f.write(self.rc_content)
|
||||||
46
stuff/widevine.py
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
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/supremegamers/vendor_google_proprietary_widevine-prebuilt/archive/a8524d608431573ef1c9313822d271f78728f9a6.zip",
|
||||||
|
"5c55df61da5c012b4e43746547ab730f"]
|
||||||
|
},
|
||||||
|
# "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/mediadrm",
|
||||||
|
"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]
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
@ -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")
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,135 +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, upgrade
|
|
||||||
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"])
|
|
||||||
upgrade()
|
|
||||||
|
|
||||||
def restart(self):
|
|
||||||
self.stop()
|
|
||||||
self.start()
|
|
||||||
upgrade()
|
|
||||||
|
|
||||||
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")
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,10 +1,53 @@
|
||||||
try:
|
import configparser
|
||||||
import dbus
|
import os
|
||||||
except ModuleNotFoundError:
|
import sys
|
||||||
pass
|
# 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")
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -7,18 +8,29 @@ 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: list, env = None, ignore = None):
|
# not good
|
||||||
|
def get_data_dir():
|
||||||
|
return os.path.join('/', "home", os.environ.get("SUDO_USER", os.environ["USER"]), ".local", "share", "waydroid", "data")
|
||||||
|
|
||||||
|
# execute on host
|
||||||
|
def run(args: list, env: Optional[str] = None, ignore: Optional[str] = None):
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
args=args,
|
args=args,
|
||||||
env=env,
|
env=env,
|
||||||
|
|
@ -39,6 +51,43 @@ def run(args: list, env = None, ignore = None):
|
||||||
)
|
)
|
||||||
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)
|
||||||
|
|
@ -82,6 +131,3 @@ 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 upgrade():
|
|
||||||
run(["waydroid", "upgrade", "-o"], ignore=r"\[.*\] Stopping container\n\[.*\] Starting container")
|
|
||||||
|
|
@ -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"]
|
||||||