diff --git a/main.py b/main.py index d9f96c8..ebb2f5f 100755 --- a/main.py +++ b/main.py @@ -13,6 +13,82 @@ from stuffs.nodataperm import Nodataperm from stuffs.smartdock import Smartdock from stuffs.widevine import Widevine import tools.helper as helper + + +import argparse + +# def main(): +# def get_certified(): +# print("Calling android_get_certified function") + +# def install_app(app_name): +# print(f"Installing {app_name}") + +# def remove_app(app_name): +# print(f"Removing {app_name}") + +# def hack_option(option_name): +# print(f"Enabling {option_name}") + +# parser = argparse.ArgumentParser(description=''' +# Does stuff like installing Gapps, installing Magisk, installing NDK Translation and getting Android ID for device registration. +# Use -h flag for help!''') + +# subparsers = parser.add_subparsers(dest='command') + +# # 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"] +# 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 +# """ +# # install and its aliases +# install_parser = subparsers.add_parser('install', aliases=['-i'], formatter_class=argparse.RawTextHelpFormatter, help='Install an app') +# install_parser.add_argument(**arg_template, help=install_help) +# install_parser.set_defaults(func=install_app) + +# # remove and its aliases +# remove_parser = subparsers.add_parser('remove', aliases=['-r'], help='Remove an app') +# remove_parser.add_argument(**arg_template, help='Name of app to remove') +# remove_parser.set_defaults(func=remove_app) + +# # hack and its aliases +# hack_parser = subparsers.add_parser('hack', aliases=['-h'], help='Hack the system') +# hack_parser.add_argument('option_name', choices=["nodataperm", "hidestatus"], help='Name of hack option') +# hack_parser.set_defaults(func=hack_option) + +# args = parser.parse_args() +# if hasattr(args, 'func'): +# args_dict = vars(args) +# if 'app_name' in args_dict: +# args.func(args_dict['app_name']) +# else: +# args.func(args_dict['option_name']) +# else: +# parser.print_help() + + + + + def install(args): app = args.app if "gapps" in app: @@ -90,17 +166,18 @@ def main(): "type": str, "nargs": '+', "metavar":"", - "choices": ["gapps", "microg", "libndk", "libhoudini", "magisk", "smartdock", "widevine", "nodataperm", "hidestatus"], } install_help = """ -gapps: Install Open GApps Pico(minimum GApps installation) +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 """ + install_parser = subparsers.add_parser("install",formatter_class=argparse.RawTextHelpFormatter, help='install something') install_parser.set_defaults(func=install) install_parser.add_argument(**arg_template,help=install_help) diff --git a/requirements.txt b/requirements.txt index e1f3e21..9a3bf03 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ tqdm requests -aapt2 +InquirerPy dbus-python==1.2.18 diff --git a/stuffs/microg.py b/stuffs/microg.py index da1e56e..b6cc0c0 100644 --- a/stuffs/microg.py +++ b/stuffs/microg.py @@ -1,105 +1,178 @@ import os import shutil -from time import sleep +import zipfile from stuffs.general import General -from tools.helper import get_download_dir, host, run -from aapt2 import aapt -from tools import container +from tools.helper import host from tools.logger import Logger class MicroG(General): partition = "system" - main_arch = host()[0] - sub_arch = "x86" if main_arch == "x86_64" else "armeabi-v7a" if main_arch == "arm64-v8a" else "" - fdroid = "https://f-droid.org/repo/" - microg="https://microg.org/fdroid/repo/" - 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", + 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" + ] } - 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_link = ... + act_md5 = ... + dl_file_name = ... + sdk = ... + extract_to = "/tmp/microg/extract" + copy_dir = "/var/lib/waydroid/overlay_rw/system" + arch = host() + rc_content = ''' +on property:sys.boot_completed=1 + start microg_service - def skip_extract(self): - return True +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/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 download(self): - for apk, md5 in self.fdroid_repo_apks.items(): - self.dl_link = self.fdroid+apk - self.act_md5 = md5 - self.dl_file_name = apk - super().download() - for apk, md5 in self.microg_apks.items(): - self.dl_link = self.microg+apk - self.act_md5 = md5 - self.dl_file_name = apk - super().download() + 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.dl_file_name = f'MinMicroG-{variant}.zip' + if android_version == "11": + self.sdk = 30 + elif android_version == "13": + self.sdk = 33 - def generate_permissions(self): - permissions = "" - download_dir = get_download_dir() - for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys(): - splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-" - package = apk.split(splitor)[0] - permissions += '\n\t\n'.format(package) - permission_list = aapt.get_apk_info(os.path.join(download_dir,apk))["permissions"] - permissions += "\n".join(['\t\t'.format(permission) for permission in permission_list]) - permissions += "\n\t" - permissions += "" - return permissions + def set_permissions(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 copy(self): - Logger.info("Copying MicroG and other files") - for apk in {**self.fdroid_repo_apks, **self.microg_apks}.keys(): - splitor = "_" if apk in self.fdroid_repo_apks.keys() else "-" - package = apk.split(splitor)[0] - download_dir = get_download_dir() - apk_dir = "app" if package not in self.priv_apps else "priv-app" - if not os.path.exists(os.path.join(self.copy_dir, self.partition, apk_dir, package)): - os.makedirs(os.path.join(self.copy_dir, self.partition, apk_dir, package)) - shutil.copyfile(os.path.join(download_dir, apk), - os.path.join(self.copy_dir, self.partition, apk_dir, package, apk)) - permissions = self.generate_permissions() - permission_dir = os.path.join(self.copy_dir, self.partition, "etc", "permissions") - if not os.path.exists(permission_dir): - os.makedirs(permission_dir) - with open(os.path.join(permission_dir, "foss-permissions.xml"), "w") as f: - f.write(permissions) - - def extra2(self): - index = 0 - while not container.is_running(): - list = ["\\", "|", "/", "—"] - sleep(0.5) - print("\r\tPlease start WayDroid for further setup {}".format(list[index%4]), end="") - index += 1 - sleep(5) - if index != 0: - print() - Logger.info("Signature spoofing") - run("waydroid shell pm grant com.google.android.gms android.permission.FAKE_PACKAGE_SIGNATURE".split()) - run("waydroid shell pm grant com.android.vending android.permission.FAKE_PACKAGE_SIGNATURE".split()) - - def remove(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) + + 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) + self.set_permissions(src_file_path) + 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": + lib_dest_dir = os.path.dirname(dst_file_path) + with zipfile.ZipFile(dst_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) + + 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) + self.set_permissions(rc_dir)