Allow component classname obfuscation

This commit is contained in:
topjohnwu 2019-10-16 04:38:31 -04:00
parent c7033dd757
commit 43bda2d4a4
22 changed files with 132 additions and 63 deletions

View File

@ -2,6 +2,14 @@ package a;
import com.topjohnwu.magisk.App; import com.topjohnwu.magisk.App;
import java.util.Map;
public class e extends App { public class e extends App {
/* stub */ public e() {
super();
}
public e(Map<String, String> map) {
super(map);
}
} }

View File

@ -23,7 +23,12 @@ import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import timber.log.Timber import timber.log.Timber
open class App : Application() { open class App() : Application() {
constructor(map: Map<String, String>) : this() {
isRunningAsStub = true
ClassMap.componentMap = map
}
init { init {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)

View File

@ -1,5 +1,8 @@
package com.topjohnwu.magisk package com.topjohnwu.magisk
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import com.topjohnwu.magisk.model.download.DownloadService import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.receiver.GeneralReceiver import com.topjohnwu.magisk.model.receiver.GeneralReceiver
import com.topjohnwu.magisk.model.update.UpdateCheckService import com.topjohnwu.magisk.model.update.UpdateCheckService
@ -9,7 +12,8 @@ import com.topjohnwu.magisk.ui.flash.FlashActivity
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
object ClassMap { object ClassMap {
private val map = mapOf(
private val classMap = mapOf(
App::class.java to a.e::class.java, App::class.java to a.e::class.java,
MainActivity::class.java to a.b::class.java, MainActivity::class.java to a.b::class.java,
SplashActivity::class.java to a.c::class.java, SplashActivity::class.java to a.c::class.java,
@ -20,7 +24,21 @@ object ClassMap {
SuRequestActivity::class.java to a.m::class.java SuRequestActivity::class.java to a.m::class.java
) )
operator fun <T : Class<*>>get(c: Class<*>): T { // This will be set if running as guest app
return map.getOrElse(c) { throw IllegalArgumentException() } as T var componentMap: Map<String, String>? = null
}
operator fun get(c: Class<*>) = classMap.getOrElse(c) { throw IllegalArgumentException() }
}
fun Class<*>.cmp(pkg: String = BuildConfig.APPLICATION_ID): ComponentName {
val name = ClassMap[this].name
return ComponentName(pkg, ClassMap.componentMap?.get(name) ?: name)
}
fun Context.intent(c: Class<*>): Intent {
val cls = ClassMap[c]
return ClassMap.componentMap?.let {
val className = it.getOrElse(cls.name) { cls.name }
Intent().setComponent(ComponentName(this, className))
} ?: Intent(this, cls)
} }

View File

@ -7,11 +7,11 @@ import android.content.Intent
import android.os.Build import android.os.Build
import android.webkit.MimeTypeMap import android.webkit.MimeTypeMap
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.chooser import com.topjohnwu.magisk.extensions.chooser
import com.topjohnwu.magisk.extensions.exists import com.topjohnwu.magisk.extensions.exists
import com.topjohnwu.magisk.extensions.provide import com.topjohnwu.magisk.extensions.provide
import com.topjohnwu.magisk.intent
import com.topjohnwu.magisk.model.entity.internal.Configuration.* import com.topjohnwu.magisk.model.entity.internal.Configuration.*
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
@ -140,8 +140,7 @@ open class DownloadService : RemoteFileService() {
inline operator fun invoke(context: Context, argBuilder: Builder.() -> Unit) { inline operator fun invoke(context: Context, argBuilder: Builder.() -> Unit) {
val app = context.applicationContext val app = context.applicationContext
val builder = Builder().apply(argBuilder) val builder = Builder().apply(argBuilder)
val intent = Intent(app, ClassMap[DownloadService::class.java]) val intent = app.intent(DownloadService::class.java).putExtra(ARG_URL, builder.subject)
.putExtra(ARG_URL, builder.subject)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
app.startForegroundService(intent) app.startForegroundService(intent)

View File

@ -1,10 +1,9 @@
package com.topjohnwu.magisk.model.download package com.topjohnwu.magisk.model.download
import android.content.ComponentName
import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.cmp
import com.topjohnwu.magisk.extensions.DynamicClassLoader import com.topjohnwu.magisk.extensions.DynamicClassLoader
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
@ -52,9 +51,7 @@ private fun RemoteFileService.restore(apk: File, id: Int) {
// Make it world readable // Make it world readable
apk.setReadable(true, false) apk.setReadable(true, false)
if (Shell.su("pm install $apk").exec().isSuccess) { if (Shell.su("pm install $apk").exec().isSuccess) {
val component = ComponentName(BuildConfig.APPLICATION_ID, Utils.rmAndLaunch(packageName, SplashActivity::class.java.cmp())
ClassMap.get<Class<*>>(SplashActivity::class.java).name)
Utils.rmAndLaunch(packageName, component)
} }
} }

View File

@ -2,7 +2,6 @@ package com.topjohnwu.magisk.model.receiver
import android.content.ContextWrapper import android.content.ContextWrapper
import android.content.Intent import android.content.Intent
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info import com.topjohnwu.magisk.Info
@ -10,6 +9,7 @@ import com.topjohnwu.magisk.base.BaseReceiver
import com.topjohnwu.magisk.data.database.PolicyDao import com.topjohnwu.magisk.data.database.PolicyDao
import com.topjohnwu.magisk.data.database.base.su import com.topjohnwu.magisk.data.database.base.su
import com.topjohnwu.magisk.extensions.reboot import com.topjohnwu.magisk.extensions.reboot
import com.topjohnwu.magisk.intent
import com.topjohnwu.magisk.model.download.DownloadService import com.topjohnwu.magisk.model.download.DownloadService
import com.topjohnwu.magisk.model.entity.ManagerJson import com.topjohnwu.magisk.model.entity.ManagerJson
import com.topjohnwu.magisk.model.entity.internal.Configuration import com.topjohnwu.magisk.model.entity.internal.Configuration
@ -51,7 +51,7 @@ open class GeneralReceiver : BaseReceiver() {
} }
when (action) { when (action) {
REQUEST -> { REQUEST -> {
val i = Intent(context, ClassMap[SuRequestActivity::class.java]) val i = context.intent(SuRequestActivity::class.java)
.setAction(action) .setAction(action)
.putExtra("socket", intent.getStringExtra("socket")) .putExtra("socket", intent.getStringExtra("socket"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

View File

@ -7,11 +7,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import com.ncapdevi.fragnav.FragNavController import com.ncapdevi.fragnav.FragNavController
import com.ncapdevi.fragnav.FragNavTransactionOptions import com.ncapdevi.fragnav.FragNavTransactionOptions
import com.topjohnwu.magisk.ClassMap import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const.Key.OPEN_SECTION import com.topjohnwu.magisk.Const.Key.OPEN_SECTION
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.base.BaseActivity import com.topjohnwu.magisk.base.BaseActivity
import com.topjohnwu.magisk.base.BaseFragment import com.topjohnwu.magisk.base.BaseFragment
import com.topjohnwu.magisk.databinding.ActivityMainBinding import com.topjohnwu.magisk.databinding.ActivityMainBinding
@ -61,7 +58,7 @@ open class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(), Na
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
if (!SplashActivity.DONE) { if (!SplashActivity.DONE) {
startActivity(Intent(this, ClassMap[SplashActivity::class.java])) startActivity(intent(SplashActivity::class.java))
finish() finish()
} }

View File

@ -2,7 +2,6 @@ package com.topjohnwu.magisk.ui
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
@ -62,7 +61,7 @@ open class SplashActivity : Activity() {
// Setup shortcuts // Setup shortcuts
Shortcuts.setup(this) Shortcuts.setup(this)
val intent = Intent(this, ClassMap[MainActivity::class.java]) val intent = intent(MainActivity::class.java)
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION)) intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION))
DONE = true DONE = true
startActivity(intent) startActivity(intent)

View File

@ -6,12 +6,12 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.base.BaseActivity import com.topjohnwu.magisk.base.BaseActivity
import com.topjohnwu.magisk.databinding.ActivityFlashBinding import com.topjohnwu.magisk.databinding.ActivityFlashBinding
import com.topjohnwu.magisk.extensions.snackbar import com.topjohnwu.magisk.extensions.snackbar
import com.topjohnwu.magisk.intent
import com.topjohnwu.magisk.model.events.BackPressEvent import com.topjohnwu.magisk.model.events.BackPressEvent
import com.topjohnwu.magisk.model.events.PermissionEvent import com.topjohnwu.magisk.model.events.PermissionEvent
import com.topjohnwu.magisk.model.events.SnackbarEvent import com.topjohnwu.magisk.model.events.SnackbarEvent
@ -60,7 +60,7 @@ open class FlashActivity : BaseActivity<FlashViewModel, ActivityFlashBinding>()
companion object { companion object {
private fun intent(context: Context) = Intent(context, ClassMap[FlashActivity::class.java]) private fun intent(context: Context) = context.intent(FlashActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
private fun intent(context: Context, file: File) = intent(context).setData(file.toUri()) private fun intent(context: Context, file: File) = intent(context).setData(file.toUri())

View File

@ -14,6 +14,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.base.BaseFragment import com.topjohnwu.magisk.base.BaseFragment
import com.topjohnwu.magisk.databinding.FragmentModulesBinding import com.topjohnwu.magisk.databinding.FragmentModulesBinding
import com.topjohnwu.magisk.extensions.reboot import com.topjohnwu.magisk.extensions.reboot
import com.topjohnwu.magisk.intent
import com.topjohnwu.magisk.model.events.OpenFilePickerEvent import com.topjohnwu.magisk.model.events.OpenFilePickerEvent
import com.topjohnwu.magisk.model.events.ViewEvent import com.topjohnwu.magisk.model.events.ViewEvent
import com.topjohnwu.magisk.ui.flash.FlashActivity import com.topjohnwu.magisk.ui.flash.FlashActivity
@ -28,7 +29,7 @@ class ModulesFragment : BaseFragment<ModuleViewModel, FragmentModulesBinding>()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) { if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
// Get the URI of the selected file // Get the URI of the selected file
val intent = Intent(activity, ClassMap[FlashActivity::class.java]) val intent = activity.intent(FlashActivity::class.java)
intent.setData(data.data).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP) intent.setData(data.data).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP)
startActivity(intent) startActivity(intent)
} }

View File

@ -1,6 +1,5 @@
package com.topjohnwu.magisk.utils package com.topjohnwu.magisk.utils
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.widget.Toast import android.widget.Toast
import com.topjohnwu.magisk.* import com.topjohnwu.magisk.*
@ -102,8 +101,7 @@ object PatchAPK {
Config.suManager = pkg Config.suManager = pkg
Config.export() Config.export()
Utils.rmAndLaunch(BuildConfig.APPLICATION_ID, Utils.rmAndLaunch(BuildConfig.APPLICATION_ID, SplashActivity::class.java.cmp(pkg))
ComponentName(pkg, ClassMap.get<Class<*>>(SplashActivity::class.java).name))
return true return true
} }

View File

@ -46,7 +46,7 @@ object Utils {
.setRequiresDeviceIdle(true) .setRequiresDeviceIdle(true)
.build() .build()
val request = PeriodicWorkRequest val request = PeriodicWorkRequest
.Builder(ClassMap[UpdateCheckService::class.java], 12, TimeUnit.HOURS) .Builder(ClassMap[UpdateCheckService::class.java] as Class<Worker>, 12, TimeUnit.HOURS)
.setConstraints(constraints) .setConstraints(constraints)
.build() .build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork( WorkManager.getInstance(context).enqueueUniquePeriodicWork(

View File

@ -4,15 +4,11 @@ import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Build import android.os.Build
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import com.topjohnwu.magisk.ClassMap import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.extensions.get import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.model.receiver.GeneralReceiver import com.topjohnwu.magisk.model.receiver.GeneralReceiver
import com.topjohnwu.magisk.ui.SplashActivity import com.topjohnwu.magisk.ui.SplashActivity
@ -34,10 +30,10 @@ object Notifications {
} }
fun magiskUpdate(context: Context) { fun magiskUpdate(context: Context) {
val intent = Intent(context, ClassMap[SplashActivity::class.java]) val intent = context.intent(SplashActivity::class.java)
intent.putExtra(Const.Key.OPEN_SECTION, "magisk") .putExtra(Const.Key.OPEN_SECTION, "magisk")
val stackBuilder = TaskStackBuilder.create(context) val stackBuilder = TaskStackBuilder.create(context)
stackBuilder.addParentStack(ClassMap.get<Class<*>>(SplashActivity::class.java)) stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName))
stackBuilder.addNextIntent(intent) stackBuilder.addNextIntent(intent)
val pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, val pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT) PendingIntent.FLAG_UPDATE_CURRENT)
@ -54,9 +50,9 @@ object Notifications {
} }
fun managerUpdate(context: Context) { fun managerUpdate(context: Context) {
val intent = Intent(context, ClassMap[GeneralReceiver::class.java]) val intent = context.intent(GeneralReceiver::class.java)
intent.action = Const.Key.BROADCAST_MANAGER_UPDATE .setAction(Const.Key.BROADCAST_MANAGER_UPDATE)
intent.putExtra(Const.Key.INTENT_SET_APP, Info.remote.app) .putExtra(Const.Key.INTENT_SET_APP, Info.remote.app)
val pendingIntent = PendingIntent.getBroadcast(context, val pendingIntent = PendingIntent.getBroadcast(context,
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT) Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
@ -73,7 +69,7 @@ object Notifications {
} }
fun dtboPatched(context: Context) { fun dtboPatched(context: Context) {
val intent = Intent(context, ClassMap[GeneralReceiver::class.java]) val intent = context.intent(GeneralReceiver::class.java)
.setAction(Const.Key.BROADCAST_REBOOT) .setAction(Const.Key.BROADCAST_REBOOT)
val pendingIntent = PendingIntent.getBroadcast(context, val pendingIntent = PendingIntent.getBroadcast(context,
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT) Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)

View File

@ -25,10 +25,11 @@ object Shortcuts {
private fun getShortCuts(context: Context): List<ShortcutInfo> { private fun getShortCuts(context: Context): List<ShortcutInfo> {
val shortCuts = mutableListOf<ShortcutInfo>() val shortCuts = mutableListOf<ShortcutInfo>()
val root = Shell.rootAccess() val root = Shell.rootAccess()
val intent = context.intent(SplashActivity::class.java)
if (Utils.showSuperUser()) { if (Utils.showSuperUser()) {
shortCuts.add(ShortcutInfo.Builder(context, "superuser") shortCuts.add(ShortcutInfo.Builder(context, "superuser")
.setShortLabel(context.getString(R.string.superuser)) .setShortLabel(context.getString(R.string.superuser))
.setIntent(Intent(context, ClassMap[SplashActivity::class.java]) .setIntent(Intent(intent)
.putExtra(Const.Key.OPEN_SECTION, "superuser") .putExtra(Const.Key.OPEN_SECTION, "superuser")
.setAction(Intent.ACTION_VIEW) .setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@ -39,7 +40,7 @@ object Shortcuts {
if (root && Config.magiskHide) { if (root && Config.magiskHide) {
shortCuts.add(ShortcutInfo.Builder(context, "magiskhide") shortCuts.add(ShortcutInfo.Builder(context, "magiskhide")
.setShortLabel(context.getString(R.string.magiskhide)) .setShortLabel(context.getString(R.string.magiskhide))
.setIntent(Intent(context, ClassMap[SplashActivity::class.java]) .setIntent(Intent(intent)
.putExtra(Const.Key.OPEN_SECTION, "magiskhide") .putExtra(Const.Key.OPEN_SECTION, "magiskhide")
.setAction(Intent.ACTION_VIEW) .setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@ -50,7 +51,7 @@ object Shortcuts {
if (!Config.coreOnly && root && Info.magiskVersionCode >= 0) { if (!Config.coreOnly && root && Info.magiskVersionCode >= 0) {
shortCuts.add(ShortcutInfo.Builder(context, "modules") shortCuts.add(ShortcutInfo.Builder(context, "modules")
.setShortLabel(context.getString(R.string.modules)) .setShortLabel(context.getString(R.string.modules))
.setIntent(Intent(context, ClassMap[SplashActivity::class.java]) .setIntent(Intent(intent)
.putExtra(Const.Key.OPEN_SECTION, "modules") .putExtra(Const.Key.OPEN_SECTION, "modules")
.setAction(Intent.ACTION_VIEW) .setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
@ -59,7 +60,7 @@ object Shortcuts {
.build()) .build())
shortCuts.add(ShortcutInfo.Builder(context, "downloads") shortCuts.add(ShortcutInfo.Builder(context, "downloads")
.setShortLabel(context.getString(R.string.downloads)) .setShortLabel(context.getString(R.string.downloads))
.setIntent(Intent(context, ClassMap[SplashActivity::class.java]) .setIntent(Intent(intent)
.putExtra(Const.Key.OPEN_SECTION, "downloads") .putExtra(Const.Key.OPEN_SECTION, "downloads")
.setAction(Intent.ACTION_VIEW) .setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))

View File

@ -16,8 +16,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<application <application
android:name="a.e" android:name="a.y"
android:appComponentFactory="a.a" android:appComponentFactory="a.x"
android:allowBackup="true" android:allowBackup="true"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning" > tools:ignore="UnusedAttribute,GoogleAppIndexingWarning" >
@ -25,7 +25,7 @@
<!-- Download Activity --> <!-- Download Activity -->
<activity <activity
android:name="a.c" android:name="a.z"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:theme="@style/SplashTheme"> android:theme="@style/SplashTheme">
<intent-filter> <intent-filter>
@ -37,23 +37,23 @@
<!-- Magisk Manager Components --> <!-- Magisk Manager Components -->
<activity <activity
android:name="a.b" android:name="a.o"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize"
android:exported="true" /> android:exported="true" />
<activity <activity
android:name="a.f" android:name="a.x"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="nosensor" /> android:screenOrientation="nosensor" />
<activity <activity
android:name="a.m" android:name="a.g"
android:directBootAware="true" android:directBootAware="true"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:exported="false" /> android:exported="false" />
<receiver <receiver
android:name="a.h" android:name="a.w"
android:directBootAware="true"> android:directBootAware="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.BOOT_COMPLETED" />
@ -68,7 +68,7 @@
</receiver> </receiver>
<service <service
android:name="a.j" android:name="a.v"
android:exported="false" /> android:exported="false" />
<meta-data <meta-data

View File

@ -0,0 +1,6 @@
package a;
import com.topjohnwu.magisk.dummy.DummyReceiver;
public class w extends DummyReceiver {
}

View File

@ -2,5 +2,5 @@ package a;
import com.topjohnwu.magisk.DelegateComponentFactory; import com.topjohnwu.magisk.DelegateComponentFactory;
public class a extends DelegateComponentFactory { public class x extends DelegateComponentFactory {
} }

View File

@ -2,5 +2,5 @@ package a;
import com.topjohnwu.magisk.DelegateApplication; import com.topjohnwu.magisk.DelegateApplication;
public class e extends DelegateApplication { public class y extends DelegateApplication {
} }

View File

@ -2,5 +2,5 @@ package a;
import com.topjohnwu.magisk.DownloadActivity; import com.topjohnwu.magisk.DownloadActivity;
public class c extends DownloadActivity { public class z extends DownloadActivity {
} }

View File

@ -0,0 +1,32 @@
package com.topjohnwu.magisk;
import java.util.HashMap;
import java.util.Map;
class ComponentMap {
private static Map<String, String> map = new HashMap<>(6);
// This mapping will be sent into the guest app
static Map<String, String> inverseMap;
static {
map.put(a.z.class.getName(), "a.c");
map.put("a.x", "a.f");
map.put("a.o", "a.b");
map.put("a.g", "a.m");
map.put(a.w.class.getName(), "a.h");
map.put("a.v", "a.j");
map.put("a.s", "androidx.work.impl.WorkManagerInitializer");
inverseMap = new HashMap<>(map.size());
for (Map.Entry<String, String> e : map.entrySet()) {
inverseMap.put(e.getValue(), e.getKey());
}
}
static String get(String name) {
String n = map.get(name);
return n != null ? n : name;
}
}

View File

@ -13,6 +13,7 @@ import com.topjohnwu.magisk.utils.DynamicClassLoader;
import java.io.File; import java.io.File;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map;
import static com.topjohnwu.magisk.DownloadActivity.TAG; import static com.topjohnwu.magisk.DownloadActivity.TAG;
@ -44,7 +45,8 @@ public class DelegateApplication extends Application {
Object df = cl.loadClass("a.a").newInstance(); Object df = cl.loadClass("a.a").newInstance();
// Create the delegate Application // Create the delegate Application
delegate = (Application) cl.loadClass("a.e").newInstance(); delegate = (Application) cl.loadClass("a.e").getConstructor(Map.class)
.newInstance(ComponentMap.inverseMap);
// Call attachBaseContext without ContextImpl to show it is being wrapped // Call attachBaseContext without ContextImpl to show it is being wrapped
Method m = ContextWrapper.class.getDeclaredMethod("attachBaseContext", Context.class); Method m = ContextWrapper.class.getDeclaredMethod("attachBaseContext", Context.class);

View File

@ -8,12 +8,15 @@ import android.app.Service;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.Intent; import android.content.Intent;
import android.util.Log;
import com.topjohnwu.magisk.dummy.DummyActivity; import com.topjohnwu.magisk.dummy.DummyActivity;
import com.topjohnwu.magisk.dummy.DummyProvider; import com.topjohnwu.magisk.dummy.DummyProvider;
import com.topjohnwu.magisk.dummy.DummyReceiver; import com.topjohnwu.magisk.dummy.DummyReceiver;
import com.topjohnwu.magisk.dummy.DummyService; import com.topjohnwu.magisk.dummy.DummyService;
import static com.topjohnwu.magisk.DownloadActivity.TAG;
@SuppressLint("NewApi") @SuppressLint("NewApi")
public class DelegateComponentFactory extends AppComponentFactory { public class DelegateComponentFactory extends AppComponentFactory {
@ -22,39 +25,45 @@ public class DelegateComponentFactory extends AppComponentFactory {
@Override @Override
public Application instantiateApplication(ClassLoader cl, String className) { public Application instantiateApplication(ClassLoader cl, String className) {
loader = cl; if (loader == null) loader = cl;
Log.d(TAG, className);
return new DelegateApplication(this); return new DelegateApplication(this);
} }
@Override @Override
public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) public Activity instantiateActivity(ClassLoader cl, String className, Intent intent)
throws ClassNotFoundException, IllegalAccessException, InstantiationException { throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Log.d(TAG, className);
if (delegate != null) if (delegate != null)
return delegate.instantiateActivity(loader, className, intent); return delegate.instantiateActivity(loader, ComponentMap.get(className), intent);
return create(className, DummyActivity.class); return create(className, DummyActivity.class);
} }
@Override @Override
public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent) public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent)
throws ClassNotFoundException, IllegalAccessException, InstantiationException { throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Log.d(TAG, className);
if (delegate != null) if (delegate != null)
return delegate.instantiateReceiver(loader, className, intent); return delegate.instantiateReceiver(loader, ComponentMap.get(className), intent);
return create(className, DummyReceiver.class); return create(className, DummyReceiver.class);
} }
@Override @Override
public Service instantiateService(ClassLoader cl, String className, Intent intent) public Service instantiateService(ClassLoader cl, String className, Intent intent)
throws ClassNotFoundException, IllegalAccessException, InstantiationException { throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Log.d(TAG, className);
if (delegate != null) if (delegate != null)
return delegate.instantiateService(loader, className, intent); return delegate.instantiateService(loader, ComponentMap.get(className), intent);
return create(className, DummyService.class); return create(className, DummyService.class);
} }
@Override @Override
public ContentProvider instantiateProvider(ClassLoader cl, String className) public ContentProvider instantiateProvider(ClassLoader cl, String className)
throws ClassNotFoundException, IllegalAccessException, InstantiationException { throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Log.d(TAG, className);
if (loader == null) loader = cl;
if (delegate != null) if (delegate != null)
return delegate.instantiateProvider(loader, className); return delegate.instantiateProvider(loader, ComponentMap.get(className));
return create(className, DummyProvider.class); return create(className, DummyProvider.class);
} }
@ -63,6 +72,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
*/ */
private <T> T create(String name, Class<? extends T> dummy) private <T> T create(String name, Class<? extends T> dummy)
throws InstantiationException, IllegalAccessException { throws InstantiationException, IllegalAccessException {
Log.d(TAG, "create " + name);
try { try {
return (T) loader.loadClass(name).newInstance(); return (T) loader.loadClass(name).newInstance();
} catch (IllegalAccessException | InstantiationException | ClassNotFoundException ignored) { } catch (IllegalAccessException | InstantiationException | ClassNotFoundException ignored) {