Skip to content

Commit

Permalink
Make main app fully independent from the stub
Browse files Browse the repository at this point in the history
- Skip 0x7f01XXXX - 0x7f05XXXX resource IDs in the main app; they are
reserved for stub resources
- Support sending additional data from host to guest
- Use resource mapping passed from host when they are being sent
to the system framework (notifications and shortcuts)
  • Loading branch information
topjohnwu committed Oct 17, 2019
1 parent 9f9de8c commit 40eda05
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 133 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ out
*.apk
/config.prop
/update.sh
/stub-ids.txt

# Built binaries
native/out
Expand Down
5 changes: 5 additions & 0 deletions app/res-ids.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
com.topjohnwu.magisk:color/xxxxxxxx = 0x7f010000
com.topjohnwu.magisk:drawable/xxxxxxxx = 0x7f020000
com.topjohnwu.magisk:string/xxxxxxxx = 0x7f030000
com.topjohnwu.magisk:style/xxxxxxxx = 0x7f040000
com.topjohnwu.magisk:xml/xxxxxxxx = 0x7f050000
6 changes: 2 additions & 4 deletions app/src/main/java/a/e.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

import com.topjohnwu.magisk.App;

import java.util.Map;

public class e extends App {
public e() {
super();
}

public e(Map<String, String> map) {
super(map);
public e(Object o) {
super(o);
}
}
7 changes: 3 additions & 4 deletions app/src/main/java/com/topjohnwu/magisk/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.topjohnwu.magisk.di.ActivityTracker
import com.topjohnwu.magisk.di.koinModules
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.unwrap
import com.topjohnwu.magisk.utils.DynAPK
import com.topjohnwu.magisk.utils.RootInit
import com.topjohnwu.superuser.Shell
import org.koin.android.ext.koin.androidContext
Expand All @@ -23,9 +24,8 @@ import timber.log.Timber

open class App() : Application() {

constructor(map: Map<String, String>) : this() {
isRunningAsStub = true
ClassMap.componentMap = map
constructor(o: Any) : this() {
ClassMap.data = DynAPK.load(o)
}

init {
Expand Down Expand Up @@ -53,7 +53,6 @@ open class App() : Application() {
val app: Application
val impl: Context
if (base is Application) {
isRunningAsStub = true
app = base
impl = base.baseContext
} else {
Expand Down
39 changes: 24 additions & 15 deletions app/src/main/java/com/topjohnwu/magisk/Hacks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.topjohnwu.magisk.utils.currentLocale
import com.topjohnwu.magisk.utils.defaultLocale
import java.util.*

var isRunningAsStub = false
val isRunningAsStub get() = ClassMap.data != null

private val addAssetPath by lazy {
AssetManager::class.java.getMethod("addAssetPath", String::class.java)
Expand All @@ -39,10 +39,14 @@ fun AssetManager.addAssetPath(path: String) {
}

fun Context.wrap(global: Boolean = true): Context
= if (!global) ResContext(this) else GlobalResContext(this)
= if (global) GlobalResContext(this) else ResContext(this)

fun Context.wrapJob(): Context = object : GlobalResContext(this) {

override fun getApplicationContext(): Context {
return this
}

@SuppressLint("NewApi")
override fun getSystemService(name: String): Any? {
return if (!isRunningAsStub) super.getSystemService(name) else
Expand All @@ -65,26 +69,32 @@ private fun Resources.patch(config: Configuration = Configuration(configuration)

fun Class<*>.cmp(pkg: String = BuildConfig.APPLICATION_ID): ComponentName {
val name = ClassMap[this].name
return ComponentName(pkg, ClassMap.componentMap?.get(name)
?: name)
return ComponentName(pkg, ClassMap.data?.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 }
return ClassMap.data?.let {
val className = it.componentMap.getOrElse(cls.name) { cls.name }
Intent().setComponent(ComponentName(this, className))
} ?: Intent(this, cls)
}

fun resolveRes(idx: Int): Int {
return ClassMap.data?.resourceMap?.get(idx) ?: when(idx) {
DynAPK.NOTIFICATION -> R.drawable.ic_magisk_outline
DynAPK.DOWNLOAD -> R.drawable.sc_cloud_download
DynAPK.SUPERUSER -> R.drawable.sc_superuser
DynAPK.MODULES -> R.drawable.sc_extension
DynAPK.MAGISKHIDE -> R.drawable.sc_magiskhide
else -> -1
}
}

private open class GlobalResContext(base: Context) : ContextWrapper(base) {
open val mRes: Resources get() = ResourceMgr.resource
private val loader by lazy { javaClass.classLoader!! }

override fun getApplicationContext(): Context {
return this
}

override fun getResources(): Resources {
return mRes
}
Expand Down Expand Up @@ -162,7 +172,7 @@ private class JobSchedulerWrapper(private val base: JobScheduler) : JobScheduler
// We need to patch the component of JobInfo to access WorkManager SystemJobService

val name = service.className
val component = ComponentName(service.packageName, ClassMap.componentMap?.get(name)
val component = ComponentName(service.packageName, ClassMap.data?.componentMap?.get(name)
?: name)

// Clone the JobInfo except component
Expand Down Expand Up @@ -205,7 +215,7 @@ private class JobSchedulerWrapper(private val base: JobScheduler) : JobScheduler

object ClassMap {

private val classMap = mapOf(
private val map = mapOf(
App::class.java to a.e::class.java,
MainActivity::class.java to a.b::class.java,
SplashActivity::class.java to a.c::class.java,
Expand All @@ -216,8 +226,7 @@ object ClassMap {
SuRequestActivity::class.java to a.m::class.java
)

// This will be set if running as guest app
var componentMap: Map<String, String>? = null
internal var data: DynAPK.Data? = null

operator fun get(c: Class<*>) = classMap.getOrElse(c) { throw IllegalArgumentException() }
operator fun get(c: Class<*>) = map.getOrElse(c) { throw IllegalArgumentException() }
}
8 changes: 5 additions & 3 deletions app/src/main/java/com/topjohnwu/magisk/view/Notifications.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
import com.topjohnwu.magisk.ui.SplashActivity
import com.topjohnwu.magisk.utils.DynAPK

object Notifications {

val mgr by lazy { NotificationManagerCompat.from(get()) }
private val icon by lazy { resolveRes(DynAPK.NOTIFICATION) }

fun setup(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand All @@ -39,7 +41,7 @@ object Notifications {
PendingIntent.FLAG_UPDATE_CURRENT)

val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
builder.setSmallIcon(icon)
.setContentTitle(context.getString(R.string.magisk_update_title))
.setContentText(context.getString(R.string.manager_download_install))
.setVibrate(longArrayOf(0, 100, 100, 100))
Expand All @@ -58,7 +60,7 @@ object Notifications {
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)

val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
builder.setSmallIcon(icon)
.setContentTitle(context.getString(R.string.manager_update_title))
.setContentText(context.getString(R.string.manager_download_install))
.setVibrate(longArrayOf(0, 100, 100, 100))
Expand All @@ -75,7 +77,7 @@ object Notifications {
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)

val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
builder.setSmallIcon(R.drawable.ic_magisk_outline)
builder.setSmallIcon(icon)
.setContentTitle(context.getString(R.string.dtbo_patched_title))
.setContentText(context.getString(R.string.dtbo_patched_reboot))
.setVibrate(longArrayOf(0, 100, 100, 100))
Expand Down
13 changes: 7 additions & 6 deletions app/src/main/java/com/topjohnwu/magisk/view/Shortcuts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ import android.os.Build
import androidx.annotation.RequiresApi
import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.ui.SplashActivity
import com.topjohnwu.magisk.utils.DynAPK
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.superuser.Shell

object Shortcuts {

fun setup(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
if (Build.VERSION.SDK_INT >= 25) {
val manager = context.getSystemService(ShortcutManager::class.java)
manager?.dynamicShortcuts = getShortCuts(context)
}
}

@RequiresApi(api = Build.VERSION_CODES.N_MR1)
@RequiresApi(api = 25)
private fun getShortCuts(context: Context): List<ShortcutInfo> {
val shortCuts = mutableListOf<ShortcutInfo>()
val root = Shell.rootAccess()
Expand All @@ -33,7 +34,7 @@ object Shortcuts {
.putExtra(Const.Key.OPEN_SECTION, "superuser")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
.setIcon(Icon.createWithResource(context, R.drawable.sc_superuser))
.setIcon(Icon.createWithResource(context, resolveRes(DynAPK.SUPERUSER)))
.setRank(0)
.build())
}
Expand All @@ -44,7 +45,7 @@ object Shortcuts {
.putExtra(Const.Key.OPEN_SECTION, "magiskhide")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
.setIcon(Icon.createWithResource(context, R.drawable.sc_magiskhide))
.setIcon(Icon.createWithResource(context, resolveRes(DynAPK.MAGISKHIDE)))
.setRank(1)
.build())
}
Expand All @@ -55,7 +56,7 @@ object Shortcuts {
.putExtra(Const.Key.OPEN_SECTION, "modules")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
.setIcon(Icon.createWithResource(context, R.drawable.sc_extension))
.setIcon(Icon.createWithResource(context, resolveRes(DynAPK.MODULES)))
.setRank(3)
.build())
shortCuts.add(ShortcutInfo.Builder(context, "downloads")
Expand All @@ -64,7 +65,7 @@ object Shortcuts {
.putExtra(Const.Key.OPEN_SECTION, "downloads")
.setAction(Intent.ACTION_VIEW)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
.setIcon(Icon.createWithResource(context, R.drawable.sc_cloud_download))
.setIcon(Icon.createWithResource(context, resolveRes(DynAPK.DOWNLOAD)))
.setRank(2)
.build())
}
Expand Down
12 changes: 0 additions & 12 deletions app/src/main/res/values/resources.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,4 @@
<string name="magiskhide" translatable="false">Magisk Hide</string>
<string name="empty" translatable="false"/>

<!-- Preserve 10 string slots for stub -->
<string name="stub_0" translatable="false"/>
<string name="stub_1" translatable="false"/>
<string name="stub_2" translatable="false"/>
<string name="stub_3" translatable="false"/>
<string name="stub_4" translatable="false"/>
<string name="stub_5" translatable="false"/>
<string name="stub_6" translatable="false"/>
<string name="stub_7" translatable="false"/>
<string name="stub_8" translatable="false"/>
<string name="stub_9" translatable="false"/>

</resources>
11 changes: 5 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ subprojects {

aaptOptions {
// Handle resource IDs
File resIds = rootProject.file('stable-ids.txt')
File stubIds = rootProject.file('stub-ids.txt')
if (module.name == 'app' && resIds.exists())
additionalParameters "--stable-ids", "${resIds.absolutePath}"
else if (module.name == 'stub')
additionalParameters "--emit-ids", "${stubIds.absolutePath}"
File resId = project.file('res-ids.txt')
if (resId.exists())
additionalParameters "--stable-ids", "${resId.absolutePath}"
else
additionalParameters "--emit-ids", "${resId.absolutePath}"
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions shared/src/main/java/com/topjohnwu/magisk/utils/DynAPK.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@
import android.content.Context;

import java.io.File;
import java.util.Map;

public class DynAPK {

// Indices of the object array
private static final int COMPONENT_MAP = 0;
private static final int RESOURCE_MAP = 1;

// Indices of the resource map
public static final int NOTIFICATION = 0;
public static final int DOWNLOAD = 1;
public static final int SUPERUSER = 2;
public static final int MODULES = 3;
public static final int MAGISKHIDE = 4;

private static File dynDir;

private static File getDynDir(Context c) {
Expand All @@ -23,4 +35,24 @@ public static File current(Context c) {
public static File update(Context c) {
return new File(getDynDir(c), "update.apk");
}

public static Data load(Object o) {
Object[] arr = (Object[]) o;
Data data = new Data();
data.componentMap = (Map<String, String>) arr[COMPONENT_MAP];
data.resourceMap = (int[]) arr[RESOURCE_MAP];
return data;
}

public static Object pack(Data data) {
Object[] arr = new Object[2];
arr[COMPONENT_MAP] = data.componentMap;
arr[RESOURCE_MAP] = data.resourceMap;
return arr;
}

public static class Data {
public Map<String, String> componentMap;
public int[] resourceMap;
}
}
32 changes: 0 additions & 32 deletions stable-ids.txt

This file was deleted.

27 changes: 27 additions & 0 deletions stub/res-ids.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
com.topjohnwu.magisk:style/SplashThemeBase.V19 = 0x7f040000
com.topjohnwu.magisk:string/app_name = 0x7f030000
com.topjohnwu.magisk:string/yes = 0x7f030001
com.topjohnwu.magisk:style/SplashTheme = 0x7f040001
com.topjohnwu.magisk:drawable/sc_superuser = 0x7f020000
com.topjohnwu.magisk:string/no_thanks = 0x7f030002
com.topjohnwu.magisk:drawable/ic_splash_activity = 0x7f020001
com.topjohnwu.magisk:drawable/sc_magiskhide = 0x7f020002
com.topjohnwu.magisk:color/light = 0x7f010000
com.topjohnwu.magisk:string/no_internet_msg = 0x7f030003
com.topjohnwu.magisk:drawable/sc_extension = 0x7f020003
com.topjohnwu.magisk:drawable/ic_magisk_outline = 0x7f020004
com.topjohnwu.magisk:color/ic_launcher_background = 0x7f010001
com.topjohnwu.magisk:xml/file_paths = 0x7f050000
com.topjohnwu.magisk:drawable/sc_cloud_download = 0x7f020005
com.topjohnwu.magisk:string/ok = 0x7f030004
com.topjohnwu.magisk:drawable/ic_magisk = 0x7f020006
com.topjohnwu.magisk:drawable/ic_superuser = 0x7f020007
com.topjohnwu.magisk:drawable/ic_cloud_download = 0x7f020008
com.topjohnwu.magisk:style/SplashThemeBase = 0x7f040002
com.topjohnwu.magisk:drawable/ic_magiskhide = 0x7f020009
com.topjohnwu.magisk:drawable/ic_launcher = 0x7f02000a
com.topjohnwu.magisk:drawable/ic_logo = 0x7f02000b
com.topjohnwu.magisk:drawable/ic_extension = 0x7f02000c
com.topjohnwu.magisk:string/upgrade_msg = 0x7f030005
com.topjohnwu.magisk:color/dark = 0x7f010002
com.topjohnwu.magisk:drawable/ic_magisk_padded = 0x7f02000d
Loading

0 comments on commit 40eda05

Please sign in to comment.