From 66cc9bc545585c5d6e5833fdb55964c9b0385f43 Mon Sep 17 00:00:00 2001 From: vvb2060 Date: Wed, 12 May 2021 13:40:53 +0800 Subject: [PATCH] Pure 64bit support --- app/build.gradle.kts | 57 +++++++++---- app/src/main/AndroidManifest.xml | 1 - .../java/com/topjohnwu/magisk/core/App.kt | 7 -- .../java/com/topjohnwu/magisk/core/Const.kt | 2 - .../java/com/topjohnwu/magisk/core/Info.kt | 17 +--- .../magisk/core/tasks/MagiskInstaller.kt | 6 +- .../topjohnwu/magisk/core/utils/ShellInit.kt | 9 +- build.gradle.kts | 6 +- build.py | 82 +++++++++++-------- native/jni/Application.mk | 7 +- scripts/flash_script.sh | 6 +- scripts/uninstaller.sh | 5 +- scripts/update_binary.sh | 11 ++- 13 files changed, 116 insertions(+), 100 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4c50bed2b..4646cf1bf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,4 @@ +import com.android.build.gradle.internal.api.ApkVariantOutputImpl import org.apache.tools.ant.filters.FixCrLfFilter import java.io.PrintStream @@ -41,6 +42,13 @@ android { } } + splits { + abi { + isEnable = true + isUniversalApk = true + } + } + buildFeatures { dataBinding = true } @@ -88,27 +96,35 @@ val syncLibs by tasks.registering(Sync::class) { rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" } } } + into("arm64-v8a") { + from(rootProject.file("native/out/arm64-v8a")) { + include("busybox", "magiskboot", "magiskinit", "magisk") + rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" } + } + from(rootProject.file("native/out/armeabi-v7a")) { + include("magisk") + rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" } + } + } + into("x86_64") { + from(rootProject.file("native/out/x86_64")) { + include("busybox", "magiskboot", "magiskinit", "magisk") + rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" } + } + from(rootProject.file("native/out/x86")) { + include("magisk") + rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" } + } + } onlyIf { - if (inputs.sourceFiles.files.size != 10) + if (inputs.sourceFiles.files.size != 16) throw StopExecutionException("Please build binaries first! (./build.py binary)") true } } -val createStubLibs by tasks.registering { - dependsOn(syncLibs) - doLast { - val arm64 = project.file("src/main/jniLibs/arm64-v8a/libstub.so") - arm64.parentFile.mkdirs() - arm64.createNewFile() - val x64 = project.file("src/main/jniLibs/x86_64/libstub.so") - x64.parentFile.mkdirs() - x64.createNewFile() - } -} - val syncAssets by tasks.registering(Sync::class) { - dependsOn(createStubLibs) + dependsOn(syncLibs) inputs.property("version", Config.version) inputs.property("versionCode", Config.versionCode) into("src/main/assets") @@ -123,9 +139,11 @@ val syncAssets by tasks.registering(Sync::class) { } filesMatching("**/util_functions.sh") { filter { - it.replace("#MAGISK_VERSION_STUB", + it.replace( + "#MAGISK_VERSION_STUB", "MAGISK_VER='${Config.version}'\n" + - "MAGISK_VER_CODE=${Config.versionCode}") + "MAGISK_VER_CODE=${Config.versionCode}" + ) } filter("eol" to FixCrLfFilter.CrLf.newInstance("lf")) } @@ -178,6 +196,13 @@ android.applicationVariants.all { } } registerJavaGeneratingTask(genSrcTask.get(), outSrcDir) + + outputs.all { + val output = this as ApkVariantOutputImpl + output.filters.forEach { + output.versionNameOverride += "-${it.identifier}" + } + } } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c94dad5c3..22361ca52 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,6 @@ android:name=".core.App" android:extractNativeLibs="true" android:icon="@drawable/ic_launcher" - android:multiArch="true" tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"> diff --git a/app/src/main/java/com/topjohnwu/magisk/core/App.kt b/app/src/main/java/com/topjohnwu/magisk/core/App.kt index 0e0f41aa0..2acf21c70 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/App.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/App.kt @@ -17,7 +17,6 @@ import com.topjohnwu.magisk.di.ServiceLocator import com.topjohnwu.magisk.ktx.unwrap import com.topjohnwu.superuser.Shell import timber.log.Timber -import java.io.File import kotlin.system.exitProcess open class App() : Application() { @@ -56,12 +55,6 @@ open class App() : Application() { val wrapped = impl.wrap() super.attachBaseContext(wrapped) - val info = base.applicationInfo - val libDir = runCatching { - info.javaClass.getDeclaredField("secondaryNativeLibraryDir").get(info) as String? - }.getOrNull() ?: info.nativeLibraryDir - Const.NATIVE_LIB_DIR = File(libDir) - ServiceLocator.context = wrapped AssetHack.init(impl) app.registerActivityLifecycleCallbacks(ForegroundTracker) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt index 5ddb8c148..93e0ed474 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Const.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Const.kt @@ -3,7 +3,6 @@ package com.topjohnwu.magisk.core import android.os.Build import android.os.Process import com.topjohnwu.magisk.BuildConfig -import java.io.File @Suppress("DEPRECATION") object Const { @@ -13,7 +12,6 @@ object Const { // Paths lateinit var MAGISKTMP: String - lateinit var NATIVE_LIB_DIR: File val MAGISK_PATH get() = "$MAGISKTMP/modules" const val TMPDIR = "/dev/tmp" const val MAGISK_LOG = "/cache/magisk.log" diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Info.kt b/app/src/main/java/com/topjohnwu/magisk/core/Info.kt index d00baa3b9..3e0bb77a1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Info.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Info.kt @@ -11,14 +11,13 @@ import com.topjohnwu.magisk.ktx.getProperty import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.ShellUtils.fastCmd import com.topjohnwu.superuser.internal.UiThreadHandler -import java.io.File -import java.io.IOException val isRunningAsStub get() = Info.stub != null object Info { var stub: DynAPK.Data? = null + var stubArch = "lib/${Const.CPU_ABI}" val EMPTY_REMOTE = UpdateInfo() var remote = EMPTY_REMOTE @@ -49,20 +48,6 @@ object Info { } } - val isNewReboot by lazy { - try { - val id = File("/proc/sys/kernel/random/boot_id").readText() - if (id != Config.bootId) { - Config.bootId = id - true - } else { - false - } - } catch (e: IOException) { - false - } - } - private fun loadState() = Env( fastCmd("magisk -v").split(":".toRegex())[0], runCatching { fastCmd("magisk -V").toInt() }.getOrDefault(-1), diff --git a/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt b/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt index 607925c3e..0c7c50b00 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt @@ -94,7 +94,7 @@ abstract class MagiskInstallImpl protected constructor( if (isRunningAsStub) { val zf = ZipFile(DynAPK.current(context)) zf.entries().asSequence().filter { - !it.isDirectory && it.name.startsWith("lib/${Const.CPU_ABI_32}/") + !it.isDirectory && it.name.startsWith(Info.stubArch) }.forEach { val n = it.name.substring(it.name.lastIndexOf('/') + 1) val name = n.substring(3, n.length - 3) @@ -102,7 +102,7 @@ abstract class MagiskInstallImpl protected constructor( zf.getInputStream(it).writeTo(dest) } } else { - val libs = Const.NATIVE_LIB_DIR.listFiles { _, name -> + val libs = File(context.applicationInfo.nativeLibraryDir).listFiles { _, name -> name.startsWith("lib") && name.endsWith(".so") } ?: emptyArray() for (lib in libs) { @@ -250,7 +250,7 @@ abstract class MagiskInstallImpl protected constructor( src.reset() val alpha = "abcdefghijklmnopqrstuvwxyz" - val alphaNum = "$alpha${alpha.toUpperCase(Locale.ROOT)}0123456789" + val alphaNum = "$alpha${alpha.uppercase(Locale.ROOT)}0123456789" val random = SecureRandom() val filename = StringBuilder("magisk_patched-${BuildConfig.VERSION_CODE}_").run { for (i in 1..5) { diff --git a/app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt b/app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt index bfec87cd7..ee9bd0516 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt @@ -1,7 +1,6 @@ package com.topjohnwu.magisk.core.utils import android.content.Context -import android.os.Build import com.topjohnwu.magisk.DynAPK import com.topjohnwu.magisk.R import com.topjohnwu.magisk.core.* @@ -34,13 +33,17 @@ class BusyBoxInit : BaseShellInit() { if (!shell.isRoot) return true val jar = JarFile(DynAPK.current(context)) - val bb = jar.getJarEntry("lib/${Const.CPU_ABI_32}/libbusybox.so") + var bb = jar.getJarEntry("${Info.stubArch}/libbusybox.so") + if (bb == null) { + Info.stubArch = "lib/${Const.CPU_ABI_32}" + bb = jar.getJarEntry("${Info.stubArch}/libbusybox.so") + } localBB = context.deviceProtectedContext.cachedFile("busybox") localBB.delete() jar.getInputStream(bb).writeTo(localBB) localBB.setExecutable(true) } else { - localBB = File(Const.NATIVE_LIB_DIR, "libbusybox.so") + localBB = File(context.applicationInfo.nativeLibraryDir, "libbusybox.so") } if (shell.isRoot) { diff --git a/build.gradle.kts b/build.gradle.kts index babb37940..a194009bb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,9 +48,9 @@ subprojects { ndkPath = "${System.getenv("ANDROID_SDK_ROOT")}/ndk/magisk" defaultConfig { - if (minSdkVersion == null) - minSdkVersion(21) - targetSdkVersion(30) + if (minSdk == null) + minSdk = 21 + targetSdk = 30 } compileOptions { diff --git a/build.py b/build.py index 01dbea51b..f55c1cdf0 100755 --- a/build.py +++ b/build.py @@ -1,17 +1,17 @@ #!/usr/bin/env python3 -import sys -import os -import subprocess import argparse -import multiprocessing -import zipfile import errno -import shutil import lzma -import platform -import urllib.request +import multiprocessing +import os import os.path as op +import platform +import shutil import stat +import subprocess +import sys +import urllib.request +import zipfile from distutils.dir_util import copy_tree @@ -40,6 +40,7 @@ is_ci = 'CI' in os.environ and os.environ['CI'] == 'true' if not is_ci and is_windows: import colorama + colorama.init() # Environment checks @@ -56,10 +57,9 @@ except FileNotFoundError: error('Please install JDK and make sure \'javac\' is available in PATH') cpu_count = multiprocessing.cpu_count() -archs = ['armeabi-v7a', 'x86'] -arch64 = ['arm64-v8a', 'x86_64'] -support_targets = ['magisk', 'magiskinit', 'magiskboot', 'magiskpolicy', 'resetprop', 'busybox', 'test'] +archs = ['armeabi-v7a', 'x86', 'arm64-v8a', 'x86_64'] default_targets = ['magisk', 'magiskinit', 'magiskboot', 'busybox'] +support_targets = default_targets + ['magiskpolicy', 'resetprop', 'test'] ndk_root = op.join(os.environ['ANDROID_SDK_ROOT'], 'ndk') ndk_path = op.join(ndk_root, 'magisk') @@ -178,7 +178,7 @@ def load_config(args): def collect_binary(): - for arch in archs + arch64: + for arch in archs: mkdir_p(op.join('native', 'out', arch)) for bin in support_targets: source = op.join('native', 'libs', arch, bin) @@ -196,7 +196,7 @@ def clean_elf(): '-o', elf_cleaner]) args = [elf_cleaner] args.extend(op.join('native', 'out', arch, 'magisk') - for arch in archs + arch64) + for arch in archs) execv(args) @@ -211,6 +211,7 @@ def find_build_tools(): build_tools = op.join(build_tools_root, ls[-1]) return build_tools + # Unused but keep this code def sign_zip(unsigned): if 'keyStore' not in config: @@ -220,18 +221,18 @@ def sign_zip(unsigned): apksigner = op.join(find_build_tools(), 'apksigner' + ('.bat' if is_windows else '')) exec_args = [apksigner, 'sign', - '--ks', config['keyStore'], - '--ks-pass', f'pass:{config["keyStorePass"]}', - '--ks-key-alias', config['keyAlias'], - '--key-pass', f'pass:{config["keyPass"]}', - '--v1-signer-name', 'CERT', - '--v4-signing-enabled', 'false'] + '--ks', config['keyStore'], + '--ks-pass', f'pass:{config["keyStorePass"]}', + '--ks-key-alias', config['keyAlias'], + '--key-pass', f'pass:{config["keyPass"]}', + '--v1-signer-name', 'CERT', + '--v4-signing-enabled', 'false'] if unsigned.endswith('.zip'): msg = '* Signing zip' exec_args.extend(['--min-sdk-version', '17', - '--v2-signing-enabled', 'false', - '--v3-signing-enabled', 'false']) + '--v2-signing-enabled', 'false', + '--v3-signing-enabled', 'false']) exec_args.append(unsigned) @@ -264,6 +265,7 @@ def dump_bin_headers(): stub = op.join(config['outdir'], 'stub-release.apk') if not op.exists(stub): error('Build stub APK before building "magiskinit"') + mkdir_p(op.join('native', 'out')) with open(op.join('native', 'out', 'binaries.h'), 'w') as out: with open(stub, 'rb') as src: binary_dump(src, out, 'manager_xz') @@ -304,18 +306,13 @@ def build_binary(args): if not args.release: base_flags += ' MAGISK_DEBUG=1' + flag = '' + if 'magisk' in args.target: - run_ndk_build('B_MAGISK=1 B_64BIT=1') - clean_elf() + flag += ' B_MAGISK=1' if 'test' in args.target: - run_ndk_build('B_TEST=1 B_64BIT=1') - - if 'busybox' in args.target: - run_ndk_build('B_BB=1') - - # 32-bit only targets can be built in one command - flag = '' + flag += ' B_TEST=1' if 'magiskinit' in args.target: dump_bin_headers() @@ -333,6 +330,12 @@ def build_binary(args): if flag: run_ndk_build(flag) + if 'magisk' in args.target: + clean_elf() + + if 'busybox' in args.target: + run_ndk_build('B_BB=1') + def build_apk(args, module): build_type = 'Release' if args.release or module == 'stub' else 'Debug' @@ -343,13 +346,20 @@ def build_apk(args, module): error(f'Build {module} failed!') build_type = build_type.lower() - apk = f'{module}-{build_type}.apk' - source = op.join(module, 'build', 'outputs', 'apk', build_type, apk) - target = op.join(config['outdir'], apk) - mv(source, target) - header('Output: ' + target) - return target + if module == 'app': + for arch in archs + ['universal']: + apk = f'{module}-{arch}-{build_type}.apk' + source = op.join(module, 'build', 'outputs', 'apk', build_type, apk) + target = op.join(config['outdir'], apk) + mv(source, target) + header('Output: ' + target) + else: + apk = f'{module}-{build_type}.apk' + source = op.join(module, 'build', 'outputs', 'apk', build_type, apk) + target = op.join(config['outdir'], apk) + mv(source, target) + header('Output: ' + target) def build_app(args): diff --git a/native/jni/Application.mk b/native/jni/Application.mk index e1d65f416..b9767d52f 100644 --- a/native/jni/Application.mk +++ b/native/jni/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := armeabi-v7a x86 +APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto \ -D__MVSTR=${MAGISK_VERSION} -D__MCODE=${MAGISK_VER_CODE} APP_LDFLAGS := -flto @@ -10,11 +10,6 @@ ifdef MAGISK_DEBUG APP_CFLAGS += -D__MDBG endif -# Build 64 bit binaries -ifdef B_64BIT -APP_ABI += arm64-v8a x86_64 -endif - # Busybox should use stock libc.a ifdef B_BB APP_PLATFORM := android-22 diff --git a/scripts/flash_script.sh b/scripts/flash_script.sh index 268d929f6..8ba48002f 100644 --- a/scripts/flash_script.sh +++ b/scripts/flash_script.sh @@ -52,12 +52,14 @@ api_level_arch_detect ui_print "- Device platform: $ARCH" -BINDIR=$INSTALLER/lib/$ARCH32 -[ ! -d "$BINDIR" ] && BINDIR=$INSTALLER/lib/armeabi-v7a +BINDIR=$INSTALLER/lib/$ABILONG +[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/$ARCH32 +[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/armeabi-v7a cd $BINDIR for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done cd / chmod -R 755 $CHROMEDIR $BINDIR +cp -af $CHROMEDIR/. $BINDIR/chromeos # Check if system root is installed and remove $BOOTMODE || remove_system_su diff --git a/scripts/uninstaller.sh b/scripts/uninstaller.sh index 0ae31d828..9b4561f9e 100644 --- a/scripts/uninstaller.sh +++ b/scripts/uninstaller.sh @@ -57,8 +57,9 @@ api_level_arch_detect ui_print "- Device platform: $ARCH" -BINDIR=$INSTALLER/lib/$ARCH32 -[ ! -d "$BINDIR" ] && BINDIR=$INSTALLER/lib/armeabi-v7a +BINDIR=$INSTALLER/lib/$ABILONG +[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/$ARCH32 +[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/armeabi-v7a cd $BINDIR for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done cd / diff --git a/scripts/update_binary.sh b/scripts/update_binary.sh index 474a85353..ff37a0b64 100644 --- a/scripts/update_binary.sh +++ b/scripts/update_binary.sh @@ -5,10 +5,15 @@ rm -rf $TMPDIR mkdir -p $TMPDIR 2>/dev/null export BBBIN=$TMPDIR/busybox -unzip -o "$3" lib/x86/libbusybox.so lib/armeabi-v7a/libbusybox.so -d $TMPDIR >&2 +unzip -o "$3" "lib/*/libbusybox.so" -d $TMPDIR >&2 chmod -R 755 $TMPDIR/lib -mv -f $TMPDIR/lib/x86/libbusybox.so $BBBIN -$BBBIN >/dev/null 2>&1 || mv -f $TMPDIR/lib/armeabi-v7a/libbusybox.so $BBBIN +for arch in "x86_64" "x86" "arm64-v8a" "armeabi-v7a"; do + libpath="$TMPDIR/lib/$arch/libbusybox.so" + if [ -x $libpath ] && $libpath >/dev/null 2>&1; then + mv -f $libpath $BBBIN + break + fi +done $BBBIN rm -rf $TMPDIR/lib export INSTALLER=$TMPDIR/install