mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 18:45:28 +00:00
Update stub implementation
This commit is contained in:
parent
88e8e15607
commit
6b81716440
@ -21,7 +21,9 @@ class RootUtils(stub: Any?) : RootService() {
|
|||||||
private val className: String = stub?.javaClass?.name ?: javaClass.name
|
private val className: String = stub?.javaClass?.name ?: javaClass.name
|
||||||
private lateinit var am: ActivityManager
|
private lateinit var am: ActivityManager
|
||||||
|
|
||||||
constructor() : this(null) {
|
constructor() : this(null)
|
||||||
|
|
||||||
|
init {
|
||||||
Timber.plant(object : Timber.DebugTree() {
|
Timber.plant(object : Timber.DebugTree() {
|
||||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||||
super.log(priority, "Magisk", message, t)
|
super.log(priority, "Magisk", message, t)
|
||||||
|
2
app/stub/proguard-rules.pro
vendored
2
app/stub/proguard-rules.pro
vendored
@ -29,4 +29,4 @@
|
|||||||
-allowaccessmodification
|
-allowaccessmodification
|
||||||
-keepclassmembers class com.topjohnwu.magisk.dummy.* { <init>(); }
|
-keepclassmembers class com.topjohnwu.magisk.dummy.* { <init>(); }
|
||||||
-keepclassmembers class com.topjohnwu.magisk.DownloadActivity { <init>(); }
|
-keepclassmembers class com.topjohnwu.magisk.DownloadActivity { <init>(); }
|
||||||
-keepclassmembers class com.topjohnwu.magisk.DelegateRootService { <init>(); }
|
-keepclassmembers class com.topjohnwu.magisk.StubRootService { <init>(); }
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
package com.topjohnwu.magisk;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
import android.app.job.JobService;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
|
||||||
|
|
||||||
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 com.topjohnwu.magisk.utils.DynamicClassLoader;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
// Wrap the actual classloader as we only want to resolve classname
|
// Wrap the actual classloader as we only want to resolve classname
|
||||||
// mapping when loading from platform (via LoadedApk.mClassLoader)
|
// mapping when loading from platform (via LoadedApk.mClassLoader)
|
||||||
class AppClassLoader extends ClassLoader {
|
class MappingClassLoader extends ClassLoader {
|
||||||
final Map<String, String> mapping = new HashMap<>();
|
|
||||||
|
|
||||||
AppClassLoader(File apk) {
|
private final Map<String, String> mapping;
|
||||||
super(new DynamicClassLoader(apk));
|
|
||||||
|
MappingClassLoader(ClassLoader parent, Map<String, String> m) {
|
||||||
|
super(parent);
|
||||||
|
mapping = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -29,72 +26,6 @@ class AppClassLoader extends ClassLoader {
|
|||||||
name = clz != null ? clz : name;
|
name = clz != null ? clz : name;
|
||||||
return super.loadClass(name, resolve);
|
return super.loadClass(name, resolve);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateComponentMap(PackageInfo stub, PackageInfo app) {
|
|
||||||
{
|
|
||||||
var src = stub.activities;
|
|
||||||
var dest = app.activities;
|
|
||||||
|
|
||||||
final ActivityInfo sa;
|
|
||||||
final ActivityInfo da;
|
|
||||||
final ActivityInfo sb;
|
|
||||||
final ActivityInfo db;
|
|
||||||
if (src[0].exported) {
|
|
||||||
sa = src[0];
|
|
||||||
sb = src[1];
|
|
||||||
} else {
|
|
||||||
sa = src[1];
|
|
||||||
sb = src[0];
|
|
||||||
}
|
|
||||||
if (dest[0].exported) {
|
|
||||||
da = dest[0];
|
|
||||||
db = dest[1];
|
|
||||||
} else {
|
|
||||||
da = dest[1];
|
|
||||||
db = dest[0];
|
|
||||||
}
|
|
||||||
mapping.put(sa.name, da.name);
|
|
||||||
mapping.put(sb.name, db.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var src = stub.services;
|
|
||||||
var dest = app.services;
|
|
||||||
|
|
||||||
final ServiceInfo sa;
|
|
||||||
final ServiceInfo da;
|
|
||||||
final ServiceInfo sb;
|
|
||||||
final ServiceInfo db;
|
|
||||||
if (JobService.PERMISSION_BIND.equals(src[0].permission)) {
|
|
||||||
sa = src[0];
|
|
||||||
sb = src[1];
|
|
||||||
} else {
|
|
||||||
sa = src[1];
|
|
||||||
sb = src[0];
|
|
||||||
}
|
|
||||||
if (JobService.PERMISSION_BIND.equals(dest[0].permission)) {
|
|
||||||
da = dest[0];
|
|
||||||
db = dest[1];
|
|
||||||
} else {
|
|
||||||
da = dest[1];
|
|
||||||
db = dest[0];
|
|
||||||
}
|
|
||||||
mapping.put(sa.name, da.name);
|
|
||||||
mapping.put(sb.name, db.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var src = stub.receivers;
|
|
||||||
var dest = app.receivers;
|
|
||||||
mapping.put(src[0].name, dest[0].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var src = stub.providers;
|
|
||||||
var dest = app.providers;
|
|
||||||
mapping.put(src[0].name, dest[0].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class StubClassLoader extends ClassLoader {
|
class StubClassLoader extends ClassLoader {
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
package com.topjohnwu.magisk;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
|
|
||||||
public class DelegateApplication extends Application {
|
|
||||||
|
|
||||||
private Application receiver;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void attachBaseContext(Context base) {
|
|
||||||
super.attachBaseContext(base);
|
|
||||||
receiver = DynLoad.createAndSetupApp(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
if (receiver != null)
|
|
||||||
receiver.onCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
|
||||||
super.onConfigurationChanged(newConfig);
|
|
||||||
if (receiver != null)
|
|
||||||
receiver.onConfigurationChanged(newConfig);
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,7 +30,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Application instantiateApplication(ClassLoader cl, String className) {
|
public Application instantiateApplication(ClassLoader cl, String className) {
|
||||||
return new DelegateApplication();
|
return new StubApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,14 +60,6 @@ public class DownloadActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (DynLoad.activeClassLoader instanceof AppClassLoader) {
|
|
||||||
// For some reason activity is created before Application.attach(),
|
|
||||||
// relaunch the activity using the same intent
|
|
||||||
finishAffinity();
|
|
||||||
startActivity(getIntent());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
themed = new ContextThemeWrapper(this, android.R.style.Theme_DeviceDefault);
|
themed = new ContextThemeWrapper(this, android.R.style.Theme_DeviceDefault);
|
||||||
|
|
||||||
// Only download and dynamic load full APK if hidden
|
// Only download and dynamic load full APK if hidden
|
||||||
@ -187,7 +179,7 @@ public class DownloadActivity extends Activity {
|
|||||||
} else {
|
} else {
|
||||||
File res = new File(getCodeCacheDir(), "res.apk");
|
File res = new File(getCodeCacheDir(), "res.apk");
|
||||||
try (var out = new ZipOutputStream(new FileOutputStream(res))) {
|
try (var out = new ZipOutputStream(new FileOutputStream(res))) {
|
||||||
// AndroidManifest.xml is reuqired on Android 6-, and directory support is broken on Android 9-10
|
// AndroidManifest.xml is required on Android 6-, and directory support is broken on Android 9-10
|
||||||
out.putNextEntry(new ZipEntry("AndroidManifest.xml"));
|
out.putNextEntry(new ZipEntry("AndroidManifest.xml"));
|
||||||
try (var stubApk = new ZipFile(getPackageCodePath())) {
|
try (var stubApk = new ZipFile(getPackageCodePath())) {
|
||||||
APKInstall.transfer(stubApk.getInputStream(stubApk.getEntry("AndroidManifest.xml")), out);
|
APKInstall.transfer(stubApk.getInputStream(stubApk.getEntry("AndroidManifest.xml")), out);
|
||||||
|
@ -4,14 +4,18 @@ import static com.topjohnwu.magisk.BuildConfig.APPLICATION_ID;
|
|||||||
|
|
||||||
import android.app.AppComponentFactory;
|
import android.app.AppComponentFactory;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.app.job.JobService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.APKInstall;
|
import com.topjohnwu.magisk.utils.APKInstall;
|
||||||
|
import com.topjohnwu.magisk.utils.DynamicClassLoader;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -20,6 +24,7 @@ import java.io.IOException;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
public class DynLoad {
|
public class DynLoad {
|
||||||
@ -31,7 +36,7 @@ public class DynLoad {
|
|||||||
var data = new StubApk.Data();
|
var data = new StubApk.Data();
|
||||||
data.setVersion(BuildConfig.STUB_VERSION);
|
data.setVersion(BuildConfig.STUB_VERSION);
|
||||||
data.setClassToComponent(new HashMap<>());
|
data.setClassToComponent(new HashMap<>());
|
||||||
data.setRootService(DelegateRootService.class);
|
data.setRootService(StubRootService.class);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +51,7 @@ public class DynLoad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically load APK from internal, external storage, or previous app
|
// Dynamically load APK from internal, external storage, or previous app
|
||||||
static AppClassLoader loadApk(Context context) {
|
static DynamicClassLoader loadApk(Context context) {
|
||||||
File apk = StubApk.current(context);
|
File apk = StubApk.current(context);
|
||||||
File update = StubApk.update(context);
|
File update = StubApk.update(context);
|
||||||
|
|
||||||
@ -82,7 +87,7 @@ public class DynLoad {
|
|||||||
|
|
||||||
if (apk.exists()) {
|
if (apk.exists()) {
|
||||||
apk.setReadOnly();
|
apk.setReadOnly();
|
||||||
return new AppClassLoader(apk);
|
return new DynamicClassLoader(apk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no APK is loaded, attempt to copy from previous app
|
// If no APK is loaded, attempt to copy from previous app
|
||||||
@ -96,7 +101,7 @@ public class DynLoad {
|
|||||||
try (src; out) {
|
try (src; out) {
|
||||||
APKInstall.transfer(src, out);
|
APKInstall.transfer(src, out);
|
||||||
}
|
}
|
||||||
return new AppClassLoader(apk);
|
return new DynamicClassLoader(apk);
|
||||||
} catch (PackageManager.NameNotFoundException ignored) {
|
} catch (PackageManager.NameNotFoundException ignored) {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(DynLoad.class.getSimpleName(), "", e);
|
Log.e(DynLoad.class.getSimpleName(), "", e);
|
||||||
@ -107,8 +112,8 @@ public class DynLoad {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically load APK and create the Application instance from the loaded APK
|
// Dynamically load APK and initialize the application
|
||||||
static Application createAndSetupApp(Application context) {
|
static void loadAndInitializeApp(Application context) {
|
||||||
// On API >= 29, AppComponentFactory will replace the ClassLoader for us
|
// On API >= 29, AppComponentFactory will replace the ClassLoader for us
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
||||||
replaceClassLoader(context);
|
replaceClassLoader(context);
|
||||||
@ -120,10 +125,10 @@ public class DynLoad {
|
|||||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||||
var pm = context.getPackageManager();
|
var pm = context.getPackageManager();
|
||||||
|
|
||||||
final PackageInfo info;
|
final PackageInfo stubInfo;
|
||||||
try {
|
try {
|
||||||
// noinspection WrongConstant
|
// noinspection WrongConstant
|
||||||
info = pm.getPackageInfo(context.getPackageName(), flags);
|
stubInfo = pm.getPackageInfo(context.getPackageName(), flags);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
// Impossible
|
// Impossible
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@ -134,20 +139,19 @@ public class DynLoad {
|
|||||||
final var cl = loadApk(context);
|
final var cl = loadApk(context);
|
||||||
if (cl != null) try {
|
if (cl != null) try {
|
||||||
// noinspection WrongConstant
|
// noinspection WrongConstant
|
||||||
var pkgInfo = pm.getPackageArchiveInfo(apk.getPath(), flags);
|
var apkInfo = pm.getPackageArchiveInfo(apk.getPath(), flags);
|
||||||
cl.updateComponentMap(info, pkgInfo);
|
var mapping = generateMapping(stubInfo, apkInfo);
|
||||||
|
|
||||||
var appInfo = pkgInfo.applicationInfo;
|
|
||||||
|
|
||||||
var data = createApkData();
|
var data = createApkData();
|
||||||
var map = data.getClassToComponent();
|
var map = data.getClassToComponent();
|
||||||
// Create the inverse mapping (class to component name)
|
// Create the inverse mapping (class to component name)
|
||||||
for (var e : cl.mapping.entrySet()) {
|
for (var e : mapping.entrySet()) {
|
||||||
map.put(e.getValue(), e.getKey());
|
map.put(e.getValue(), e.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the receiver Application
|
var appInfo = apkInfo.applicationInfo;
|
||||||
var app = (Application) cl.loadClass(appInfo.className)
|
// Create the receiver Application with proper constructor
|
||||||
|
var app = cl.loadClass(appInfo.className)
|
||||||
.getConstructor(Object.class)
|
.getConstructor(Object.class)
|
||||||
.newInstance(data.getObject());
|
.newInstance(data.getObject());
|
||||||
|
|
||||||
@ -162,19 +166,17 @@ public class DynLoad {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activeClassLoader = cl;
|
activeClassLoader = new MappingClassLoader(cl, mapping);
|
||||||
|
|
||||||
// Send real application to attachBaseContext
|
// Call Application.attachBaseContext
|
||||||
attachContext(app, context);
|
attachContext(app, context);
|
||||||
|
|
||||||
return app;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(DynLoad.class.getSimpleName(), "", e);
|
Log.e(DynLoad.class.getSimpleName(), "", e);
|
||||||
apk.delete();
|
apk.delete();
|
||||||
|
} else {
|
||||||
|
// Dynamic loading failed, use normal stub classloader
|
||||||
|
activeClassLoader = new StubClassLoader(stubInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
activeClassLoader = new StubClassLoader(info);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace LoadedApk mClassLoader
|
// Replace LoadedApk mClassLoader
|
||||||
@ -198,4 +200,72 @@ public class DynLoad {
|
|||||||
Log.e(DynLoad.class.getSimpleName(), "", e);
|
Log.e(DynLoad.class.getSimpleName(), "", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> generateMapping(PackageInfo stub, PackageInfo app) {
|
||||||
|
var mapping = new HashMap<String, String>();
|
||||||
|
{
|
||||||
|
var src = stub.activities;
|
||||||
|
var dest = app.activities;
|
||||||
|
|
||||||
|
final ActivityInfo sa;
|
||||||
|
final ActivityInfo da;
|
||||||
|
final ActivityInfo sb;
|
||||||
|
final ActivityInfo db;
|
||||||
|
if (src[0].exported) {
|
||||||
|
sa = src[0];
|
||||||
|
sb = src[1];
|
||||||
|
} else {
|
||||||
|
sa = src[1];
|
||||||
|
sb = src[0];
|
||||||
|
}
|
||||||
|
if (dest[0].exported) {
|
||||||
|
da = dest[0];
|
||||||
|
db = dest[1];
|
||||||
|
} else {
|
||||||
|
da = dest[1];
|
||||||
|
db = dest[0];
|
||||||
|
}
|
||||||
|
mapping.put(sa.name, da.name);
|
||||||
|
mapping.put(sb.name, db.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var src = stub.services;
|
||||||
|
var dest = app.services;
|
||||||
|
|
||||||
|
final ServiceInfo sa;
|
||||||
|
final ServiceInfo da;
|
||||||
|
final ServiceInfo sb;
|
||||||
|
final ServiceInfo db;
|
||||||
|
if (JobService.PERMISSION_BIND.equals(src[0].permission)) {
|
||||||
|
sa = src[0];
|
||||||
|
sb = src[1];
|
||||||
|
} else {
|
||||||
|
sa = src[1];
|
||||||
|
sb = src[0];
|
||||||
|
}
|
||||||
|
if (JobService.PERMISSION_BIND.equals(dest[0].permission)) {
|
||||||
|
da = dest[0];
|
||||||
|
db = dest[1];
|
||||||
|
} else {
|
||||||
|
da = dest[1];
|
||||||
|
db = dest[0];
|
||||||
|
}
|
||||||
|
mapping.put(sa.name, da.name);
|
||||||
|
mapping.put(sb.name, db.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var src = stub.receivers;
|
||||||
|
var dest = app.receivers;
|
||||||
|
mapping.put(src[0].name, dest[0].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var src = stub.providers;
|
||||||
|
var dest = app.providers;
|
||||||
|
mapping.put(src[0].name, dest[0].name);
|
||||||
|
}
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class StubApplication extends Application {
|
||||||
|
@Override
|
||||||
|
protected void attachBaseContext(Context base) {
|
||||||
|
super.attachBaseContext(base);
|
||||||
|
DynLoad.loadAndInitializeApp(this);
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,9 @@ import android.util.Log;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
public class DelegateRootService extends ContextWrapper {
|
public class StubRootService extends ContextWrapper {
|
||||||
|
|
||||||
public DelegateRootService() {
|
public StubRootService() {
|
||||||
super(null);
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ public class DelegateRootService extends ContextWrapper {
|
|||||||
Object service = ctor.newInstance(this);
|
Object service = ctor.newInstance(this);
|
||||||
DynLoad.attachContext(service, base);
|
DynLoad.attachContext(service, base);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(DelegateRootService.class.getSimpleName(), "", e);
|
Log.e(StubRootService.class.getSimpleName(), "", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,13 +2,20 @@ import org.gradle.api.DefaultTask
|
|||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.CacheableTask
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.PathSensitive
|
||||||
|
import org.gradle.api.tasks.PathSensitivity
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.*
|
import java.util.Random
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import javax.crypto.CipherOutputStream
|
import javax.crypto.CipherOutputStream
|
||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
@ -169,7 +176,7 @@ abstract class ManifestUpdater: DefaultTask() {
|
|||||||
|<application
|
|<application
|
||||||
| android:appComponentFactory="$factoryPkg.$factoryClass"
|
| android:appComponentFactory="$factoryPkg.$factoryClass"
|
||||||
| android:name="$appPkg.$appClass"""".ind(1)
|
| android:name="$appPkg.$appClass"""".ind(1)
|
||||||
).replace(Regex(".*\\<\\/application"), components + "\n </application")
|
).replace(Regex(".*\\<\\/application"), "$components\n </application")
|
||||||
outputManifest.get().asFile.writeText(manifest)
|
outputManifest.get().asFile.writeText(manifest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +225,7 @@ fun genStubClasses(factoryOutDir: File, appOutDir: File) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
genClass("DelegateComponentFactory", factoryOutDir)
|
genClass("DelegateComponentFactory", factoryOutDir)
|
||||||
genClass("DelegateApplication", appOutDir)
|
genClass("StubApplication", appOutDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun genEncryptedResources(res: ByteArray, outDir: File) {
|
fun genEncryptedResources(res: ByteArray, outDir: File) {
|
||||||
|
@ -26,6 +26,6 @@ android.injected.testOnly=false
|
|||||||
android.nonFinalResIds=false
|
android.nonFinalResIds=false
|
||||||
|
|
||||||
# Magisk
|
# Magisk
|
||||||
magisk.stubVersion=39
|
magisk.stubVersion=40
|
||||||
magisk.versionCode=27003
|
magisk.versionCode=27003
|
||||||
magisk.ondkVersion=r27.2
|
magisk.ondkVersion=r27.2
|
||||||
|
Loading…
Reference in New Issue
Block a user