mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 18:47:38 +00:00
Add new tests for app hiding
This commit is contained in:
parent
820710c086
commit
5885b8c20d
11
app/core/proguard-rules.pro
vendored
11
app/core/proguard-rules.pro
vendored
@ -37,13 +37,4 @@
|
||||
-flattenpackagehierarchy
|
||||
-allowaccessmodification
|
||||
|
||||
-dontwarn org.junit.Assert
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLParameters
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
|
||||
-dontwarn org.commonmark.ext.gfm.strikethrough.Strikethrough
|
||||
-dontwarn org.conscrypt.Conscrypt*
|
||||
-dontwarn org.conscrypt.ConscryptHostnameVerifier
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
|
||||
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
|
||||
-dontwarn org.openjsse.net.ssl.OpenJSSE
|
||||
-dontwarn org.junit.**
|
||||
|
@ -1,50 +0,0 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import androidx.annotation.Keep
|
||||
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.CallbackList
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertTrue
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* We implement all test logic here and mark it with @Keep so that our instrumentation package
|
||||
* can properly run tests on fully obfuscated release APKs.
|
||||
*/
|
||||
@Keep
|
||||
object TestImpl {
|
||||
|
||||
fun before() {
|
||||
assertTrue("Should have root access", Shell.getShell().isRoot)
|
||||
// Make sure the root service is running
|
||||
RootUtils.Connection.await()
|
||||
}
|
||||
|
||||
object LogList : CallbackList<String>(Runnable::run) {
|
||||
override fun onAddElement(e: String) {
|
||||
Timber.i(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun setupMagisk() {
|
||||
runBlocking {
|
||||
MagiskInstaller.Emulator(LogList, LogList).exec()
|
||||
}
|
||||
}
|
||||
|
||||
fun setupShellGrantTest() {
|
||||
// Clear existing grant for ADB shell
|
||||
runBlocking {
|
||||
ServiceLocator.policyDB.delete(2000)
|
||||
Config.suAutoResponse = Config.Value.SU_AUTO_ALLOW
|
||||
Config.prefs.edit().commit()
|
||||
}
|
||||
}
|
||||
|
||||
fun testZygisk() {
|
||||
assertTrue("Zygisk should be enabled", Info.isZygiskEnabled)
|
||||
}
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
package com.topjohnwu.magisk.core.model.su
|
||||
|
||||
class SuPolicy(val uid: Int) {
|
||||
class SuPolicy(
|
||||
val uid: Int,
|
||||
var policy: Int = INTERACTIVE,
|
||||
var until: Long = -1L,
|
||||
var logging: Boolean = true,
|
||||
var notification: Boolean = true,
|
||||
) {
|
||||
companion object {
|
||||
const val INTERACTIVE = 0
|
||||
const val DENY = 1
|
||||
const val ALLOW = 2
|
||||
}
|
||||
|
||||
var policy: Int = INTERACTIVE
|
||||
var until: Long = -1L
|
||||
var logging: Boolean = true
|
||||
var notification: Boolean = true
|
||||
|
||||
fun toMap(): MutableMap<String, Any> = mutableMapOf(
|
||||
"uid" to uid,
|
||||
"policy" to policy,
|
||||
|
@ -62,7 +62,7 @@ class SuRequestHandler(
|
||||
return false
|
||||
}
|
||||
output = File(fifo)
|
||||
policy = SuPolicy(uid)
|
||||
policy = policyDB.fetch(uid) ?: SuPolicy(uid)
|
||||
try {
|
||||
pkgInfo = pm.getPackageInfo(uid, pid) ?: PackageInfo().apply {
|
||||
val name = pm.getNameForUid(uid) ?: throw PackageManager.NameNotFoundException()
|
||||
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||
import android.app.ActivityOptions
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.StubApk
|
||||
@ -25,7 +26,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.security.SecureRandom
|
||||
@ -36,6 +36,7 @@ object AppMigration {
|
||||
private const val ALPHA = "abcdefghijklmnopqrstuvwxyz"
|
||||
private const val ALPHADOTS = "$ALPHA....."
|
||||
private const val ANDROID_MANIFEST = "AndroidManifest.xml"
|
||||
private const val TEST_PKG_NAME = "$APP_PACKAGE_NAME.test"
|
||||
|
||||
// Some arbitrary limit
|
||||
const val MAX_LABEL_LENGTH = 32
|
||||
@ -131,21 +132,15 @@ object AppMigration {
|
||||
val je = jar.getJarEntry(ANDROID_MANIFEST)
|
||||
val xml = AXML(jar.getRawData(je))
|
||||
val generator = classNameGenerator()
|
||||
|
||||
if (!xml.patchStrings {
|
||||
for (i in it.indices) {
|
||||
val s = it[i]
|
||||
if (s.contains(APP_PACKAGE_NAME)) {
|
||||
it[i] = s.replace(APP_PACKAGE_NAME, pkg)
|
||||
} else if (s.contains(PLACEHOLDER)) {
|
||||
it[i] = generator.next()
|
||||
} else if (s == origLabel) {
|
||||
it[i] = label.toString()
|
||||
}
|
||||
val p = xml.patchStrings {
|
||||
when {
|
||||
it.contains(APP_PACKAGE_NAME) -> it.replace(APP_PACKAGE_NAME, pkg)
|
||||
it.contains(PLACEHOLDER) -> generator.next()
|
||||
it == origLabel -> label.toString()
|
||||
else -> it
|
||||
}
|
||||
}) {
|
||||
return false
|
||||
}
|
||||
if (!p) return false
|
||||
|
||||
// Write apk changes
|
||||
jar.getOutputStream(je).use { it.write(xml.bytes) }
|
||||
@ -159,40 +154,83 @@ object AppMigration {
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchApp(activity: Activity, pkg: String) {
|
||||
val intent = activity.packageManager.getLaunchIntentForPackage(pkg) ?: return
|
||||
private fun patchTest(apk: File, out: File, pkg: String): Boolean {
|
||||
try {
|
||||
JarMap.open(apk, true).use { jar ->
|
||||
val je = jar.getJarEntry(ANDROID_MANIFEST)
|
||||
val xml = AXML(jar.getRawData(je))
|
||||
val p = xml.patchStrings {
|
||||
when (it) {
|
||||
APP_PACKAGE_NAME -> pkg
|
||||
TEST_PKG_NAME -> "$pkg.test"
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
if (!p) return false
|
||||
|
||||
// Write apk changes
|
||||
jar.getOutputStream(je).use { it.write(xml.bytes) }
|
||||
val keys = Keygen()
|
||||
out.outputStream().use { SignApk.sign(keys.cert, keys.key, jar, it) }
|
||||
return true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchApp(context: Context, pkg: String) {
|
||||
val intent = context.packageManager.getLaunchIntentForPackage(pkg) ?: return
|
||||
intent.putExtra(Const.Key.PREV_CONFIG, Config.toBundle())
|
||||
val options = ActivityOptions.makeBasic()
|
||||
if (Build.VERSION.SDK_INT >= 34) {
|
||||
options.setShareIdentityEnabled(true)
|
||||
}
|
||||
activity.startActivity(intent, options.toBundle())
|
||||
activity.finish()
|
||||
context.startActivity(intent, options.toBundle())
|
||||
if (context is Activity) {
|
||||
context.finish()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun patchAndHide(activity: Activity, label: String): Boolean {
|
||||
val stub = File(activity.cacheDir, "stub.apk")
|
||||
suspend fun patchAndHide(context: Context, label: String, pkg: String? = null): Boolean {
|
||||
val stub = File(context.cacheDir, "stub.apk")
|
||||
try {
|
||||
activity.assets.open("stub.apk").writeTo(stub)
|
||||
context.assets.open("stub.apk").writeTo(stub)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
|
||||
// Generate a new random package name and signature
|
||||
val repack = File(activity.cacheDir, "patched.apk")
|
||||
val pkg = genPackageName()
|
||||
// Generate a new random signature and package name if needed
|
||||
val pkg = pkg ?: genPackageName()
|
||||
Config.keyStoreRaw = ""
|
||||
|
||||
if (!patch(activity, stub, FileOutputStream(repack), pkg, label))
|
||||
return false
|
||||
// Check and patch the test APK
|
||||
try {
|
||||
val info = context.packageManager.getApplicationInfo(TEST_PKG_NAME, 0)
|
||||
val testApk = File(info.sourceDir)
|
||||
val testRepack = File(context.cacheDir, "test.apk")
|
||||
if (!patchTest(testApk, testRepack, pkg))
|
||||
return false
|
||||
val cmd = "adb_pm_install $testRepack $pkg.test"
|
||||
if (!Shell.cmd(cmd).exec().isSuccess)
|
||||
return false
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
}
|
||||
|
||||
val repack = File(context.cacheDir, "patched.apk")
|
||||
repack.outputStream().use {
|
||||
if (!patch(context, stub, it, pkg, label))
|
||||
return false
|
||||
}
|
||||
|
||||
// Install and auto launch app
|
||||
val cmd = "adb_pm_install $repack $pkg"
|
||||
if (Shell.cmd(cmd).exec().isSuccess) {
|
||||
Config.suManager = pkg
|
||||
Shell.cmd("touch $AppApkPath").exec()
|
||||
launchApp(activity, pkg)
|
||||
launchApp(context, pkg)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -216,6 +254,18 @@ object AppMigration {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun restoreApp(context: Context): Boolean {
|
||||
val apk = StubApk.current(context)
|
||||
val cmd = "adb_pm_install $apk $APP_PACKAGE_NAME"
|
||||
if (Shell.cmd(cmd).await().isSuccess) {
|
||||
Config.suManager = ""
|
||||
Shell.cmd("touch $AppApkPath").exec()
|
||||
launchApp(context, APP_PACKAGE_NAME)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun restore(activity: Activity) {
|
||||
val dialog = android.app.ProgressDialog(activity).apply {
|
||||
@ -224,13 +274,7 @@ object AppMigration {
|
||||
setCancelable(false)
|
||||
show()
|
||||
}
|
||||
val apk = StubApk.current(activity)
|
||||
val cmd = "adb_pm_install $apk $APP_PACKAGE_NAME"
|
||||
if (Shell.cmd(cmd).await().isSuccess) {
|
||||
Config.suManager = ""
|
||||
Shell.cmd("touch $AppApkPath").exec()
|
||||
launchApp(activity, APP_PACKAGE_NAME)
|
||||
} else {
|
||||
if (!restoreApp(activity)) {
|
||||
activity.toast(R.string.failure, Toast.LENGTH_LONG)
|
||||
}
|
||||
dialog.dismiss()
|
||||
|
@ -29,7 +29,7 @@ class AXML(b: ByteArray) {
|
||||
* Followed by an array of uint32_t with size = number of strings
|
||||
* Each entry points to an offset into the string data
|
||||
*/
|
||||
fun patchStrings(patchFn: (Array<String>) -> Unit): Boolean {
|
||||
fun patchStrings(mapFn: (String) -> String): Boolean {
|
||||
val buffer = ByteBuffer.wrap(bytes).order(LITTLE_ENDIAN)
|
||||
|
||||
fun findStringPool(): Int {
|
||||
@ -65,7 +65,9 @@ class AXML(b: ByteArray) {
|
||||
}
|
||||
|
||||
val strArr = strList.toTypedArray()
|
||||
patchFn(strArr)
|
||||
for (i in strArr.indices) {
|
||||
strArr[i] = mapFn(strArr[i])
|
||||
}
|
||||
|
||||
// Write everything before string data, will patch values later
|
||||
val baos = RawByteStream()
|
||||
|
@ -0,0 +1,87 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.topjohnwu.magisk.core.BuildConfig.APP_PACKAGE_NAME
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.superuser.CallbackList
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import timber.log.Timber
|
||||
|
||||
@Keep
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class Environment {
|
||||
|
||||
companion object {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun before() = MagiskAppTest.before()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupMagisk() {
|
||||
val log = object : CallbackList<String>(Runnable::run) {
|
||||
override fun onAddElement(e: String) {
|
||||
Timber.i(e)
|
||||
}
|
||||
}
|
||||
runBlocking {
|
||||
assertTrue(
|
||||
"Magisk setup failed",
|
||||
MagiskInstaller.Emulator(log, log).exec()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupShellGrantTest() {
|
||||
runBlocking {
|
||||
// Inject an undetermined + mute logging policy for ADB shell
|
||||
val policy = SuPolicy(
|
||||
uid = 2000,
|
||||
logging = false,
|
||||
notification = false,
|
||||
until = 0L
|
||||
)
|
||||
ServiceLocator.policyDB.update(policy)
|
||||
// Bypass the need to actually show a dialog
|
||||
Config.suAutoResponse = Config.Value.SU_AUTO_ALLOW
|
||||
Config.prefs.edit().commit()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupAppHide() {
|
||||
runBlocking {
|
||||
assertTrue(
|
||||
"App hiding failed",
|
||||
AppMigration.patchAndHide(
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext,
|
||||
label = "Settings",
|
||||
pkg = "repackaged.$APP_PACKAGE_NAME"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupAppRestore() {
|
||||
runBlocking {
|
||||
assertTrue(
|
||||
"App restoration failed",
|
||||
AppMigration.restoreApp(
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.utils.RootUtils
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@Keep
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MagiskAppTest {
|
||||
|
||||
companion object {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun before() {
|
||||
assertTrue("Should have root access", Shell.getShell().isRoot)
|
||||
// Make sure the root service is running
|
||||
RootUtils.Connection.await()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testZygisk() {
|
||||
assertTrue("Zygisk should be enabled", Info.isZygiskEnabled)
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import dalvik.system.BaseDexClassLoader;
|
||||
public class DynamicClassLoader extends BaseDexClassLoader {
|
||||
|
||||
public DynamicClassLoader(File apk) {
|
||||
this(apk, getSystemClassLoader());
|
||||
this(apk, DynamicClassLoader.class.getClassLoader());
|
||||
}
|
||||
|
||||
public DynamicClassLoader(File apk, ClassLoader parent) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
</application>
|
||||
|
||||
<instrumentation
|
||||
android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||
android:name="com.topjohnwu.magisk.test.TestRunner"
|
||||
android:targetPackage="com.topjohnwu.magisk"
|
||||
android:label="Tests for Magisk" />
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.topjohnwu.magisk.core.TestImpl
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class Environment {
|
||||
|
||||
companion object {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun before() {
|
||||
TestImpl.before()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupMagisk() {
|
||||
TestImpl.setupMagisk()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setupShellGrantTest() {
|
||||
TestImpl.setupShellGrantTest()
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.topjohnwu.magisk.core.TestImpl
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MagiskAppTest {
|
||||
|
||||
companion object {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun before() {
|
||||
TestImpl.before()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testZygisk() {
|
||||
TestImpl.testZygisk()
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.topjohnwu.magisk.test
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnitRunner
|
||||
|
||||
class TestRunner : AndroidJUnitRunner() {
|
||||
override fun onCreate(arguments: Bundle) {
|
||||
// Force using the target context's classloader to run tests
|
||||
arguments.putString("classLoader", TestClassLoader::class.java.name)
|
||||
super.onCreate(arguments)
|
||||
}
|
||||
}
|
||||
|
||||
private val targetClassLoader inline get() =
|
||||
InstrumentationRegistry.getInstrumentation().targetContext.classLoader
|
||||
|
||||
class TestClassLoader : ClassLoader(targetClassLoader)
|
@ -80,7 +80,7 @@ void su_info::check_db() {
|
||||
}
|
||||
|
||||
// We need to check our manager
|
||||
if (access.log || access.notify) {
|
||||
if (access.policy == QUERY || access.log || access.notify) {
|
||||
mgr_uid = get_manager(to_user_id(eval_uid), &mgr_pkg, true);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ export PATH="$PATH:$ANDROID_HOME/platform-tools"
|
||||
emu="$ANDROID_HOME/emulator/emulator"
|
||||
sdk="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager"
|
||||
avd="$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager"
|
||||
test_pkg='com.topjohnwu.magisk.test'
|
||||
|
||||
boot_timeout=600
|
||||
|
||||
@ -24,14 +23,27 @@ print_error() {
|
||||
echo -e "\n\033[41;39m${1}\033[0m\n"
|
||||
}
|
||||
|
||||
run_instrument_tests() {
|
||||
local out=$(adb shell am instrument -w \
|
||||
--user 0 \
|
||||
-e class "$1" \
|
||||
com.topjohnwu.magisk.test/androidx.test.runner.AndroidJUnitRunner)
|
||||
# $1 = TestClass#method
|
||||
# $2: boolean = isRepackaged
|
||||
run_instrument_test() {
|
||||
local test_pkg
|
||||
if [ -n "$2" -a $2 ]; then
|
||||
test_pkg="repackaged.com.topjohnwu.magisk.test"
|
||||
else
|
||||
test_pkg=com.topjohnwu.magisk.test
|
||||
fi
|
||||
local out=$(adb shell am instrument -w --user 0 \
|
||||
-e class "com.topjohnwu.magisk.test.$1" \
|
||||
"$test_pkg/com.topjohnwu.magisk.test.TestRunner")
|
||||
grep -q 'OK (' <<< "$out"
|
||||
}
|
||||
|
||||
# $1 = pkg
|
||||
wait_for_pm() {
|
||||
sleep 5
|
||||
adb shell pm uninstall $1 || true
|
||||
}
|
||||
|
||||
test_setup() {
|
||||
local variant=$1
|
||||
adb shell 'PATH=$PATH:/debug_ramdisk magisk -v'
|
||||
@ -43,14 +55,34 @@ test_setup() {
|
||||
adb install -r -g out/test-${variant}.apk
|
||||
|
||||
# Run setup through the test app
|
||||
run_instrument_tests "$test_pkg.Environment#setupMagisk"
|
||||
run_instrument_test 'Environment#setupMagisk'
|
||||
}
|
||||
|
||||
test_app() {
|
||||
# Run app tests
|
||||
run_instrument_tests "$test_pkg.MagiskAppTest"
|
||||
run_instrument_test 'MagiskAppTest'
|
||||
|
||||
# Test shell su request
|
||||
run_instrument_tests "$test_pkg.Environment#setupShellGrantTest"
|
||||
run_instrument_test 'Environment#setupShellGrantTest'
|
||||
adb shell /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||
adb shell am force-stop com.topjohnwu.magisk
|
||||
|
||||
# Test app hiding
|
||||
run_instrument_test 'Environment#setupAppHide'
|
||||
wait_for_pm com.topjohnwu.magisk
|
||||
|
||||
# Make sure it still works
|
||||
run_instrument_test 'MagiskAppTest' true
|
||||
|
||||
# Test shell su request
|
||||
run_instrument_test 'Environment#setupShellGrantTest' true
|
||||
adb shell /system/xbin/su 2000 su -c id | tee /dev/fd/2 | grep -q 'uid=0'
|
||||
adb shell am force-stop repackaged.com.topjohnwu.magisk
|
||||
|
||||
# Test app restore
|
||||
run_instrument_test 'Environment#setupAppRestore' true
|
||||
wait_for_pm repackaged.com.topjohnwu.magisk
|
||||
|
||||
# Make sure it still works
|
||||
run_instrument_test 'MagiskAppTest'
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user