merge all subprojects into one dex
This commit is contained in:
parent
7885999285
commit
0ca163d021
|
|
@ -20,36 +20,22 @@ jobs:
|
|||
- name: Get version code
|
||||
run: echo APPVEYOR_BUILD_NUMBER=$(expr $GITHUB_RUN_NUMBER + 4999) >> $GITHUB_ENV
|
||||
- name: Build with Gradle
|
||||
run: bash ./gradlew zipYahfaRelease zipSandhookRelease zipYahfaDebug zipSandhookDebug
|
||||
run: bash ./gradlew zipRelease zipDebug
|
||||
- name: Prepare artifact
|
||||
if: success()
|
||||
run: unzip edxp-core/release/EdXposed-YAHFA-v*-release.zip -d EdXposed-YAHFA-release;
|
||||
unzip edxp-core/release/EdXposed-SandHook-v*-release.zip -d EdXposed-SandHook-release;
|
||||
unzip edxp-core/release/EdXposed-YAHFA-v*-debug.zip -d EdXposed-YAHFA-debug;
|
||||
unzip edxp-core/release/EdXposed-SandHook-v*-debug.zip -d EdXposed-SandHook-debug
|
||||
- name: Upload YAHFA release
|
||||
run: unzip edxp-core/release/LSPosed-v*-release.zip -d LSPosed-release;
|
||||
unzip edxp-core/release/LSPosed-v*-debug.zip -d LSPosed-debug;
|
||||
- name: Upload release
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: EdXposed-YAHFA-release
|
||||
path: './EdXposed-YAHFA-release/*'
|
||||
- name: Upload Sandhook release
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: EdXposed-SandHook-release
|
||||
path: './EdXposed-SandHook-release/*'
|
||||
- name: Upload YAHFA debug
|
||||
name: LSPosed-release
|
||||
path: './LSPosed-release/*'
|
||||
- name: Upload debug
|
||||
# if: ${{ github.event_name == 'pull_request' && success() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: EdXposed-YAHFA-debug
|
||||
path: './EdXposed-YAHFA-debug/*'
|
||||
- name: Upload Sandhook debug
|
||||
# if: ${{ github.event_name == 'pull_request' && success() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: EdXposed-SandHook-debug
|
||||
path: './EdXposed-SandHook-debug/*'
|
||||
name: LSPosed-debug
|
||||
path: './LSPosed-debug/*'
|
||||
# - name: Prepare publish artifact
|
||||
# if: ${{ github.event_name == 'push' && success() }}
|
||||
# run: mkdir -p to_publish && mv edxp-core/release/EdXposed-YAHFA-v*-release.zip to_publish/EdXposed-YAHFA-release.zip && mv edxp-core/release/EdXposed-SandHook-v*-release.zip to_publish/EdXposed-SandHook-release.zip && echo $APPVEYOR_BUILD_NUMBER > to_publish/version
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ buildscript {
|
|||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
/build
|
||||
dex
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||
ndkVersion androidCompileNdkVersion
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
android.applicationVariants.all { variant ->
|
||||
def variantNameCapped = variant.name.capitalize()
|
||||
def variantNameLowered = variant.name.toLowerCase()
|
||||
|
||||
task("copyDex${variantNameCapped}", type: Copy) {
|
||||
dependsOn "assemble${variantNameCapped}"
|
||||
def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}"
|
||||
from (dexOutPath){
|
||||
rename("classes.dex", "eddalvikdx.dex")
|
||||
}
|
||||
destinationDir file(templateRootPath + "system/framework/")
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") {
|
||||
dependsOn "assemble${variantNameCapped}"
|
||||
from "${buildDir}/intermediates/javac/${variantNameLowered}/classes"
|
||||
baseName "dalvikdx"
|
||||
outputs.file(archivePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<manifest package="com.elderdrivers.riru.edxp.eddalvikdx" />
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
/build
|
||||
dex
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
description = "A utility for doing compile or runtime code generation targeting Android's Dalvik VM"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||
ndkVersion androidCompileNdkVersion
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly files(project(":dalvikdx").tasks.getByName("makeJarRelease").outputs)
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
android.applicationVariants.all { variant ->
|
||||
def variantNameCapped = variant.name.capitalize()
|
||||
def variantNameLowered = variant.name.toLowerCase()
|
||||
|
||||
task("copyDex${variantNameCapped}", type: Copy) {
|
||||
dependsOn "assemble${variantNameCapped}"
|
||||
def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}"
|
||||
from (dexOutPath){
|
||||
rename("classes.dex", "eddexmaker.dex")
|
||||
}
|
||||
destinationDir file(templateRootPath + "system/framework/")
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") {
|
||||
dependsOn "assemble${variantNameCapped}"
|
||||
from "${buildDir}/intermediates/javac/${variantNameLowered}/classes"
|
||||
baseName "dexmaker"
|
||||
outputs.file(archivePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<manifest package="com.elderdrivers.riru.edxp.dexmaker" />
|
||||
|
|
@ -1 +0,0 @@
|
|||
/build
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion androidMinSdkVersion.toInteger()
|
||||
targetSdkVersion androidTargetSdkVersion.toInteger()
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
buildConfigField("String", "VERSION_NAME", "\"${rootProject.ext.versionName}\"")
|
||||
buildConfigField("Integer", "VERSION_CODE", String.valueOf(rootProject.ext.versionCode))
|
||||
}
|
||||
debug {
|
||||
buildConfigField("String", "VERSION_NAME", "\"${rootProject.ext.versionName}\"")
|
||||
buildConfigField("Integer", "VERSION_CODE", String.valueOf(rootProject.ext.versionCode))
|
||||
}
|
||||
}
|
||||
|
||||
ndkVersion androidCompileNdkVersion
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(':hiddenapi-stubs')
|
||||
api project(':xposed-bridge')
|
||||
compileOnly project(':dexmaker')
|
||||
compileOnly 'com.android.support:support-annotations:28.0.0'
|
||||
}
|
||||
|
||||
|
||||
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:${hiddenApiStubJarFilePath}")
|
||||
}
|
||||
|
||||
task("copyCommonProperties", type: Copy) {
|
||||
from file("${projectDir}/template_override/")
|
||||
into file(templateRootPath)
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<manifest package="com.elderdrivers.riru.edxp.common" />
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import groovy.xml.XmlUtil
|
||||
import org.apache.tools.ant.filters.FixCrLfFilter
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
static def calcSha256(file) {
|
||||
def md = MessageDigest.getInstance("SHA-256")
|
||||
|
|
@ -30,16 +31,13 @@ if (System.env.APPVEYOR_BUILD_NUMBER != null) {
|
|||
version buildVersionName
|
||||
|
||||
ext {
|
||||
module_name = "EdXposed"
|
||||
module_name = "LSPosed"
|
||||
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
||||
is_windows = OperatingSystem.current().isWindows()
|
||||
backends = ["YAHFA", "SandHook"]
|
||||
yahfa_module_id = "riru_edxposed"
|
||||
sandhook_module_id = yahfa_module_id + "_sandhook"
|
||||
yahfa_authors = "solohsu, MlgmXyysd & rk700"
|
||||
sandhook_authors = "solohsu, MlgmXyysd & ganyao114"
|
||||
module_id = "riru_lsposed"
|
||||
authors = "LSPosed Developers"
|
||||
|
||||
riruModuleId = "edxp"
|
||||
riruModuleId = "lsposed"
|
||||
|
||||
moduleMinRiruApiVersion = 10
|
||||
moduleMinRiruVersionName = "v23.0"
|
||||
|
|
@ -54,13 +52,18 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
implementation 'rikka.ndk:riru:10'
|
||||
implementation project(path: ':sandhook-hooklib')
|
||||
compileOnly project(':hiddenapi-stubs')
|
||||
compileOnly 'com.android.support:support-annotations:28.0.0'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||
defaultConfig {
|
||||
applicationId "com.elderdrivers.riru.edxp"
|
||||
minSdkVersion androidMinSdkVersion.toInteger()
|
||||
targetSdkVersion androidTargetSdkVersion.toInteger()
|
||||
multiDexEnabled false
|
||||
|
||||
buildFeatures {
|
||||
prefab true
|
||||
|
|
@ -76,6 +79,10 @@ android {
|
|||
"-DRIRU_MODULE_VERSION_NAME:STRING=\"$rootProject.ext.versionName\""
|
||||
}
|
||||
}
|
||||
|
||||
buildConfigField("int", "API_CODE", "$apiCode")
|
||||
buildConfigField("String", "VERSION_NAME", "\"${rootProject.ext.versionName}\"")
|
||||
buildConfigField("Integer", "VERSION_CODE", String.valueOf(rootProject.ext.versionCode))
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
@ -88,14 +95,15 @@ android {
|
|||
}
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer"
|
||||
cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer"
|
||||
}
|
||||
}
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
|
|
@ -104,153 +112,178 @@ android {
|
|||
}
|
||||
}
|
||||
ndkVersion androidCompileNdkVersion
|
||||
compileOptions {
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
}
|
||||
|
||||
task cleanTemplate(type: Delete) {
|
||||
delete file(templateSystemx86Path)
|
||||
}
|
||||
|
||||
preBuild.doLast {
|
||||
def imlFile = file(project.name + ".iml")
|
||||
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 ignored) {
|
||||
// nop, iml not found
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
tasks.withType(JavaCompile) {
|
||||
dependsOn tasks.getByPath(":hiddenapi-stubs:makeStubJar")
|
||||
options.compilerArgs.add("-Xbootclasspath/p:${hiddenApiStubJarFilePath}")
|
||||
}
|
||||
|
||||
android.libraryVariants.all { variant ->
|
||||
task("copyCommonProperties", type: Copy) {
|
||||
from file("${projectDir}/template_override/")
|
||||
into file(templateRootPath)
|
||||
}
|
||||
|
||||
android.applicationVariants.all { variant ->
|
||||
def variantCapped = variant.name.capitalize()
|
||||
def variantLowered = variant.name.toLowerCase()
|
||||
def zipFileName = "${module_name}-${project.version}-${variantLowered}.zip"
|
||||
|
||||
backends.each { backend ->
|
||||
def backendLowered = backend.toLowerCase()
|
||||
def backendCapped = backendLowered.capitalize()
|
||||
def authorList = property("${backendLowered}" + "_authors")
|
||||
def magiskModuleId = property("${backendLowered}" + "_module_id")
|
||||
|
||||
delete file(zipPathMagiskReleasePath)
|
||||
|
||||
def prepareJarsTask = task("prepareJars${backendCapped}${variantCapped}") {
|
||||
dependsOn cleanTemplate
|
||||
dependsOn tasks.getByPath(":dexmaker:copyDex${variantCapped}")
|
||||
dependsOn tasks.getByPath(":dalvikdx:copyDex${variantCapped}")
|
||||
dependsOn tasks.getByPath(":edxp-service:copyDex${variantCapped}")
|
||||
dependsOn tasks.getByPath(":edxp-${backendLowered}:copyDex${variantCapped}")
|
||||
task("copyMainDex${variantCapped}", type: Copy) {
|
||||
def dexOutPath = variant.name.contains("release") ?
|
||||
"${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" :
|
||||
"${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}"
|
||||
from (dexOutPath){
|
||||
rename("classes.dex", "edxp.dex")
|
||||
}
|
||||
destinationDir file(zipPathMagiskReleasePath + "system/framework/")
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) {
|
||||
dependsOn prepareJarsTask, "assemble${variantCapped}"
|
||||
doFirst {
|
||||
copy {
|
||||
from "${projectDir}/tpl/edconfig.tpl"
|
||||
into templateFrameworkPath
|
||||
rename "edconfig.tpl", "edconfig.jar"
|
||||
expand(version: "$version", backend: "$backend", apiCode: "$apiCode")
|
||||
}
|
||||
copy {
|
||||
from "${projectDir}/tpl/module.prop.tpl"
|
||||
into templateRootPath
|
||||
rename "module.prop.tpl", "module.prop"
|
||||
expand(moduleId: "$magiskModuleId", backend: "$backendCapped",
|
||||
versionName: "$version" + " ($backend)",
|
||||
versionCode: "$versionCode", authorList: "$authorList",
|
||||
apiCode: "$apiCode", minApi: "$moduleMinRiruApiVersion")
|
||||
filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
}
|
||||
delete file(zipPathMagiskReleasePath)
|
||||
|
||||
def prepareMagiskFilesTask = task("prepareMagiskFiles${variantCapped}", type: Delete) {
|
||||
dependsOn "assemble${variantCapped}"
|
||||
dependsOn tasks.getByPath(":sandhook-hooklib:copySandHook${variantCapped}LibraryToMagiskTemplate")
|
||||
doFirst {
|
||||
copy {
|
||||
from "${projectDir}/tpl/edconfig.tpl"
|
||||
into templateFrameworkPath
|
||||
rename "edconfig.tpl", "edconfig.jar"
|
||||
expand(version: "$version", apiCode: "$apiCode")
|
||||
}
|
||||
def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj"
|
||||
def exclude_list = ["riru.sh"]
|
||||
doLast {
|
||||
copy {
|
||||
from "${projectDir}/template_override"
|
||||
into zipPathMagiskReleasePath
|
||||
exclude exclude_list
|
||||
}
|
||||
copy {
|
||||
from "${projectDir}/template_override"
|
||||
into zipPathMagiskReleasePath
|
||||
include 'util_functions.sh'
|
||||
filter { line ->
|
||||
line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId)
|
||||
.replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString())
|
||||
.replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName)
|
||||
}
|
||||
filter(FixCrLfFilter.class,
|
||||
eol: FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/armeabi-v7a"
|
||||
into "$zipPathMagiskReleasePath/system/lib"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/arm64-v8a"
|
||||
into "$zipPathMagiskReleasePath/system/lib64"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/x86"
|
||||
into "$zipPathMagiskReleasePath/system_x86/lib"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/x86_64"
|
||||
into "$zipPathMagiskReleasePath/system_x86/lib64"
|
||||
}
|
||||
// generate sha1sum
|
||||
fileTree(zipPathMagiskReleasePath).matching {
|
||||
exclude "README.md", "META-INF"
|
||||
}.visit { f ->
|
||||
if (f.directory) return
|
||||
file(f.file.path + ".s").text = calcSha256(f.file)
|
||||
}
|
||||
copy {
|
||||
from "${projectDir}/tpl/module.prop.tpl"
|
||||
into templateRootPath
|
||||
rename "module.prop.tpl", "module.prop"
|
||||
expand(moduleId: "$module_id",
|
||||
versionName: "$version",
|
||||
versionCode: "$versionCode", authorList: "$authors",
|
||||
apiCode: "$apiCode", minApi: "$moduleMinRiruApiVersion")
|
||||
filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
}
|
||||
}
|
||||
|
||||
def zipTask = task("zip${backendCapped}${variantCapped}", type: Zip) {
|
||||
dependsOn prepareMagiskFilesTask
|
||||
archiveName "${module_name}-${backend}-${project.version}-${variantLowered}.zip"
|
||||
destinationDir file("$projectDir/release")
|
||||
from "$zipPathMagiskReleasePath"
|
||||
}
|
||||
|
||||
task("push${backendCapped}${variantCapped}", type: Exec) {
|
||||
dependsOn zipTask
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "push",
|
||||
"${module_name}-${backend}-${project.version}-${variantLowered}.zip",
|
||||
"/data/local/tmp/"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj"
|
||||
def exclude_list = ["riru.sh"]
|
||||
doLast {
|
||||
def dexOutPath = variant.name.contains("release") ?
|
||||
"${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" :
|
||||
"${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}"
|
||||
copy {
|
||||
from (dexOutPath){
|
||||
rename("classes.dex", "edxp.dex")
|
||||
}
|
||||
into file(zipPathMagiskReleasePath + "system/framework/")
|
||||
}
|
||||
}
|
||||
task("flash${backendCapped}${variantCapped}", type: Exec) {
|
||||
dependsOn tasks.getByPath("push${backendCapped}${variantCapped}")
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "shell", "su", "-c",
|
||||
"magisk --install-module /data/local/tmp/${module_name}-${backend}-${project.version}-${variantLowered}.zip"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
copy {
|
||||
from "${projectDir}/template_override"
|
||||
into zipPathMagiskReleasePath
|
||||
exclude exclude_list
|
||||
}
|
||||
}
|
||||
task("flashAndReboot${backendCapped}${variantCapped}", type: Exec) {
|
||||
dependsOn tasks.getByPath("flash${backendCapped}${variantCapped}")
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "shell", "reboot"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
copy {
|
||||
from "${projectDir}/template_override"
|
||||
into zipPathMagiskReleasePath
|
||||
include 'util_functions.sh'
|
||||
filter { line ->
|
||||
line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId)
|
||||
.replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString())
|
||||
.replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName)
|
||||
}
|
||||
filter(FixCrLfFilter.class,
|
||||
eol: FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/armeabi-v7a"
|
||||
into "$zipPathMagiskReleasePath/system/lib"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/arm64-v8a"
|
||||
into "$zipPathMagiskReleasePath/system/lib64"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/x86"
|
||||
into "$zipPathMagiskReleasePath/system_x86/lib"
|
||||
}
|
||||
copy {
|
||||
include "libriru_edxp.so"
|
||||
from "$libPathRelease/x86_64"
|
||||
into "$zipPathMagiskReleasePath/system_x86/lib64"
|
||||
}
|
||||
// generate sha1sum
|
||||
fileTree(zipPathMagiskReleasePath).matching {
|
||||
exclude "README.md", "META-INF"
|
||||
}.visit { f ->
|
||||
if (f.directory) return
|
||||
file(f.file.path + ".sha256").text = calcSha256(f.file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// backward compatible
|
||||
task("zip${variantCapped}") {
|
||||
dependsOn "zipYahfa${variantCapped}"
|
||||
def zipTask = task("zip${variantCapped}", type: Zip) {
|
||||
dependsOn prepareMagiskFilesTask
|
||||
archiveName zipFileName
|
||||
destinationDir file("$projectDir/release")
|
||||
from "$zipPathMagiskReleasePath"
|
||||
}
|
||||
task("push${variantCapped}") {
|
||||
dependsOn "pushYahfa${variantCapped}"
|
||||
|
||||
task("push${variantCapped}", type: Exec) {
|
||||
dependsOn zipTask
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "push",
|
||||
zipFileName,
|
||||
"/data/local/tmp/"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
}
|
||||
}
|
||||
task("flash${variantCapped}", type: Exec) {
|
||||
dependsOn tasks.getByPath("push${variantCapped}")
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "shell", "su", "-c",
|
||||
"magisk --install-module /data/local/tmp/${zipFileName}"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
}
|
||||
}
|
||||
task("flashAndReboot${variantCapped}", type: Exec) {
|
||||
dependsOn tasks.getByPath("flash${variantCapped}")
|
||||
workingDir "${projectDir}/release"
|
||||
def commands = [android.adbExecutable, "shell", "reboot"]
|
||||
if (is_windows) {
|
||||
commandLine 'cmd', '/c', commands.join(" ")
|
||||
} else {
|
||||
commandLine commands
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace edxp {
|
|||
|
||||
ConfigManager::ConfigManager(uid_t user, bool initialized) :
|
||||
user_(user),
|
||||
data_path_prefix_(fs::path(use_prot_storage_ ? "/data/user_de" : "/data/user") /
|
||||
data_path_prefix_(fs::path("/data/user_de") /
|
||||
std::to_string(user_)),
|
||||
base_config_path_(RetrieveBaseConfigPath()),
|
||||
initialized_(initialized || InitConfigPath()),
|
||||
|
|
@ -344,11 +344,7 @@ namespace edxp {
|
|||
return !std::isspace(ch);
|
||||
}).base(), path.end());
|
||||
misc_path_ = fs::path("/data/misc") / path;
|
||||
std::transform(kXposedInjectDexPath.begin(), kXposedInjectDexPath.end(),
|
||||
std::back_inserter(inject_dex_paths_),
|
||||
[](auto i) {
|
||||
return GetFrameworkPath(i);
|
||||
});
|
||||
inject_dex_path_ = GetFrameworkPath(kXposedInjectDexPath);
|
||||
LOGI("Got base config path: %s", misc_path_.c_str());
|
||||
} catch (const RirudSocket::RirudSocketException &e) {
|
||||
LOGE("%s", e.what());
|
||||
|
|
|
|||
|
|
@ -14,16 +14,11 @@
|
|||
|
||||
namespace edxp {
|
||||
|
||||
|
||||
class ConfigManager {
|
||||
private:
|
||||
inline static const auto kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"s;
|
||||
inline static const auto kXposedPropName = "edconfig.jar"s;
|
||||
inline static const std::vector<std::string> kXposedInjectDexPath = {
|
||||
"edxp.dex",
|
||||
"eddalvikdx.dex",
|
||||
"eddexmaker.dex",
|
||||
};
|
||||
inline static const auto kXposedInjectDexPath = "edxp.dex";
|
||||
|
||||
public:
|
||||
static void Init();
|
||||
|
|
@ -105,22 +100,22 @@ namespace edxp {
|
|||
|
||||
void EnsurePermission(const std::string &pkg_name, uid_t uid) const;
|
||||
|
||||
static const auto &GetInjectDexPaths() { return inject_dex_paths_; };
|
||||
static const auto &GetInjectDexPath() { return inject_dex_path_; };
|
||||
|
||||
bool IsInstaller(const std::string &pkg_name) const {
|
||||
return pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
inline static std::unordered_map<uid_t, std::unique_ptr<ConfigManager>> instances_{};
|
||||
inline static uid_t current_user_ = 0u;
|
||||
inline static std::filesystem::path misc_path_;
|
||||
inline static std::vector<std::filesystem::path> inject_dex_paths_;
|
||||
inline static const bool use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__;
|
||||
inline static std::filesystem::path misc_path_; // /data/misc/edxp_xxxx
|
||||
inline static std::filesystem::path inject_dex_path_;
|
||||
|
||||
const uid_t user_;
|
||||
const std::filesystem::path data_path_prefix_;
|
||||
const std::filesystem::path base_config_path_;
|
||||
const std::filesystem::path data_path_prefix_; // /data/user_de/{user}
|
||||
const std::filesystem::path base_config_path_; // /data/misc/edxp_xxxx/{user}
|
||||
const bool initialized_ = false;
|
||||
const std::filesystem::path installer_pkg_name_;
|
||||
const bool white_list_enable_ = false;
|
||||
|
|
|
|||
|
|
@ -54,18 +54,17 @@ namespace edxp {
|
|||
CallPostFixupStaticTrampolinesCallback(class_ptr, post_fixup_static_mid_);
|
||||
}
|
||||
|
||||
void Context::PreLoadDex(const std::vector<fs::path> &dex_paths) {
|
||||
void Context::PreLoadDex(const fs::path &dex_path) {
|
||||
if (LIKELY(!dexes.empty())) return;
|
||||
for (const auto &path: dex_paths) {
|
||||
std::ifstream is(path, std::ios::binary);
|
||||
if (!is.good()) {
|
||||
LOGE("Cannot load path %s", path.c_str());
|
||||
continue;
|
||||
}
|
||||
dexes.emplace_back(std::istreambuf_iterator<char>(is),
|
||||
std::istreambuf_iterator<char>());
|
||||
LOGI("Loaded %s with size %zu", path.c_str(), dexes.back().size());
|
||||
|
||||
std::ifstream is(dex_path, std::ios::binary);
|
||||
if (!is.good()) {
|
||||
LOGE("Cannot load path %s", dex_path.c_str());
|
||||
return;
|
||||
}
|
||||
dexes.emplace_back(std::istreambuf_iterator<char>(is),
|
||||
std::istreambuf_iterator<char>());
|
||||
LOGI("Loaded %s with size %zu", dex_path.c_str(), dexes.back().size());
|
||||
}
|
||||
|
||||
void Context::InjectDexAndInit(JNIEnv *env) {
|
||||
|
|
@ -227,7 +226,7 @@ namespace edxp {
|
|||
LOGD("skip injecting into android because no module hooks it");
|
||||
}
|
||||
if (!skip_) {
|
||||
PreLoadDex(ConfigManager::GetInjectDexPaths());
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
}
|
||||
ConfigManager::GetInstance()->EnsurePermission("android", 1000);
|
||||
}
|
||||
|
|
@ -410,7 +409,7 @@ namespace edxp {
|
|||
}, is_child_zygote);
|
||||
if (!skip_) {
|
||||
ConfigManager::GetInstance()->EnsurePermission(package_name, uid);
|
||||
PreLoadDex(ConfigManager::GetInjectDexPaths());
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace edxp {
|
|||
|
||||
Context() {}
|
||||
|
||||
void PreLoadDex(const std::vector<std::filesystem::path> &dex_path);
|
||||
void PreLoadDex(const std::filesystem::path &dex_paths);
|
||||
|
||||
void InjectDexAndInit(JNIEnv *env);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,223 @@
|
|||
package android.app;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.view.Display;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
|
||||
import de.robv.android.xposed.XSharedPreferences;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
import static de.robv.android.xposed.XposedHelpers.findClass;
|
||||
import static de.robv.android.xposed.XposedHelpers.findFieldIfExists;
|
||||
import static de.robv.android.xposed.XposedHelpers.findMethodExactIfExists;
|
||||
import static de.robv.android.xposed.XposedHelpers.getObjectField;
|
||||
import static de.robv.android.xposed.XposedHelpers.newInstance;
|
||||
import static de.robv.android.xposed.XposedHelpers.setFloatField;
|
||||
|
||||
/**
|
||||
* Contains various methods for information about the current app.
|
||||
*
|
||||
* <p>For historical reasons, this class is in the {@code android.app} package. It can't be moved
|
||||
* without breaking compatibility with existing modules.
|
||||
*/
|
||||
public final class AndroidAppHelper {
|
||||
private AndroidAppHelper() {}
|
||||
|
||||
private static final Class<?> CLASS_RESOURCES_KEY;
|
||||
private static final boolean HAS_IS_THEMEABLE;
|
||||
private static final boolean HAS_THEME_CONFIG_PARAMETER;
|
||||
|
||||
static {
|
||||
CLASS_RESOURCES_KEY = (Build.VERSION.SDK_INT < 19) ?
|
||||
findClass("android.app.ActivityThread$ResourcesKey", null)
|
||||
: findClass("android.content.res.ResourcesKey", null);
|
||||
|
||||
HAS_IS_THEMEABLE = findFieldIfExists(CLASS_RESOURCES_KEY, "mIsThemeable") != null;
|
||||
HAS_THEME_CONFIG_PARAMETER = HAS_IS_THEMEABLE && Build.VERSION.SDK_INT >= 21
|
||||
&& findMethodExactIfExists("android.app.ResourcesManager", null, "getThemeConfig") != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private static Map<Object, WeakReference> getResourcesMap(ActivityThread activityThread) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
Object resourcesManager = getObjectField(activityThread, "mResourcesManager");
|
||||
return (Map) getObjectField(resourcesManager, "mResourceImpls");
|
||||
} else if (Build.VERSION.SDK_INT >= 19) {
|
||||
Object resourcesManager = getObjectField(activityThread, "mResourcesManager");
|
||||
return (Map) getObjectField(resourcesManager, "mActiveResources");
|
||||
} else {
|
||||
return (Map) getObjectField(activityThread, "mActiveResources");
|
||||
}
|
||||
}
|
||||
|
||||
/* For SDK 15 & 16 */
|
||||
private static Object createResourcesKey(String resDir, float scale) {
|
||||
try {
|
||||
if (HAS_IS_THEMEABLE)
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, scale, false);
|
||||
else
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, scale);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* For SDK 17 & 18 & 23 */
|
||||
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
|
||||
try {
|
||||
if (HAS_THEME_CONFIG_PARAMETER)
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, null);
|
||||
else if (HAS_IS_THEMEABLE)
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false);
|
||||
else
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* For SDK 19 - 22 */
|
||||
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale, IBinder token) {
|
||||
try {
|
||||
if (HAS_THEME_CONFIG_PARAMETER)
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, null, token);
|
||||
else if (HAS_IS_THEMEABLE)
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, token);
|
||||
else
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, token);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* For SDK 24+ */
|
||||
private static Object createResourcesKey(String resDir, String[] splitResDirs, String[] overlayDirs, String[] libDirs, int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
|
||||
try {
|
||||
return newInstance(CLASS_RESOURCES_KEY, resDir, splitResDirs, overlayDirs, libDirs, displayId, overrideConfiguration, compatInfo);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void addActiveResource(String resDir, float scale, boolean isThemeable, Resources resources) {
|
||||
addActiveResource(resDir, resources);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void addActiveResource(String resDir, Resources resources) {
|
||||
ActivityThread thread = ActivityThread.currentActivityThread();
|
||||
if (thread == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object resourcesKey;
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
CompatibilityInfo compatInfo = (CompatibilityInfo) newInstance(CompatibilityInfo.class);
|
||||
setFloatField(compatInfo, "applicationScale", resources.hashCode());
|
||||
resourcesKey = createResourcesKey(resDir, null, null, null, Display.DEFAULT_DISPLAY, null, compatInfo);
|
||||
} else if (Build.VERSION.SDK_INT == 23) {
|
||||
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode());
|
||||
} else if (Build.VERSION.SDK_INT >= 19) {
|
||||
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode(), null);
|
||||
} else if (Build.VERSION.SDK_INT >= 17) {
|
||||
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode());
|
||||
} else {
|
||||
resourcesKey = createResourcesKey(resDir, resources.hashCode());
|
||||
}
|
||||
|
||||
if (resourcesKey != null) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
Object resImpl = getObjectField(resources, "mResourcesImpl");
|
||||
getResourcesMap(thread).put(resourcesKey, new WeakReference<>(resImpl));
|
||||
} else {
|
||||
getResourcesMap(thread).put(resourcesKey, new WeakReference<>(resources));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the current process. It's usually the same as the main package name.
|
||||
*/
|
||||
public static String currentProcessName() {
|
||||
String processName = ActivityThread.currentPackageName();
|
||||
if (processName == null)
|
||||
return "android";
|
||||
return processName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the main application in the current process.
|
||||
*
|
||||
* <p>In a few cases, multiple apps might run in the same process, e.g. the SystemUI and the
|
||||
* Keyguard which both have {@code android:process="com.android.systemui"} set in their
|
||||
* manifest. In those cases, the first application that was initialized will be returned.
|
||||
*/
|
||||
public static ApplicationInfo currentApplicationInfo() {
|
||||
ActivityThread am = ActivityThread.currentActivityThread();
|
||||
if (am == null)
|
||||
return null;
|
||||
|
||||
Object boundApplication = getObjectField(am, "mBoundApplication");
|
||||
if (boundApplication == null)
|
||||
return null;
|
||||
|
||||
return (ApplicationInfo) getObjectField(boundApplication, "appInfo");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Android package name of the main application in the current process.
|
||||
*
|
||||
* <p>In a few cases, multiple apps might run in the same process, e.g. the SystemUI and the
|
||||
* Keyguard which both have {@code android:process="com.android.systemui"} set in their
|
||||
* manifest. In those cases, the first application that was initialized will be returned.
|
||||
*/
|
||||
public static String currentPackageName() {
|
||||
ApplicationInfo ai = currentApplicationInfo();
|
||||
return (ai != null) ? ai.packageName : "android";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the main {@link android.app.Application} object in the current process.
|
||||
*
|
||||
* <p>In a few cases, multiple apps might run in the same process, e.g. the SystemUI and the
|
||||
* Keyguard which both have {@code android:process="com.android.systemui"} set in their
|
||||
* manifest. In those cases, the first application that was initialized will be returned.
|
||||
*/
|
||||
public static Application currentApplication() {
|
||||
return ActivityThread.currentApplication();
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link XSharedPreferences} instead. */
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@Deprecated
|
||||
public static SharedPreferences getSharedPreferencesForPackage(String packageName, String prefFileName, int mode) {
|
||||
return new XSharedPreferences(packageName, prefFileName);
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link XSharedPreferences} instead. */
|
||||
@Deprecated
|
||||
public static SharedPreferences getDefaultSharedPreferencesForPackage(String packageName) {
|
||||
return new XSharedPreferences(packageName);
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link XSharedPreferences#reload} instead. */
|
||||
@Deprecated
|
||||
public static void reloadSharedPreferencesIfNeeded(SharedPreferences pref) {
|
||||
if (pref instanceof XSharedPreferences) {
|
||||
((XSharedPreferences) pref).reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Contains {@link android.app.AndroidAppHelper} with various methods for information about the current app.
|
||||
*/
|
||||
package android.app;
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package android.content.res;
|
||||
|
||||
import android.app.AndroidAppHelper;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import de.robv.android.xposed.IXposedHookInitPackageResources;
|
||||
import de.robv.android.xposed.IXposedHookZygoteInit;
|
||||
import de.robv.android.xposed.IXposedHookZygoteInit.StartupParam;
|
||||
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;
|
||||
|
||||
/**
|
||||
* Provides access to resources from a certain path (usually the module's own path).
|
||||
*/
|
||||
public class XModuleResources extends Resources {
|
||||
private XModuleResources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
|
||||
super(assets, metrics, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* <p>This is usually called with {@link StartupParam#modulePath} from
|
||||
* {@link IXposedHookZygoteInit#initZygote} and {@link InitPackageResourcesParam#res} from
|
||||
* {@link IXposedHookInitPackageResources#handleInitPackageResources} (or {@code null} for
|
||||
* system-wide replacements).
|
||||
*
|
||||
* @param path The path to the APK from which the resources should be loaded.
|
||||
* @param origRes The resources object from which settings like the display metrics and the
|
||||
* configuration should be copied. May be {@code null}.
|
||||
*/
|
||||
public static XModuleResources createInstance(String path, XResources origRes) {
|
||||
if (path == null)
|
||||
throw new IllegalArgumentException("path must not be null");
|
||||
|
||||
AssetManager assets = new AssetManager();
|
||||
assets.addAssetPath(path);
|
||||
|
||||
XModuleResources res;
|
||||
if (origRes != null)
|
||||
res = new XModuleResources(assets, origRes.getDisplayMetrics(), origRes.getConfiguration());
|
||||
else
|
||||
res = new XModuleResources(assets, null, null);
|
||||
|
||||
AndroidAppHelper.addActiveResource(path, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link XResForwarder} instance that forwards requests to {@code id} in this resource.
|
||||
*/
|
||||
public XResForwarder fwd(int id) {
|
||||
return new XResForwarder(this, id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package android.content.res;
|
||||
|
||||
/**
|
||||
* Instances of this class can be used for {@link XResources#setReplacement(String, String, String, Object)}
|
||||
* and its variants. They forward the resource request to a different {@link android.content.res.Resources}
|
||||
* instance with a possibly different ID.
|
||||
*
|
||||
* <p>Usually, instances aren't created directly but via {@link XModuleResources#fwd}.
|
||||
*/
|
||||
public class XResForwarder {
|
||||
private final Resources res;
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param res The target {@link android.content.res.Resources} instance to forward requests to.
|
||||
* @param id The target resource ID.
|
||||
*/
|
||||
public XResForwarder(Resources res, int id) {
|
||||
this.res = res;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/** Returns the target {@link android.content.res.Resources} instance. */
|
||||
public Resources getResources() {
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Returns the target resource ID. */
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Contains classes that are required for replacing resources.
|
||||
*/
|
||||
package android.content.res;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.elderdrivers.riru.edxp.config;
|
||||
|
||||
import com.elderdrivers.riru.edxp.hook.HookProvider;
|
||||
|
||||
public class EdXpConfigGlobal {
|
||||
|
||||
public static volatile EdxpConfig sConfig;
|
||||
public static volatile HookProvider sHookProvider;
|
||||
|
||||
public static EdxpConfig getConfig() {
|
||||
if (sConfig == null) {
|
||||
throw new IllegalArgumentException("sConfig should not be null.");
|
||||
}
|
||||
return sConfig;
|
||||
}
|
||||
|
||||
public static HookProvider getHookProvider() {
|
||||
if (sHookProvider == null) {
|
||||
throw new IllegalArgumentException("sHookProvider should not be null.");
|
||||
}
|
||||
return sHookProvider;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.elderdrivers.riru.edxp.config;
|
||||
|
||||
public interface EdxpConfig {
|
||||
|
||||
String getConfigPath(String suffix);
|
||||
|
||||
String getDataPathPrefix();
|
||||
|
||||
String getInstallerPackageName();
|
||||
|
||||
String getLibSandHookName();
|
||||
|
||||
boolean isNoModuleLogEnabled();
|
||||
|
||||
boolean isResourcesHookEnabled();
|
||||
|
||||
boolean isBlackWhiteListMode();
|
||||
|
||||
String getModulesList();
|
||||
}
|
||||
|
|
@ -3,16 +3,13 @@ package com.elderdrivers.riru.edxp.core;
|
|||
import android.annotation.SuppressLint;
|
||||
|
||||
import com.elderdrivers.riru.common.KeepAll;
|
||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||
import com.elderdrivers.riru.edxp.util.Utils;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.elderdrivers.riru.edxp.core.EdxpImpl.NONE;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public class Main implements KeepAll {
|
||||
private static final AtomicReference<EdxpImpl> edxpImplRef = new AtomicReference<>(null);
|
||||
|
|
@ -73,16 +70,31 @@ public class Main implements KeepAll {
|
|||
}
|
||||
|
||||
private static void loadEdxpImpls() {
|
||||
// We don't have Manifest now, so we have to load manually.
|
||||
String file_name = ConfigManager.getConfigPath("variant");
|
||||
int variant = EdxpImpl.NONE;
|
||||
try {
|
||||
Class.forName("com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl");
|
||||
}catch(Throwable ignored) {
|
||||
Utils.logD("not using sandhook");
|
||||
String f = new String(Files.readAllBytes(Paths.get(file_name)));
|
||||
variant = Integer.parseInt(f);
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
|
||||
Utils.logD("Loading variant " + variant);
|
||||
|
||||
try {
|
||||
Class.forName("com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl");
|
||||
}catch(Throwable ignored) {
|
||||
Utils.logD("not using yahfa");
|
||||
switch (variant) {
|
||||
case EdxpImpl.YAHFA:
|
||||
Class.forName("com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl");
|
||||
break;
|
||||
case EdxpImpl.SANDHOOK:
|
||||
Class.forName("com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl");
|
||||
break;
|
||||
default:
|
||||
Utils.logE("Unsupported variant" + variant);
|
||||
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
Utils.logE("loadEdxpImpls: Class not found", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.elderdrivers.riru.edxp.hook;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
public interface HookProvider {
|
||||
|
||||
void hookMethod(Member method, XposedBridge.AdditionalHookInfo additionalInfo);
|
||||
|
||||
void unhookMethod(Member method);
|
||||
|
||||
Object invokeOriginalMethod(Member method, long methodId, Object thisObject, Object[] args) throws Throwable;
|
||||
|
||||
Member findMethodNative(Member hookMethod);
|
||||
|
||||
void deoptMethods(String packageName, ClassLoader classLoader);
|
||||
|
||||
long getMethodId(Member member);
|
||||
|
||||
Object findMethodNative(Class clazz, String methodName, String methodSig);
|
||||
|
||||
void deoptMethodNative(Object method);
|
||||
|
||||
boolean initXResourcesNative();
|
||||
|
||||
boolean removeFinalFlagNative(Class clazz);
|
||||
|
||||
boolean methodHooked(Member target);
|
||||
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import android.view.ViewGroup;
|
|||
|
||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
||||
import com.elderdrivers.riru.edxp.common.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.core.EdxpImpl;
|
||||
import com.elderdrivers.riru.edxp.core.Main;
|
||||
import com.elderdrivers.riru.edxp.util.Utils;
|
||||
|
|
@ -184,7 +184,7 @@ public class XposedInstallerHooker {
|
|||
|
||||
Object method = XposedHelpers.findMethodExact(clazz, methodName, params);
|
||||
EdXpConfigGlobal.getHookProvider().deoptMethodNative(method);
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
Utils.logE("Error when deoptimizing " + className + ":" + methodName, e);
|
||||
}
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ package com.elderdrivers.riru.edxp.util;
|
|||
import android.os.Build;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.elderdrivers.riru.edxp.common.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -21,7 +21,7 @@ import de.robv.android.xposed.annotation.Level;
|
|||
@ApiSensitive(Level.LOW)
|
||||
public class ClassLoaderUtils {
|
||||
|
||||
public static final String DEXPATH = "/system/framework/edxp.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex";
|
||||
public static final String DEXPATH = "/system/framework/edxp.dex";
|
||||
|
||||
public static void replaceParentClassLoader(ClassLoader appClassLoader) {
|
||||
if (appClassLoader == null) {
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package com.elderdrivers.riru.edxp.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import pxb.android.axml.AxmlReader;
|
||||
import pxb.android.axml.AxmlVisitor;
|
||||
import pxb.android.axml.NodeVisitor;
|
||||
|
||||
public class MetaDataReader {
|
||||
private final HashMap<String, Object> metaData = new HashMap<>();
|
||||
|
||||
public static Map<String, Object> getMetaData(File apk) throws IOException {
|
||||
return new MetaDataReader(apk).metaData;
|
||||
}
|
||||
|
||||
private MetaDataReader(File apk) throws IOException {
|
||||
try(JarFile zip = new JarFile(apk)) {
|
||||
InputStream is = zip.getInputStream(zip.getEntry("AndroidManifest.xml"));
|
||||
byte[] bytes = getBytesFromInputStream(is);
|
||||
AxmlReader reader = new AxmlReader(bytes);
|
||||
reader.accept(new AxmlVisitor() {
|
||||
@Override
|
||||
public NodeVisitor child(String ns, String name) {
|
||||
NodeVisitor child = super.child(ns, name);
|
||||
return new ManifestTagVisitor(child);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException {
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
byte[] b = new byte[1024];
|
||||
int n;
|
||||
while ((n = inputStream.read(b)) != -1) {
|
||||
bos.write(b, 0, n);
|
||||
}
|
||||
byte[] data = bos.toByteArray();
|
||||
return data;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class ManifestTagVisitor extends NodeVisitor {
|
||||
public ManifestTagVisitor(NodeVisitor child) {
|
||||
super(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeVisitor child(String ns, String name) {
|
||||
NodeVisitor child = super.child(ns, name);
|
||||
if ("application".equals(name)) {
|
||||
return new ApplicationTagVisitor(child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
private class ApplicationTagVisitor extends NodeVisitor {
|
||||
public ApplicationTagVisitor(NodeVisitor child) {
|
||||
super(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeVisitor child(String ns, String name) {
|
||||
NodeVisitor child = super.child(ns, name);
|
||||
if("meta-data".equals(name)) {
|
||||
return new MetaDataVisitor(child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MetaDataVisitor extends NodeVisitor {
|
||||
public String name = null;
|
||||
public Object value = null;
|
||||
public MetaDataVisitor(NodeVisitor child) {
|
||||
super(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attr(String ns, String name, int resourceId, int type, Object obj) {
|
||||
if (type == 3 && "name".equals(name)) {
|
||||
this.name = (String)obj;
|
||||
}
|
||||
if ("value".equals(name) ) {
|
||||
value = obj;
|
||||
}
|
||||
super.attr(ns, name, resourceId, type, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
if(name != null && value != null) {
|
||||
metaData.put(name, value);
|
||||
}
|
||||
super.end();
|
||||
}
|
||||
}
|
||||
|
||||
public static int extractIntPart(String str) {
|
||||
int result = 0, length = str.length();
|
||||
for (int offset = 0; offset < length; offset++) {
|
||||
char c = str.charAt(offset);
|
||||
if ('0' <= c && c <= '9')
|
||||
result = result * 10 + (c - '0');
|
||||
else
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.elderdrivers.riru.edxp.util;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.elderdrivers.riru.edxp.common.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.annotation.ApiSensitive;
|
||||
|
|
@ -2,7 +2,7 @@ package com.elderdrivers.riru.edxp.yahfa.dexmaker;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.elderdrivers.riru.edxp.yahfa.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
|
||||
public class DexLog {
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ import com.elderdrivers.riru.edxp.config.ConfigManager;
|
|||
import com.elderdrivers.riru.edxp.core.Yahfa;
|
||||
import com.elderdrivers.riru.edxp.core.yahfa.HookMain;
|
||||
import com.elderdrivers.riru.edxp.util.ProxyClassLoader;
|
||||
import com.elderdrivers.riru.edxp.yahfa.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -2,7 +2,7 @@ package com.swift.sandhook.xposedcompat.hookstub;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.elderdrivers.riru.edxp.sandhook.BuildConfig;
|
||||
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.SandHookMethodResolver;
|
||||
import com.swift.sandhook.utils.ParamWrapper;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue