Merge branch 'master' of https://github.com/ElderDrivers/EdXposed
This commit is contained in:
commit
7504dd878f
|
|
@ -1,138 +0,0 @@
|
||||||
import groovy.xml.XmlUtil
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
|
|
||||||
gradle.projectsEvaluated {
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs.add('-Xbootclasspath/p:libs/framework-stub.jar')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 28
|
|
||||||
buildToolsVersion '28.0.3'
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
multiDexEnabled false
|
|
||||||
minSdkVersion 23
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
java.srcDirs += ['src/main/apacheCommonsLang']
|
|
||||||
jniLibs.srcDirs = ['libs']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled true
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only build the release variant
|
|
||||||
// variantFilter { variant ->
|
|
||||||
// if (variant.buildType.name != BuilderConstants.DEBUG) {
|
|
||||||
// variant.ignore = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
task generateStubs(type: Javadoc, dependsOn: 'compileReleaseSources') {
|
|
||||||
source = file('src/main/java')
|
|
||||||
ext.stubsDir = "$buildDir/api/stub-sources"
|
|
||||||
outputs.dir ext.stubsDir
|
|
||||||
title = null
|
|
||||||
|
|
||||||
options {
|
|
||||||
doclet = 'com.google.doclava.Doclava'
|
|
||||||
docletpath = fileTree(dir: 'doclib', include: '**/*.jar').asType(List)
|
|
||||||
jFlags '-Dignore.symbol.file'
|
|
||||||
addBooleanOption 'nodocs', true
|
|
||||||
addFileOption 'stubs', file(ext.stubsDir)
|
|
||||||
addFileOption 'api', file('doclib/api/current.txt')
|
|
||||||
addBooleanOption 'hide 111', true
|
|
||||||
addBooleanOption 'hide 113', true
|
|
||||||
addBooleanOption 'hidePackage xposed.dummy', true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task compileStubs(type: JavaCompile, dependsOn: 'generateStubs') {
|
|
||||||
source = fileTree(generateStubs.ext.stubsDir)
|
|
||||||
destinationDir = file("$buildDir/api/stub-classes")
|
|
||||||
options.compilerArgs += '-XDsuppressNotes'
|
|
||||||
}
|
|
||||||
|
|
||||||
task jarStubs(type: Jar) {
|
|
||||||
from compileStubs
|
|
||||||
destinationDir = file("$buildDir/api")
|
|
||||||
baseName = 'api'
|
|
||||||
}
|
|
||||||
|
|
||||||
task jarStubsSource(type: Jar) {
|
|
||||||
from generateStubs.source
|
|
||||||
destinationDir = jarStubs.destinationDir
|
|
||||||
baseName = jarStubs.baseName
|
|
||||||
classifier = 'sources'
|
|
||||||
}
|
|
||||||
|
|
||||||
task generateAPI(dependsOn: ['generateStubs', 'jarStubs', 'jarStubsSource'])
|
|
||||||
|
|
||||||
// Make sure that hiddenapistubs are placed before the Android SDK in app.iml
|
|
||||||
// as there doesn't seem to be any way to configure this in Android Studio.
|
|
||||||
task fixIml {
|
|
||||||
ext.imlFile = projectDir.absolutePath + '/' + project.name + '.iml'
|
|
||||||
inputs.file imlFile
|
|
||||||
outputs.file imlFile
|
|
||||||
|
|
||||||
println imlFile
|
|
||||||
doLast {
|
|
||||||
def imlFile = file(project.name + ".iml")
|
|
||||||
println 'Change ' + project.name + '.iml order'
|
|
||||||
try {
|
|
||||||
def parsedXml = (new XmlParser()).parse(imlFile)
|
|
||||||
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
|
|
||||||
parsedXml.component[1].remove(jdkNode)
|
|
||||||
def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
|
|
||||||
new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
|
|
||||||
XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
// nop, iml not found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.preBuild.dependsOn fixIml
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly files("libs/framework-stub.jar")
|
|
||||||
compileOnly project(':dexmaker')
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
|
|
||||||
task javac
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs.add('-Xbootclasspath/p:libs/framework-stub.jar')
|
|
||||||
}
|
|
||||||
|
|
||||||
android.applicationVariants.all { variant ->
|
|
||||||
def nameCapped = variant.name.capitalize()
|
|
||||||
def nameLowered = variant.name.toLowerCase()
|
|
||||||
|
|
||||||
def makeAndCopyTask = task("makeAndCopy${nameCapped}", type: Copy, dependsOn: "assemble${nameCapped}") {
|
|
||||||
from "build/intermediates/transforms/dexMerger/${nameLowered}/0/classes.dex"
|
|
||||||
into '../Core/template_override/system/framework'
|
|
||||||
rename("classes.dex", "edxposed.dex")
|
|
||||||
}
|
|
||||||
|
|
||||||
// def makeAndCopyTask = task("makeAndCopy${nameCapped}", type: Jar, dependsOn: "assemble${nameCapped}") {
|
|
||||||
// from "build/intermediates/transforms/dexMerger/${nameLowered}/0/"
|
|
||||||
// destinationDir file("../Core/template_override/system/framework/")
|
|
||||||
// baseName "edxposed"
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
package de.robv.android.xposed;
|
|
||||||
|
|
||||||
public class GeneClass_Template {
|
|
||||||
public static java.lang.reflect.Member method;
|
|
||||||
public static de.robv.android.xposed.XposedBridge.AdditionalHookInfo tAdditionalInfoObj;
|
|
||||||
|
|
||||||
public static boolean backup(java.lang.Object obj, int i) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean hook(java.lang.Object obj, int i) throws Throwable {
|
|
||||||
java.lang.Throwable th;
|
|
||||||
if (!de.robv.android.xposed.XposedBridge.disableHooks) {
|
|
||||||
java.lang.Object[] snapshot = tAdditionalInfoObj.callbacks.getSnapshot();
|
|
||||||
int length = snapshot.length;
|
|
||||||
if (length != 0) {
|
|
||||||
de.robv.android.xposed.XC_MethodHook.MethodHookParam methodHookParam = new de.robv.android.xposed.XC_MethodHook.MethodHookParam();
|
|
||||||
methodHookParam.method = method;
|
|
||||||
java.lang.Object[] objArr = new java.lang.Object[1];
|
|
||||||
methodHookParam.args = objArr;
|
|
||||||
methodHookParam.thisObject = obj;
|
|
||||||
objArr[0] = java.lang.Integer.valueOf(i);
|
|
||||||
int i2 = 0;
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
((de.robv.android.xposed.XC_MethodHook) snapshot[i2]).callBeforeHookedMethod(methodHookParam);
|
|
||||||
if (methodHookParam.returnEarly) {
|
|
||||||
i2++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (java.lang.Throwable th2) {
|
|
||||||
de.robv.android.xposed.XposedBridge.log(th2);
|
|
||||||
methodHookParam.setResult(null);
|
|
||||||
methodHookParam.returnEarly = false;
|
|
||||||
}
|
|
||||||
i2++;
|
|
||||||
} while (i2 < length);
|
|
||||||
if (!methodHookParam.returnEarly) {
|
|
||||||
try {
|
|
||||||
methodHookParam.setResult(java.lang.Boolean.valueOf(backup(obj, i)));
|
|
||||||
} catch (java.lang.Throwable th3) {
|
|
||||||
methodHookParam.setThrowable(th3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i2--;
|
|
||||||
do {
|
|
||||||
java.lang.Object result = methodHookParam.getResult();
|
|
||||||
Throwable th2 = methodHookParam.getThrowable();
|
|
||||||
try {
|
|
||||||
((de.robv.android.xposed.XC_MethodHook) snapshot[i2]).callAfterHookedMethod(methodHookParam);
|
|
||||||
} catch (java.lang.Throwable th4) {
|
|
||||||
de.robv.android.xposed.XposedBridge.log(th4);
|
|
||||||
if (th2 == null) {
|
|
||||||
methodHookParam.setResult(result);
|
|
||||||
} else {
|
|
||||||
methodHookParam.setThrowable(th2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i2--;
|
|
||||||
} while (i2 >= 0);
|
|
||||||
if (!methodHookParam.hasThrowable()) {
|
|
||||||
return ((java.lang.Boolean) methodHookParam.getResult()).booleanValue();
|
|
||||||
}
|
|
||||||
throw methodHookParam.getThrowable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return backup(obj, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setup(java.lang.reflect.Member member, de.robv.android.xposed.XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
|
||||||
method = member;
|
|
||||||
tAdditionalInfoObj = additionalHookInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/.externalNativeBuild
|
|
||||||
/build
|
|
||||||
/libs
|
|
||||||
/obj
|
|
||||||
/release
|
|
||||||
/template_override/system/framework/edxposed.dex
|
|
||||||
*.iml
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
import org.gradle.internal.os.OperatingSystem;
|
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
|
||||||
version "v0.3.1.6_beta-SNAPSHOT"
|
|
||||||
extensions["module_name"] = "EdXposed"
|
|
||||||
android {
|
|
||||||
compileSdkVersion 28
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
|
||||||
|
|
||||||
externalNativeBuild {
|
|
||||||
ndkBuild {
|
|
||||||
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
|
|
||||||
arguments "NDK_PROJECT_PATH=jni/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
externalNativeBuild {
|
|
||||||
ndkBuild {
|
|
||||||
path 'jni/Android.mk'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
afterEvaluate {
|
|
||||||
|
|
||||||
android.libraryVariants.all { variant ->
|
|
||||||
def nameCapped = variant.name.capitalize()
|
|
||||||
def nameLowered = variant.name.toLowerCase()
|
|
||||||
|
|
||||||
def zipTask = task("zip${nameCapped}", type: Exec, dependsOn: ":Bridge:makeAndCopy${nameCapped}") {
|
|
||||||
workingDir '..'
|
|
||||||
commandLine 'sh', 'build.sh', \
|
|
||||||
project.name, \
|
|
||||||
"${project.version}-${nameLowered}", \
|
|
||||||
"${project.extensions['module_name']}"
|
|
||||||
}
|
|
||||||
|
|
||||||
def pushTask = task("push${nameCapped}", type: Exec) {
|
|
||||||
workingDir 'release'
|
|
||||||
def commands = ["adb", "push", "magisk-${project.extensions['module_name']}" +
|
|
||||||
"-${project.version}-${nameLowered}.zip", "/sdcard/"]
|
|
||||||
if (OperatingSystem.current().isWindows()) {
|
|
||||||
commandLine 'cmd', '/c', commands.join(" ")
|
|
||||||
} else {
|
|
||||||
commandLine commands
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pushTask.dependsOn(zipTask)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#include <jni.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H
|
|
||||||
|
|
||||||
//#define LOG_DISABLED
|
|
||||||
//#define DEBUG
|
|
||||||
|
|
||||||
#define INJECT_DEX_PATH \
|
|
||||||
"/system/framework/edxposed.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex"
|
|
||||||
|
|
||||||
#define ENTRY_CLASS_NAME "com.elderdrivers.riru.xposed.Main"
|
|
||||||
|
|
||||||
#endif //CONFIG_H
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<manifest package="com.elderdrivers.riru.xposed" />
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -32,10 +32,9 @@ and zip binaries can be downloaded from [here](http://gnuwin32.sourceforge.net/p
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. run `:Bridge:makeAndCopyRelease` in Gradle window to build `edxposed.dex`
|
1. run `./gradlew :edxp-core:zipRelease` to build flashable zip
|
||||||
2. run `:Core:zipRelease` to build Magisk Riru module flashable zip file
|
2. find the flashable under `edxp-core/release/`
|
||||||
3. find the flashable under `Core/release/`
|
3. flash the zip in recovery mode or in Magisk Manager
|
||||||
4. flash the zip in recovery mode or in Magisk Manager
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|
|
||||||
15
build.gradle
15
build.gradle
|
|
@ -1,14 +1,14 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|
@ -16,6 +16,15 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
ext {
|
||||||
|
templateRootPath = project(":edxp-core").projectDir.path + "/template_override/"
|
||||||
|
templateSystemPath = templateRootPath + "/system/"
|
||||||
|
templateSystemx86Path = templateRootPath + "/system_x86/"
|
||||||
|
templateFrameworkPath = templateRootPath + "/system/framework/"
|
||||||
|
templateLibPath = templateRootPath + "/system/lib/"
|
||||||
|
templateLib64Path = templateRootPath + "/system/lib64/"
|
||||||
|
templateEtcPath = templateRootPath + "/system/etc/"
|
||||||
|
}
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,21 @@ dependencies {
|
||||||
|
|
||||||
sourceCompatibility = "7"
|
sourceCompatibility = "7"
|
||||||
targetCompatibility = "7"
|
targetCompatibility = "7"
|
||||||
|
|
||||||
|
|
||||||
|
task dexInJar(type: Jar) {
|
||||||
|
dependsOn jar
|
||||||
|
doFirst {
|
||||||
|
exec {
|
||||||
|
workingDir jar.destinationDir
|
||||||
|
executable "dx"
|
||||||
|
args "--dex", "--output", "classes.dex", "${jar.archiveName}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from "${jar.destinationDir}/classes.dex"
|
||||||
|
destinationDir jar.destinationDir
|
||||||
|
baseName "eddalvikdx"
|
||||||
|
onlyIf {
|
||||||
|
!jar.state.upToDate || !file(archiveName).exists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,3 @@
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url "https://plugins.gradle.org/m2/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: "net.ltgt.errorprone"
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
|
||||||
description = "A utility for doing compile or runtime code generation targeting Android's Dalvik VM"
|
description = "A utility for doing compile or runtime code generation targeting Android's Dalvik VM"
|
||||||
|
|
@ -21,10 +9,23 @@ repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs += ["-Xep:StringSplitter:OFF"]
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly project(':dalvikdx')
|
compileOnly project(':dalvikdx')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task dexInJar(type: Jar) {
|
||||||
|
dependsOn jar
|
||||||
|
doFirst {
|
||||||
|
exec {
|
||||||
|
workingDir jar.destinationDir
|
||||||
|
executable "dx"
|
||||||
|
args "--dex", "--output", "classes.dex", "${jar.archiveName}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from "${jar.destinationDir}/classes.dex"
|
||||||
|
destinationDir jar.destinationDir
|
||||||
|
baseName "eddexmaker"
|
||||||
|
onlyIf {
|
||||||
|
!jar.state.upToDate || !file(archiveName).exists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ public final class DexMaker {
|
||||||
* Modifier#FINAL} and {@link Modifier#ABSTRACT}.
|
* Modifier#FINAL} and {@link Modifier#ABSTRACT}.
|
||||||
*/
|
*/
|
||||||
public void declare(TypeId<?> type, String sourceFile, int flags,
|
public void declare(TypeId<?> type, String sourceFile, int flags,
|
||||||
TypeId<?> supertype, TypeId<?>... interfaces) {
|
TypeId<?> supertype, TypeId<?>... interfaces) {
|
||||||
TypeDeclaration declaration = getTypeDeclaration(type);
|
TypeDeclaration declaration = getTypeDeclaration(type);
|
||||||
int supportedFlags = Modifier.PUBLIC | Modifier.FINAL | Modifier.ABSTRACT
|
int supportedFlags = Modifier.PUBLIC | Modifier.FINAL | Modifier.ABSTRACT
|
||||||
| AccessFlags.ACC_SYNTHETIC;
|
| AccessFlags.ACC_SYNTHETIC;
|
||||||
|
|
@ -471,8 +471,23 @@ public final class DexMaker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClassLoader loadClassDirect(ClassLoader parent, File dexCache, String dexFileName) {
|
||||||
|
File result = new File(dexCache, dexFileName);
|
||||||
|
// Check that the file exists. If it does, return a DexClassLoader and skip all
|
||||||
|
// the dex bytecode generation.
|
||||||
|
if (result.exists()) {
|
||||||
|
return generateClassLoader(result, dexCache, parent);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
|
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
|
||||||
return generateAndLoad(parent, dexCache, null);
|
return generateAndLoad(parent, dexCache, generateFileName(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String dexFileName) throws IOException {
|
||||||
|
return generateAndLoad(parent, dexCache, dexFileName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -500,9 +515,8 @@ public final class DexMaker {
|
||||||
* @param dexCache the destination directory where generated and optimized
|
* @param dexCache the destination directory where generated and optimized
|
||||||
* dex files will be written. If null, this class will try to guess the
|
* dex files will be written. If null, this class will try to guess the
|
||||||
* application's private data dir.
|
* application's private data dir.
|
||||||
* @param fileName the name of dex file
|
|
||||||
*/
|
*/
|
||||||
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String fileName) throws IOException {
|
public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String dexFileName, boolean deleteOld) throws IOException {
|
||||||
if (dexCache == null) {
|
if (dexCache == null) {
|
||||||
String property = System.getProperty("dexmaker.dexcache");
|
String property = System.getProperty("dexmaker.dexcache");
|
||||||
if (property != null) {
|
if (property != null) {
|
||||||
|
|
@ -516,16 +530,18 @@ public final class DexMaker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileName == null || fileName.isEmpty())
|
File result = new File(dexCache, dexFileName);
|
||||||
fileName = generateFileName();
|
|
||||||
File result = new File(dexCache, fileName);
|
|
||||||
// Check that the file exists. If it does, return a DexClassLoader and skip all
|
|
||||||
// the dex bytecode generation.
|
|
||||||
if (result.exists()) {
|
|
||||||
return generateClassLoader(result, dexCache, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] dex = generate();
|
if (result.exists()) {
|
||||||
|
if (deleteOld) {
|
||||||
|
try {
|
||||||
|
deleteOldDex(result);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return generateClassLoader(result, dexCache, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This implementation currently dumps the dex to the filesystem. It
|
* This implementation currently dumps the dex to the filesystem. It
|
||||||
|
|
@ -534,9 +550,17 @@ public final class DexMaker {
|
||||||
*
|
*
|
||||||
* TODO: load the dex from memory where supported.
|
* TODO: load the dex from memory where supported.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
File parentDir = result.getParentFile();
|
||||||
|
if (!parentDir.exists()) {
|
||||||
|
parentDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
result.createNewFile();
|
result.createNewFile();
|
||||||
|
|
||||||
JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
|
JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
|
||||||
JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME);
|
JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME);
|
||||||
|
byte[] dex = generate();
|
||||||
entry.setSize(dex.length);
|
entry.setSize(dex.length);
|
||||||
jarOut.putNextEntry(entry);
|
jarOut.putNextEntry(entry);
|
||||||
jarOut.write(dex);
|
jarOut.write(dex);
|
||||||
|
|
@ -545,6 +569,32 @@ public final class DexMaker {
|
||||||
return generateClassLoader(result, dexCache, parent);
|
return generateClassLoader(result, dexCache, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteOldDex(File dexFile) {
|
||||||
|
dexFile.delete();
|
||||||
|
String dexDir = dexFile.getParent();
|
||||||
|
File oatDir = new File(dexDir, "/oat/");
|
||||||
|
File oatDirArm = new File(oatDir, "/arm/");
|
||||||
|
File oatDirArm64 = new File(oatDir, "/arm64/");
|
||||||
|
if (!oatDir.exists())
|
||||||
|
return;
|
||||||
|
String nameStart = dexFile.getName().replaceAll(".jar", "");
|
||||||
|
doDeleteOatFiles(oatDir, nameStart);
|
||||||
|
doDeleteOatFiles(oatDirArm, nameStart);
|
||||||
|
doDeleteOatFiles(oatDirArm64, nameStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDeleteOatFiles(File dir, String nameStart) {
|
||||||
|
if (!dir.exists())
|
||||||
|
return;
|
||||||
|
File[] oats = dir.listFiles();
|
||||||
|
if (oats == null)
|
||||||
|
return;
|
||||||
|
for (File oatFile:oats) {
|
||||||
|
if (oatFile.isFile() && oatFile.getName().startsWith(nameStart))
|
||||||
|
oatFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DexFile getDexFile() {
|
DexFile getDexFile() {
|
||||||
if (outputDex == null) {
|
if (outputDex == null) {
|
||||||
DexOptions options = new DexOptions();
|
DexOptions options = new DexOptions();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 26
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly files("libs/framework-stub.jar")
|
||||||
|
implementation project(':xposed-bridge')
|
||||||
|
compileOnly project(':dexmaker')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
preBuild.doLast {
|
||||||
|
def imlFile = file(project.name + ".iml")
|
||||||
|
try {
|
||||||
|
def parsedXml = (new groovy.util.XmlParser()).parse(imlFile)
|
||||||
|
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
|
||||||
|
parsedXml.component[1].remove(jdkNode)
|
||||||
|
def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
|
||||||
|
new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
|
||||||
|
groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// nop, iml not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs.add("-Xbootclasspath/p:${projectDir.absolutePath}/libs/framework-stub.jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<manifest package="com.elderdrivers.riru.edxp.common" />
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.elderdrivers.riru.xposed.config;
|
package com.elderdrivers.riru.edxp.config;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -6,8 +6,8 @@ import java.util.Set;
|
||||||
|
|
||||||
import de.robv.android.xposed.SELinuxHelper;
|
import de.robv.android.xposed.SELinuxHelper;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.xposed.config.InstallerChooser.INSTALLER_DATA_BASE_DIR;
|
import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_DATA_BASE_DIR;
|
||||||
import static com.elderdrivers.riru.xposed.config.InstallerChooser.INSTALLER_PACKAGE_NAME;
|
import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
|
|
||||||
|
|
@ -1,32 +1,34 @@
|
||||||
package com.elderdrivers.riru.xposed.config;
|
package com.elderdrivers.riru.edxp.config;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import com.elderdrivers.riru.xposed.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import de.robv.android.xposed.SELinuxHelper;
|
import de.robv.android.xposed.SELinuxHelper;
|
||||||
import de.robv.android.xposed.services.BaseService;
|
import de.robv.android.xposed.services.BaseService;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.xposed.Main.getInstallerPkgName;
|
|
||||||
|
|
||||||
public class InstallerChooser {
|
public class InstallerChooser {
|
||||||
|
|
||||||
private static final AtomicBoolean hasSet = new AtomicBoolean(false);
|
private static final AtomicBoolean hasSet = new AtomicBoolean(false);
|
||||||
|
@SuppressLint("SdCardPath")
|
||||||
private static final String DATA_DIR_PATH_PREFIX =
|
private static final String DATA_DIR_PATH_PREFIX =
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? "/data/user_de/0/" : "/data/data/";
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? "/data/user_de/0/" : "/data/user/0/";
|
||||||
|
|
||||||
|
|
||||||
public static final String PRIMARY_INSTALLER_PACKAGE_NAME = "com.solohsu.android.edxp.manager";
|
public static final String PRIMARY_INSTALLER_PACKAGE_NAME = "com.solohsu.android.edxp.manager";
|
||||||
public static final String SECONDARY_INSTALLER_PACKAGE_NAME = "org.meowcat.edxposed.manager";
|
public static final String SECONDARY_INSTALLER_PACKAGE_NAME = "org.meowcat.edxposed.manager";
|
||||||
public static final String LEGACY_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
public static final String LEGACY_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||||
|
|
||||||
public static String INSTALLER_PACKAGE_NAME = getInstallerPkgName();
|
public static String INSTALLER_PACKAGE_NAME;
|
||||||
@SuppressLint("SdCardPath")
|
public static String INSTALLER_DATA_BASE_DIR;
|
||||||
public static String INSTALLER_DATA_BASE_DIR = DATA_DIR_PATH_PREFIX + INSTALLER_PACKAGE_NAME + "/";
|
|
||||||
|
|
||||||
|
public static void setInstallerPackageName(String packageName) {
|
||||||
|
INSTALLER_PACKAGE_NAME = packageName;
|
||||||
|
INSTALLER_DATA_BASE_DIR = DATA_DIR_PATH_PREFIX + INSTALLER_PACKAGE_NAME + "/";
|
||||||
|
}
|
||||||
|
|
||||||
public static void setup() {
|
public static void setup() {
|
||||||
if (!hasSet.compareAndSet(false, true)) {
|
if (!hasSet.compareAndSet(false, true)) {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package com.elderdrivers.riru.xposed.util;
|
package com.elderdrivers.riru.edxp.util;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import com.elderdrivers.riru.xposed.BuildConfig;
|
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -11,10 +11,11 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import dalvik.system.PathClassLoader;
|
import dalvik.system.PathClassLoader;
|
||||||
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
|
|
||||||
public class ClassLoaderUtils {
|
public class ClassLoaderUtils {
|
||||||
|
|
||||||
public static final String DEXPATH = "/system/framework/edxposed.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex";
|
public static final String DEXPATH = "/system/framework/edxp.jar:/system/framework/eddalvikdx.jar:/system/framework/eddexmaker.jar";
|
||||||
|
|
||||||
public static void replaceParentClassLoader(ClassLoader appClassLoader) {
|
public static void replaceParentClassLoader(ClassLoader appClassLoader) {
|
||||||
if (appClassLoader == null) {
|
if (appClassLoader == null) {
|
||||||
|
|
@ -91,7 +92,7 @@ public class ClassLoaderUtils {
|
||||||
try {
|
try {
|
||||||
PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
|
PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
baseDexClassLoader.addDexPath(DEXPATH);
|
XposedHelpers.callMethod(baseDexClassLoader, "addDexPath", DEXPATH);
|
||||||
} else {
|
} else {
|
||||||
DexUtils.injectDexAtFirst(DEXPATH, baseDexClassLoader);
|
DexUtils.injectDexAtFirst(DEXPATH, baseDexClassLoader);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.elderdrivers.riru.xposed.util;
|
package com.elderdrivers.riru.edxp.util;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
@ -8,7 +8,6 @@ import java.lang.reflect.Field;
|
||||||
|
|
||||||
import dalvik.system.BaseDexClassLoader;
|
import dalvik.system.BaseDexClassLoader;
|
||||||
import dalvik.system.DexClassLoader;
|
import dalvik.system.DexClassLoader;
|
||||||
import dalvik.system.PathClassLoader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For 6.0 only.
|
* For 6.0 only.
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.elderdrivers.riru.xposed.util;
|
package com.elderdrivers.riru.edxp.util;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
@ -12,7 +12,7 @@ import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.xposed.util.ProcessUtils.PER_USER_RANGE;
|
import static com.elderdrivers.riru.edxp.util.ProcessUtils.PER_USER_RANGE;
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package com.elderdrivers.riru.xposed.util;
|
package com.elderdrivers.riru.edxp.util;
|
||||||
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.elderdrivers.riru.xposed.Main;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
|
@ -16,8 +14,7 @@ public class ProcessUtils {
|
||||||
public static final int PER_USER_RANGE = 100000;
|
public static final int PER_USER_RANGE = 100000;
|
||||||
public static final int USER_SYSTEM = 0;
|
public static final int USER_SYSTEM = 0;
|
||||||
|
|
||||||
public static String getCurrentProcessName() {
|
public static String getCurrentProcessName(String prettyName) {
|
||||||
String prettyName = Main.appProcessName;
|
|
||||||
if (!TextUtils.isEmpty(prettyName)) {
|
if (!TextUtils.isEmpty(prettyName)) {
|
||||||
return prettyName;
|
return prettyName;
|
||||||
}
|
}
|
||||||
|
|
@ -26,8 +23,6 @@ public class ProcessUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a common solution from https://stackoverflow.com/a/21389402
|
* a common solution from https://stackoverflow.com/a/21389402
|
||||||
* <p>
|
|
||||||
* use {@link com.elderdrivers.riru.xposed.Main#appProcessName} to get current process name
|
|
||||||
*/
|
*/
|
||||||
public static String getProcessName(int pid) {
|
public static String getProcessName(int pid) {
|
||||||
BufferedReader cmdlineReader = null;
|
BufferedReader cmdlineReader = null;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package com.elderdrivers.riru.xposed.util;
|
package com.elderdrivers.riru.edxp.util;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.elderdrivers.riru.xposed.BuildConfig;
|
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||||
|
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/.externalNativeBuild
|
||||||
|
/build
|
||||||
|
/libs
|
||||||
|
/obj
|
||||||
|
/release
|
||||||
|
/template_override/system
|
||||||
|
/template_override/system_x86
|
||||||
|
*.iml
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
version "v0.3.1.8_beta-SNAPSHOT"
|
||||||
|
|
||||||
|
ext {
|
||||||
|
module_name = "EdXposed"
|
||||||
|
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
||||||
|
is_windows = OperatingSystem.current().isWindows()
|
||||||
|
backends = ["Yahfa", "Sandhook", "Whale"]
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
|
||||||
|
arguments "NDK_PROJECT_PATH=jni/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
path 'jni/Android.mk'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyDalvikdxJar {
|
||||||
|
def jarTask = tasks.getByPath(':dalvikdx:dexInJar')
|
||||||
|
dependsOn jarTask
|
||||||
|
doLast {
|
||||||
|
copy {
|
||||||
|
from jarTask
|
||||||
|
into jar_dest_dir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onlyIf {
|
||||||
|
!jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyDexmakerJar {
|
||||||
|
def jarTask = tasks.getByPath(':dexmaker:dexInJar')
|
||||||
|
dependsOn jarTask
|
||||||
|
doLast {
|
||||||
|
copy {
|
||||||
|
from jarTask
|
||||||
|
into jar_dest_dir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onlyIf {
|
||||||
|
!jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanTemplate(type: Delete) {
|
||||||
|
delete file(templateSystemPath), file(templateSystemx86Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
|
||||||
|
android.libraryVariants.all { variant ->
|
||||||
|
|
||||||
|
def variantCapped = variant.name.capitalize()
|
||||||
|
def variantLowered = variant.name.toLowerCase()
|
||||||
|
|
||||||
|
backends.each { backend ->
|
||||||
|
|
||||||
|
def backendCapped = backend.capitalize()
|
||||||
|
def backendLowered = backend.toLowerCase()
|
||||||
|
|
||||||
|
def zipTask = task("zip${backendCapped}${variantCapped}", type: Exec) {
|
||||||
|
dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar
|
||||||
|
dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}")
|
||||||
|
workingDir '..'
|
||||||
|
commandLine 'sh', 'build.sh', project.name,
|
||||||
|
"${backendLowered}-${project.version}-${variantLowered}", "${module_name}"
|
||||||
|
doFirst {
|
||||||
|
copy {
|
||||||
|
from "${projectDir}/edconfig.tpl"
|
||||||
|
into templateFrameworkPath
|
||||||
|
rename "edconfig.tpl", "edconfig.jar"
|
||||||
|
expand(backend: "$backendCapped")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task("push${backendCapped}${variantCapped}", type: Exec) {
|
||||||
|
dependsOn zipTask
|
||||||
|
workingDir "${projectDir}/release"
|
||||||
|
def commands = ["adb", "push",
|
||||||
|
"magisk-${module_name}-${backendLowered}-${project.version}-${variantLowered}.zip",
|
||||||
|
"/sdcard/"]
|
||||||
|
if (is_windows) {
|
||||||
|
commandLine 'cmd', '/c', commands.join(" ")
|
||||||
|
} else {
|
||||||
|
commandLine commands
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// backward compatible
|
||||||
|
task("zip${variantCapped}") {
|
||||||
|
dependsOn "zipYahfa${variantCapped}"
|
||||||
|
}
|
||||||
|
task("push${variantCapped}") {
|
||||||
|
dependsOn "pushYahfa${variantCapped}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
version=90.0-0.3.1.6-beta-SNAPSHOT
|
version=90.0-0.3.1.8-beta-SNAPSHOT ($backend)
|
||||||
arch=arm64
|
arch=arm64
|
||||||
minsdk=23
|
minsdk=23
|
||||||
maxsdk=28
|
maxsdk=28
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include <jni.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
//#define LOG_DISABLED
|
||||||
|
//#define DEBUG
|
||||||
|
|
||||||
|
#define INJECT_DEX_PATH \
|
||||||
|
"/system/framework/edxp.jar:/system/framework/eddalvikdx.jar:/system/framework/eddexmaker.jar"
|
||||||
|
|
||||||
|
#define ENTRY_CLASS_NAME "com.elderdrivers.riru.edxp.Main"
|
||||||
|
|
||||||
|
#define CLASS_SAND_HOOK "com.swift.sandhook.SandHook"
|
||||||
|
|
||||||
|
#define CLASS_NEVER_CALL "com.swift.sandhook.ClassNeverCall"
|
||||||
|
|
||||||
|
#endif //CONFIG_H
|
||||||
|
|
@ -168,6 +168,29 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
|
||||||
} else {
|
} else {
|
||||||
LOGE("HookEntry class is null. %d", getpid());
|
LOGE("HookEntry class is null. %d", getpid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//load lib sandhook
|
||||||
|
void* lib_sandhook;
|
||||||
|
if (sizeof(void*) == 8) {
|
||||||
|
lib_sandhook = dlopen("/system/lib64/libsandhook.edxp.so", RTLD_NOW);
|
||||||
|
} else {
|
||||||
|
lib_sandhook = dlopen("/system/lib/libsandhook.edxp.so", RTLD_NOW);
|
||||||
|
}
|
||||||
|
if (!lib_sandhook) {
|
||||||
|
LOGW("libsandhook open failed. %s", dlerror());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool* (*jni_load)(JNIEnv*, jclass, jclass) = reinterpret_cast<bool *(*)(JNIEnv *, jclass,
|
||||||
|
jclass)>(dlsym(lib_sandhook, "JNI_Load_Ex"));
|
||||||
|
|
||||||
|
jclass sandhook_class = findClassFromLoader(env, myClassLoader, CLASS_SAND_HOOK);
|
||||||
|
jclass nevercall_class = findClassFromLoader(env, myClassLoader, CLASS_NEVER_CALL);
|
||||||
|
if (!sandhook_class || !nevercall_class) { // fail-fast
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!jni_load(env, sandhook_class, nevercall_class)) {
|
||||||
|
LOGE("SandHook: HookEntry class error. %d", getpid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring getThrowableMessage(JNIEnv *env, jobject throwable) {
|
jstring getThrowableMessage(JNIEnv *env, jobject throwable) {
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
#if defined(__LP64__)
|
#if defined(__LP64__)
|
||||||
static constexpr const char *kLibArtPath = "/system/lib64/libart.so";
|
static constexpr const char *kLibArtPath = "/system/lib64/libart.so";
|
||||||
static constexpr const char *kLibWhalePath = "/system/lib64/libwhale.so";
|
static constexpr const char *kLibWhalePath = "/system/lib64/libwhale.edxp.so";
|
||||||
#else
|
#else
|
||||||
static constexpr const char *kLibArtPath = "/system/lib/libart.so";
|
static constexpr const char *kLibArtPath = "/system/lib/libart.so";
|
||||||
static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so";
|
static constexpr const char *kLibWhalePath = "/system/lib/libwhale.edxp.so";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define XHOOK_REGISTER(NAME) \
|
#define XHOOK_REGISTER(NAME) \
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<manifest package="com.elderdrivers.riru.edxp" />
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/system/bin/sh
|
#!/system/bin/sh
|
||||||
|
|
||||||
EDXP_VERSION="0.3.1.6_beta-SNAPSHOT (3160)"
|
EDXP_VERSION="0.3.1.8_beta-SNAPSHOT (3180)"
|
||||||
ANDROID_SDK=`getprop ro.build.version.sdk`
|
ANDROID_SDK=`getprop ro.build.version.sdk`
|
||||||
BUILD_DESC=`getprop ro.build.description`
|
BUILD_DESC=`getprop ro.build.description`
|
||||||
PRODUCT=`getprop ro.build.product`
|
PRODUCT=`getprop ro.build.product`
|
||||||
|
|
@ -41,7 +41,7 @@ LATESTARTSERVICE=false
|
||||||
|
|
||||||
print_modname() {
|
print_modname() {
|
||||||
ui_print "************************************"
|
ui_print "************************************"
|
||||||
ui_print " Riru - Ed Xposed v0.3.1.6 "
|
ui_print " Riru - Ed Xposed v0.3.1.8 "
|
||||||
ui_print "************************************"
|
ui_print "************************************"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
id=riru_edxposed
|
id=riru_edxposed
|
||||||
name=Riru - Ed Xposed
|
name=Riru - Ed Xposed
|
||||||
version=v0.3.1.6_beta-SNAPSHOT
|
version=v0.3.1.8_beta-SNAPSHOT
|
||||||
versionCode=3160
|
versionCode=3180
|
||||||
author=solohsu & MlgmXyysd
|
author=solohsu & MlgmXyysd
|
||||||
description=Magisk version of Xposed. Require Riru - Core installed.
|
description=Magisk version of Xposed. Require Riru - Core installed.
|
||||||
minMagisk=17000
|
minMagisk=17000
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name=Ed Xposed
|
name=Ed Xposed
|
||||||
version=v0.3.1.6_beta-SNAPSHOT
|
version=v0.3.1.8_beta-SNAPSHOT
|
||||||
versionCode=3160
|
versionCode=3180
|
||||||
author=solohsu & MlgmXyysd
|
author=solohsu & MlgmXyysd
|
||||||
description=Magisk version of Xposed. Require Riru - Core installed.
|
description=Magisk version of Xposed. Require Riru - Core installed.
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
/build
|
||||||
|
/template_override/system/framework/edxp.jar
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.elderdrivers.riru.edxp.sandhook"
|
||||||
|
minSdkVersion 26
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly files("libs/framework-stub.jar")
|
||||||
|
implementation project(':edxp-common')
|
||||||
|
implementation project(':xposed-bridge')
|
||||||
|
implementation 'com.swift.sandhook:hooklib:3.3.3'
|
||||||
|
compileOnly project(':dexmaker')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
preBuild.doLast {
|
||||||
|
def imlFile = file(project.name + ".iml")
|
||||||
|
try {
|
||||||
|
def parsedXml = (new groovy.util.XmlParser()).parse(imlFile)
|
||||||
|
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
|
||||||
|
parsedXml.component[1].remove(jdkNode)
|
||||||
|
def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
|
||||||
|
new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
|
||||||
|
groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// nop, iml not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs.add("-Xbootclasspath/p:${projectDir.absolutePath}/libs/framework-stub.jar")
|
||||||
|
}
|
||||||
|
|
||||||
|
android.applicationVariants.all { variant ->
|
||||||
|
|
||||||
|
def variantNameCapped = variant.name.capitalize()
|
||||||
|
def variantNameLowered = variant.name.toLowerCase()
|
||||||
|
|
||||||
|
def myTemplatePath = "${projectDir}/template_override/"
|
||||||
|
|
||||||
|
task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") {
|
||||||
|
from "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/"
|
||||||
|
destinationDir file(myTemplatePath + "system/framework/")
|
||||||
|
baseName "edxp"
|
||||||
|
doLast {
|
||||||
|
copy {
|
||||||
|
from file(myTemplatePath)
|
||||||
|
into file(templateRootPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
STUB_FILE_NAME = "MethodHookerStubs"
|
||||||
|
|
||||||
|
TEMP_STUB_CLASS_WRAPPER = """package com.swift.sandhook.xposedcompat.hookstub;
|
||||||
|
|
||||||
|
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge;
|
||||||
|
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.getMethodId;
|
||||||
|
import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.originMethods;
|
||||||
|
import static com.swift.sandhook.xposedcompat.utils.DexLog.printCallOriginError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this file is auto gen by genhookstubs.py
|
||||||
|
* it is for sandhook internal hooker & backup methods
|
||||||
|
**/
|
||||||
|
public class MethodHookerStubs%d {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
TEMP_STUB_HOOK_METHOD_NAME = """stub_hook_%d"""
|
||||||
|
TEMP_STUB_HOOK_BACKUP_NAME = """stub_backup_%d"""
|
||||||
|
TEMP_STUB_CALL_ORIGIN_NAME = """call_origin_%d_%d"""
|
||||||
|
|
||||||
|
TEMP_STUB_GET_METHOD_ID_NAME = """getMethodId(%d, %d)"""
|
||||||
|
|
||||||
|
JAVA_TYPE_INT = "int"
|
||||||
|
JAVA_CAST_INT = "(int)"
|
||||||
|
JAVA_TYPE_LONG = "long"
|
||||||
|
|
||||||
|
TEMP_STUB_HOOK_METHOD = """
|
||||||
|
public static %s %s(%s) throws Throwable {
|
||||||
|
return %s hookBridge(%s, %s %s);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
TEMP_STUB_BACKUP_METHOD = """
|
||||||
|
public static %s %s(%s) throws Throwable {
|
||||||
|
try {
|
||||||
|
printCallOriginError(originMethods[%s]);
|
||||||
|
} catch (Throwable throwable) {}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
TEMP_STUB_CALL_ORIGIN_CLASS = """
|
||||||
|
static class %s implements CallOriginCallBack {
|
||||||
|
@Override
|
||||||
|
public long call(long... args) throws Throwable {
|
||||||
|
return %s(%s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
TEMP_STUB_INFO = """
|
||||||
|
public static boolean hasStubBackup = %s;
|
||||||
|
public static int[] stubSizes = {%s};
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
STUB_SIZES_32 = [10,20,30,30,30,30,30,20,10,10,5,5,3]
|
||||||
|
STUB_SIZES_64 = [10,20,30,30,30,30,50,50]
|
||||||
|
HAS_BACKUP = False
|
||||||
|
|
||||||
|
|
||||||
|
def getMethodId(args, index):
|
||||||
|
return TEMP_STUB_GET_METHOD_ID_NAME % (args, index)
|
||||||
|
|
||||||
|
def getMethodHookName(index):
|
||||||
|
return TEMP_STUB_HOOK_METHOD_NAME % index
|
||||||
|
|
||||||
|
def getMethodBackupName(index):
|
||||||
|
return TEMP_STUB_HOOK_BACKUP_NAME % index
|
||||||
|
|
||||||
|
def getCallOriginClassName(args, index):
|
||||||
|
return TEMP_STUB_CALL_ORIGIN_NAME % (args, index)
|
||||||
|
|
||||||
|
|
||||||
|
def genArgsList(is64Bit, isDefine, length):
|
||||||
|
args_list = ""
|
||||||
|
for i in range(length):
|
||||||
|
if (i != 0):
|
||||||
|
args_list += ", "
|
||||||
|
if isDefine:
|
||||||
|
if (is64Bit):
|
||||||
|
args_list += (JAVA_TYPE_LONG + " " + "a" + str(i))
|
||||||
|
else:
|
||||||
|
args_list += (JAVA_TYPE_INT + " " + "a" + str(i))
|
||||||
|
else:
|
||||||
|
args_list += ("a" + str(i))
|
||||||
|
return args_list
|
||||||
|
|
||||||
|
|
||||||
|
def genArgsListForCallOriginMethod(is64Bit, length):
|
||||||
|
arg_name = """args[%s]"""
|
||||||
|
args_list = ""
|
||||||
|
for i in range(length):
|
||||||
|
if (i != 0):
|
||||||
|
args_list += ", "
|
||||||
|
if (is64Bit):
|
||||||
|
args_list += arg_name % i
|
||||||
|
else:
|
||||||
|
args_list += (JAVA_CAST_INT + arg_name % i)
|
||||||
|
return args_list
|
||||||
|
|
||||||
|
|
||||||
|
def genHookMethod(is64Bit, args, index):
|
||||||
|
java_type = JAVA_TYPE_LONG if is64Bit else JAVA_TYPE_INT
|
||||||
|
cast = "" if is64Bit else JAVA_CAST_INT
|
||||||
|
args_list_pre = ", " if args > 0 else ""
|
||||||
|
args_list = genArgsList(is64Bit, False, args)
|
||||||
|
args_list_def = genArgsList(is64Bit, True, args)
|
||||||
|
call_origin_obj = ("new " + getCallOriginClassName(args, index) + "()") if HAS_BACKUP else "null"
|
||||||
|
method = TEMP_STUB_HOOK_METHOD % (java_type, getMethodHookName(index), args_list_def, cast, getMethodId(args, index), call_origin_obj, args_list_pre + args_list)
|
||||||
|
return method
|
||||||
|
|
||||||
|
|
||||||
|
def genBackupMethod(is64Bit, args, index):
|
||||||
|
java_type = JAVA_TYPE_LONG if is64Bit else JAVA_TYPE_INT
|
||||||
|
args_list_def = genArgsList(is64Bit, True, args)
|
||||||
|
method = TEMP_STUB_BACKUP_METHOD % (java_type, getMethodBackupName(index), args_list_def, getMethodId(args, index))
|
||||||
|
return method
|
||||||
|
|
||||||
|
def genCallOriginClass(is64Bit, args, index):
|
||||||
|
method = TEMP_STUB_CALL_ORIGIN_CLASS % (getCallOriginClassName(args, index), getMethodBackupName(index), genArgsListForCallOriginMethod(is64Bit, args))
|
||||||
|
return method
|
||||||
|
|
||||||
|
def genStubInfo32():
|
||||||
|
hasStub = "true" if HAS_BACKUP else "false"
|
||||||
|
stubSizes = ""
|
||||||
|
for args in range(len(STUB_SIZES_32)):
|
||||||
|
if (args != 0):
|
||||||
|
stubSizes += ", "
|
||||||
|
stubSizes += str(STUB_SIZES_32[args])
|
||||||
|
return TEMP_STUB_INFO % (hasStub, stubSizes)
|
||||||
|
|
||||||
|
def genStubInfo64():
|
||||||
|
hasStub = "true" if HAS_BACKUP else "false"
|
||||||
|
stubSizes = ""
|
||||||
|
for args in range(len(STUB_SIZES_64)):
|
||||||
|
if (args != 0):
|
||||||
|
stubSizes += ", "
|
||||||
|
stubSizes += str(STUB_SIZES_64[args])
|
||||||
|
return TEMP_STUB_INFO % (hasStub, stubSizes)
|
||||||
|
|
||||||
|
def gen32Stub(packageDir):
|
||||||
|
class_content = genStubInfo32()
|
||||||
|
class_name = STUB_FILE_NAME + "32"
|
||||||
|
for args in range(len(STUB_SIZES_32)):
|
||||||
|
for index in range(STUB_SIZES_32[args]):
|
||||||
|
class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index)
|
||||||
|
class_content += genHookMethod(False, args, index)
|
||||||
|
if HAS_BACKUP:
|
||||||
|
class_content += "\n"
|
||||||
|
class_content += genCallOriginClass(False, args, index)
|
||||||
|
class_content += "\n"
|
||||||
|
class_content += genBackupMethod(False, args, index)
|
||||||
|
class_content += "\n"
|
||||||
|
class_str = TEMP_STUB_CLASS_WRAPPER % (32, class_content)
|
||||||
|
javaFile = open(os.path.join(packageDir, class_name + ".java"), "w")
|
||||||
|
javaFile.write(class_str)
|
||||||
|
javaFile.close()
|
||||||
|
|
||||||
|
|
||||||
|
def gen64Stub(packageDir):
|
||||||
|
class_content = genStubInfo64()
|
||||||
|
class_name = STUB_FILE_NAME + "64"
|
||||||
|
for args in range(len(STUB_SIZES_64)):
|
||||||
|
for index in range(STUB_SIZES_64[args]):
|
||||||
|
class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index)
|
||||||
|
class_content += genHookMethod(True, args, index)
|
||||||
|
if HAS_BACKUP:
|
||||||
|
class_content += "\n"
|
||||||
|
class_content += genCallOriginClass(True, args, index)
|
||||||
|
class_content += "\n"
|
||||||
|
class_content += genBackupMethod(True, args, index)
|
||||||
|
class_content += "\n"
|
||||||
|
class_str = TEMP_STUB_CLASS_WRAPPER % (64, class_content)
|
||||||
|
javaFile = open(os.path.join(packageDir, class_name + ".java"), "w")
|
||||||
|
javaFile.write(class_str)
|
||||||
|
javaFile.close()
|
||||||
|
|
||||||
|
|
||||||
|
def genStub(packageDir):
|
||||||
|
for fileName in os.listdir(packageDir):
|
||||||
|
if fileName.startswith(STUB_FILE_NAME):
|
||||||
|
os.remove(os.path.join(packageDir, fileName))
|
||||||
|
gen32Stub(packageDir)
|
||||||
|
gen64Stub(packageDir)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
genStub(os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||||
|
"src/main/java/com/swift/sandhook/xposedcompat/hookstub"))
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
-dontobfuscate
|
||||||
|
-keep class de.robv.android.xposed.** {*;}
|
||||||
|
-keep class android.** { *; }
|
||||||
|
|
||||||
|
-keep interface com.elderdrivers.riru.common.KeepAll
|
||||||
|
-keep interface com.elderdrivers.riru.common.KeepMembers
|
||||||
|
|
||||||
|
-keep class * implements com.elderdrivers.riru.common.KeepAll { *; }
|
||||||
|
-keepclassmembers class * implements com.elderdrivers.riru.common.KeepMembers { *; }
|
||||||
|
|
||||||
|
-keep class com.swift.sandhook.** {*;}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<manifest package="com.elderdrivers.riru.edxp.sandhook" />
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
package com.elderdrivers.riru.edxp;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Process;
|
||||||
|
|
||||||
|
import com.elderdrivers.riru.common.KeepAll;
|
||||||
|
import com.elderdrivers.riru.edxp.sandhook.BuildConfig;
|
||||||
|
import com.elderdrivers.riru.edxp.config.InstallerChooser;
|
||||||
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
|
import com.elderdrivers.riru.edxp.sandhook.core.HookMethodResolver;
|
||||||
|
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||||
|
import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy;
|
||||||
|
import com.elderdrivers.riru.edxp.sandhook.proxy.NormalProxy;
|
||||||
|
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||||
|
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
public class Main implements KeepAll {
|
||||||
|
|
||||||
|
public static String appDataDir = "";
|
||||||
|
public static String niceName = "";
|
||||||
|
public static String appProcessName = "";
|
||||||
|
private static String forkAndSpecializePramsStr = "";
|
||||||
|
private static String forkSystemServerPramsStr = "";
|
||||||
|
|
||||||
|
static {
|
||||||
|
init(Build.VERSION.SDK_INT);
|
||||||
|
HookMethodResolver.init();
|
||||||
|
Router.injectConfig();
|
||||||
|
InstallerChooser.setInstallerPackageName(getInstallerPkgName());
|
||||||
|
SandHookXposedBridge.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAppDataDir(String appDataDir) {
|
||||||
|
Main.appDataDir = appDataDir;
|
||||||
|
XposedCompat.appDataDir = appDataDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// entry points
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags,
|
||||||
|
int[][] rlimits, int mountExternal, String seInfo,
|
||||||
|
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||||
|
boolean startChildZygote, String instructionSet,
|
||||||
|
String appDataDir) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
forkAndSpecializePramsStr = String.format(
|
||||||
|
"Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)",
|
||||||
|
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||||
|
mountExternal, seInfo, niceName, Arrays.toString(fdsToClose),
|
||||||
|
Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir);
|
||||||
|
}
|
||||||
|
if (isBlackWhiteListEnabled()) {
|
||||||
|
BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits,
|
||||||
|
mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote,
|
||||||
|
instructionSet, appDataDir);
|
||||||
|
} else {
|
||||||
|
NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal,
|
||||||
|
seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet,
|
||||||
|
appDataDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
|
||||||
|
if (pid == 0) {
|
||||||
|
Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid());
|
||||||
|
if (isBlackWhiteListEnabled()) {
|
||||||
|
BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, niceName);
|
||||||
|
} else {
|
||||||
|
NormalProxy.forkAndSpecializePost(pid, appDataDir, niceName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in zygote process, res is child zygote pid
|
||||||
|
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)",
|
||||||
|
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||||
|
permittedCapabilities, effectiveCapabilities);
|
||||||
|
}
|
||||||
|
if (isBlackWhiteListEnabled()) {
|
||||||
|
BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||||
|
permittedCapabilities, effectiveCapabilities);
|
||||||
|
} else {
|
||||||
|
NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||||
|
permittedCapabilities, effectiveCapabilities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forkSystemServerPost(int pid) {
|
||||||
|
if (pid == 0) {
|
||||||
|
Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid());
|
||||||
|
if (isBlackWhiteListEnabled()) {
|
||||||
|
BlackWhiteListProxy.forkSystemServerPost(pid);
|
||||||
|
} else {
|
||||||
|
NormalProxy.forkSystemServerPost(pid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in zygote process, res is child zygote pid
|
||||||
|
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// native methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public static native boolean backupAndHookNative(Object target, Method hook, Method backup);
|
||||||
|
|
||||||
|
public static native void setMethodNonCompilable(Object member);
|
||||||
|
|
||||||
|
public static native void ensureMethodCached(Method hook, Method backup);
|
||||||
|
|
||||||
|
// JNI.ToReflectedMethod() could return either Method or Constructor
|
||||||
|
public static native Object findMethodNative(Class targetClass, String methodName, String methodSig);
|
||||||
|
|
||||||
|
private static native void init(int SDK_version);
|
||||||
|
|
||||||
|
public static native String getInstallerPkgName();
|
||||||
|
|
||||||
|
public static native boolean isBlackWhiteListEnabled();
|
||||||
|
|
||||||
|
public static native boolean isDynamicModulesEnabled();
|
||||||
|
|
||||||
|
public static native boolean isAppNeedHook(String appDataDir);
|
||||||
|
|
||||||
|
// prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote
|
||||||
|
// https://github.com/rovo89/Xposed/commit/b3ba245ad04cd485699fb1d2ebde7117e58214ff
|
||||||
|
public static native void closeFilesBeforeForkNative();
|
||||||
|
|
||||||
|
public static native void reopenFilesAfterForkNative();
|
||||||
|
|
||||||
|
public static native void deoptMethodNative(Object object);
|
||||||
|
|
||||||
|
public static native long suspendAllThreads();
|
||||||
|
|
||||||
|
public static native void resumeAllThreads(long obj);
|
||||||
|
|
||||||
|
public static native int waitForGcToComplete(long thread);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue