From 196d9af0994c1d8a04fa6b4d0477d0ca91f40cb1 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 19 Oct 2023 05:15:53 -0700 Subject: [PATCH] Add application and Zygisk tests to avd_test.sh --- .../com/topjohnwu/magisk/core/Provider.kt | 10 ++- .../topjohnwu/magisk/core/su/TestHandler.kt | 67 +++++++++++++++++++ scripts/avd_magisk.sh | 2 +- scripts/avd_test.sh | 59 ++++++++++++---- 4 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/core/su/TestHandler.kt diff --git a/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt b/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt index 0439989f9..c634ffe24 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/Provider.kt @@ -6,12 +6,18 @@ import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor.MODE_READ_ONLY import com.topjohnwu.magisk.core.base.BaseProvider import com.topjohnwu.magisk.core.su.SuCallbackHandler +import com.topjohnwu.magisk.core.su.TestHandler class Provider : BaseProvider() { override fun call(method: String, arg: String?, extras: Bundle?): Bundle? { - SuCallbackHandler.run(context!!, method, extras) - return Bundle.EMPTY + return when (method) { + SuCallbackHandler.LOG, SuCallbackHandler.NOTIFY -> { + SuCallbackHandler.run(context!!, method, extras) + Bundle.EMPTY + } + else -> TestHandler.run(method) + } } override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { diff --git a/app/src/main/java/com/topjohnwu/magisk/core/su/TestHandler.kt b/app/src/main/java/com/topjohnwu/magisk/core/su/TestHandler.kt new file mode 100644 index 000000000..79e56a5c0 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/core/su/TestHandler.kt @@ -0,0 +1,67 @@ +package com.topjohnwu.magisk.core.su + +import android.os.Bundle +import com.topjohnwu.magisk.core.Config +import com.topjohnwu.magisk.core.Info +import com.topjohnwu.magisk.core.di.ServiceLocator +import com.topjohnwu.magisk.core.tasks.MagiskInstaller +import com.topjohnwu.magisk.core.utils.RootUtils +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.internal.NOPList +import kotlinx.coroutines.runBlocking + +object TestHandler { + + fun run(method: String): Bundle { + val r = Bundle() + + fun setup(): Boolean { + val nop = NOPList.getInstance() + return runBlocking { + MagiskInstaller.Emulator(nop, nop).exec() + } + } + + fun test(): Boolean { + // Make sure Zygisk works correctly + if (!Info.isZygiskEnabled) { + r.putString("reason", "zygisk not enabled") + return false + } + + // Make sure the Magisk app can get root + val shell = Shell.getShell() + if (!shell.isRoot) { + r.putString("reason", "shell not root") + return false + } + + // Make sure the root service is running + RootUtils.Connection.await() + + // Clear existing grant for ADB shell + runBlocking { + ServiceLocator.policyDB.delete(2000) + Config.suAutoResponse = Config.Value.SU_AUTO_ALLOW + } + return true + } + + val b = runCatching { + when (method) { + "setup" -> setup() + "test" -> test() + else -> { + r.putString("reason", "unknown method") + false + } + } + }.getOrElse { + r.putString("reason", it.stackTraceToString()) + false + } + + r.putBoolean("result", b) + return r + } +} diff --git a/scripts/avd_magisk.sh b/scripts/avd_magisk.sh index 62f948047..c76ec44b2 100755 --- a/scripts/avd_magisk.sh +++ b/scripts/avd_magisk.sh @@ -44,7 +44,7 @@ if [ -z "$FIRST_STAGE" ]; then fi fi -pm install -r $(pwd)/magisk.apk +pm install -r -g $(pwd)/magisk.apk # Extract files from APK unzip -oj magisk.apk 'assets/util_functions.sh' 'assets/stub.apk' diff --git a/scripts/avd_test.sh b/scripts/avd_test.sh index 124ef2eca..fb74ddff6 100755 --- a/scripts/avd_test.sh +++ b/scripts/avd_test.sh @@ -3,7 +3,7 @@ emu="$ANDROID_SDK_ROOT/emulator/emulator" avd="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager" sdk="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" -emu_args='-no-window -gpu swiftshader_indirect -read-only -no-snapshot -noaudio -no-boot-anim -show-kernel' +emu_args='-no-window -gpu swiftshader_indirect -read-only -no-snapshot -no-audio -no-boot-anim -show-kernel' boot_timeout=600 emu_pid= @@ -20,8 +20,16 @@ type='google_apis' api_list='23 26 28 29 34' +print_title() { + echo -e "\n\033[44;39m${1}\033[0m\n" +} + +print_error() { + echo -e "\n\033[41;39m${1}\033[0m\n" +} + cleanup() { - echo -e '\n\033[41;39m! An error occurred\033[0m\n' + print_error "! An error occurred when testing $pkg" for api in $api_list; do set_api_env $api @@ -77,16 +85,43 @@ restore_avd() { fi } -test_emu() { - "$emu" @test $emu_args & - emu_pid=$! - timeout $boot_timeout bash -c wait_for_boot & +wait_emu() { + local wait_fn=$1 + local which_pid + + timeout $boot_timeout bash -c $wait_fn & local wait_pid=$! - # Handle the case when emulator dies with error - wait -n $emu_pid $wait_pid + # Handle the case when emulator dies earlier than wait + wait -p which_pid -n $emu_pid $wait_pid + [ $which_pid -eq $wait_pid ] +} + +test_emu() { + local variant=$1 + + print_title "* Testing $pkg ($variant)" + + "$emu" @test $emu_args & + emu_pid=$! + wait_emu wait_for_boot adb shell magisk -v + + # Install the Magisk app + adb install -r -g out/app-${variant}.apk + adb shell appops set com.topjohnwu.magisk REQUEST_INSTALL_PACKAGES allow + + # Use the app to run setup and reboot + adb shell echo "'content call --uri content://com.topjohnwu.magisk.provider --method setup'" \| /system/xbin/su \ + | tee /dev/fd/2 | grep -q 'result=true' + adb reboot + wait_emu wait_for_boot + + # Run app tests + adb shell echo "'content call --uri content://com.topjohnwu.magisk.provider --method test'" \| /system/xbin/su \ + | tee /dev/fd/2 | grep -q 'result=true' + adb shell echo "'su -c id'" \| /system/xbin/su 2000 | tee /dev/fd/2 | grep -q 'uid=0' } @@ -96,27 +131,27 @@ run_test() { set_api_env $api # Setup emulator - echo -e "\n\033[44;39m* Testing $pkg\033[0m\n" "$sdk" $pkg echo no | "$avd" create avd -f -n test -k $pkg # Launch stock emulator + print_title "* Launching $pkg" restore_avd "$emu" @test $emu_args & emu_pid=$! - timeout $boot_timeout bash -c wait_for_bootanim + wait_emu wait_for_bootanim # Patch and test debug build ./build.py avd_patch -s "$ramdisk" kill -INT $emu_pid wait $emu_pid - test_emu + test_emu debug # Re-patch and test release build ./build.py -r avd_patch -s "$ramdisk" kill -INT $emu_pid wait $emu_pid - test_emu + test_emu release # Cleanup kill -INT $emu_pid