mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-13 05:37:47 +02:00
Make main app fully independent from the stub
- 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)
This commit is contained in:
@ -1,12 +0,0 @@
|
||||
package androidx.work.impl;
|
||||
|
||||
import com.topjohnwu.magisk.dummy.DummyProvider;
|
||||
|
||||
public class WorkManagerInitializer extends DummyProvider {
|
||||
/* This class have to exist, or else pre 9.0 devices
|
||||
* will experience ClassNotFoundException crashes when
|
||||
* launching the stub, as ContentProviders are constructed
|
||||
* when an app starts up. Pre 9.0 devices do not have
|
||||
* our custom DelegateComponentFactory to help creating
|
||||
* dummies. */
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AppComponentFactory;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
@ -13,7 +14,6 @@ import com.topjohnwu.magisk.utils.DynamicClassLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.topjohnwu.magisk.DownloadActivity.TAG;
|
||||
|
||||
@ -34,35 +34,7 @@ public class DelegateApplication extends Application {
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
// If 9.0+, try to dynamically load the APK
|
||||
DelegateComponentFactory factory = (DelegateComponentFactory) this.factory;
|
||||
MANAGER_APK = DynAPK.current(this);
|
||||
File update = DynAPK.update(this);
|
||||
if (update.exists())
|
||||
update.renameTo(MANAGER_APK);
|
||||
if (MANAGER_APK.exists()) {
|
||||
ClassLoader cl = new DynamicClassLoader(MANAGER_APK, factory.loader);
|
||||
try {
|
||||
// Create the delegate AppComponentFactory
|
||||
Object df = cl.loadClass("a.a").newInstance();
|
||||
|
||||
// Create the delegate Application
|
||||
delegate = (Application) cl.loadClass("a.e").getConstructor(Map.class)
|
||||
.newInstance(ComponentMap.inverseMap);
|
||||
|
||||
// Call attachBaseContext without ContextImpl to show it is being wrapped
|
||||
Method m = ContextWrapper.class.getDeclaredMethod("attachBaseContext", Context.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(delegate, this);
|
||||
|
||||
// If everything went well, set our loader and delegate
|
||||
factory.delegate = (AppComponentFactory) df;
|
||||
factory.loader = cl;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "dyn load", e);
|
||||
MANAGER_APK.delete();
|
||||
}
|
||||
}
|
||||
setUpDynAPK();
|
||||
} else {
|
||||
MANAGER_APK = new File(base.getCacheDir(), "manager.apk");
|
||||
}
|
||||
@ -73,4 +45,36 @@ public class DelegateApplication extends Application {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
delegate.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void setUpDynAPK() {
|
||||
DelegateComponentFactory factory = (DelegateComponentFactory) this.factory;
|
||||
MANAGER_APK = DynAPK.current(this);
|
||||
File update = DynAPK.update(this);
|
||||
if (update.exists())
|
||||
update.renameTo(MANAGER_APK);
|
||||
if (MANAGER_APK.exists()) {
|
||||
ClassLoader cl = new DynamicClassLoader(MANAGER_APK, factory.loader);
|
||||
try {
|
||||
// Create the delegate AppComponentFactory
|
||||
Object df = cl.loadClass("a.a").newInstance();
|
||||
|
||||
// Create the delegate Application
|
||||
delegate = (Application) cl.loadClass("a.e").getConstructor(Object.class)
|
||||
.newInstance(DynAPK.pack(Mapping.data));
|
||||
|
||||
// Call attachBaseContext without ContextImpl to show it is being wrapped
|
||||
Method m = ContextWrapper.class.getDeclaredMethod("attachBaseContext", Context.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(delegate, this);
|
||||
|
||||
// If everything went well, set our loader and delegate
|
||||
factory.delegate = (AppComponentFactory) df;
|
||||
factory.loader = cl;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "dyn load", e);
|
||||
MANAGER_APK.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
|
||||
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
|
||||
Log.d(TAG, className);
|
||||
if (delegate != null)
|
||||
return delegate.instantiateActivity(loader, ComponentMap.get(className), intent);
|
||||
return delegate.instantiateActivity(loader, Mapping.get(className), intent);
|
||||
return create(className, DummyActivity.class);
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
|
||||
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
|
||||
Log.d(TAG, className);
|
||||
if (delegate != null)
|
||||
return delegate.instantiateReceiver(loader, ComponentMap.get(className), intent);
|
||||
return delegate.instantiateReceiver(loader, Mapping.get(className), intent);
|
||||
return create(className, DummyReceiver.class);
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
|
||||
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
|
||||
Log.d(TAG, className);
|
||||
if (delegate != null)
|
||||
return delegate.instantiateService(loader, ComponentMap.get(className), intent);
|
||||
return delegate.instantiateService(loader, Mapping.get(className), intent);
|
||||
return create(className, DummyService.class);
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
|
||||
Log.d(TAG, className);
|
||||
if (loader == null) loader = cl;
|
||||
if (delegate != null)
|
||||
return delegate.instantiateProvider(loader, ComponentMap.get(className));
|
||||
return delegate.instantiateProvider(loader, Mapping.get(className));
|
||||
return create(className, DummyProvider.class);
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,13 @@ package com.topjohnwu.magisk;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class ComponentMap {
|
||||
import static com.topjohnwu.magisk.utils.DynAPK.*;
|
||||
|
||||
class Mapping {
|
||||
private static Map<String, String> map = new HashMap<>();
|
||||
|
||||
// This mapping will be sent into the guest app
|
||||
static Map<String, String> inverseMap;
|
||||
static Data data = new Data();
|
||||
|
||||
static {
|
||||
map.put(a.z.class.getName(), "a.c");
|
||||
@ -18,10 +20,17 @@ class ComponentMap {
|
||||
map.put("a.v", "a.j");
|
||||
map.put("a.j", "androidx.work.impl.background.systemjob.SystemJobService");
|
||||
|
||||
inverseMap = new HashMap<>(map.size());
|
||||
data.componentMap = new HashMap<>(map.size());
|
||||
for (Map.Entry<String, String> e : map.entrySet()) {
|
||||
inverseMap.put(e.getValue(), e.getKey());
|
||||
data.componentMap.put(e.getValue(), e.getKey());
|
||||
}
|
||||
int[] res = new int[5];
|
||||
res[NOTIFICATION] = R.drawable.ic_magisk_outline;
|
||||
res[SUPERUSER] = R.drawable.sc_superuser;
|
||||
res[MAGISKHIDE] = R.drawable.sc_magiskhide;
|
||||
res[DOWNLOAD] = R.drawable.sc_cloud_download;
|
||||
res[MODULES] = R.drawable.sc_extension;
|
||||
data.resourceMap = res;
|
||||
}
|
||||
|
||||
static String get(String name) {
|
Reference in New Issue
Block a user