merge all subprojects into one dex
This commit is contained in:
parent
7885999285
commit
0ca163d021
|
|
@ -20,36 +20,22 @@ jobs:
|
||||||
- name: Get version code
|
- name: Get version code
|
||||||
run: echo APPVEYOR_BUILD_NUMBER=$(expr $GITHUB_RUN_NUMBER + 4999) >> $GITHUB_ENV
|
run: echo APPVEYOR_BUILD_NUMBER=$(expr $GITHUB_RUN_NUMBER + 4999) >> $GITHUB_ENV
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: bash ./gradlew zipYahfaRelease zipSandhookRelease zipYahfaDebug zipSandhookDebug
|
run: bash ./gradlew zipRelease zipDebug
|
||||||
- name: Prepare artifact
|
- name: Prepare artifact
|
||||||
if: success()
|
if: success()
|
||||||
run: unzip edxp-core/release/EdXposed-YAHFA-v*-release.zip -d EdXposed-YAHFA-release;
|
run: unzip edxp-core/release/LSPosed-v*-release.zip -d LSPosed-release;
|
||||||
unzip edxp-core/release/EdXposed-SandHook-v*-release.zip -d EdXposed-SandHook-release;
|
unzip edxp-core/release/LSPosed-v*-debug.zip -d LSPosed-debug;
|
||||||
unzip edxp-core/release/EdXposed-YAHFA-v*-debug.zip -d EdXposed-YAHFA-debug;
|
- name: Upload release
|
||||||
unzip edxp-core/release/EdXposed-SandHook-v*-debug.zip -d EdXposed-SandHook-debug
|
|
||||||
- name: Upload YAHFA release
|
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: EdXposed-YAHFA-release
|
name: LSPosed-release
|
||||||
path: './EdXposed-YAHFA-release/*'
|
path: './LSPosed-release/*'
|
||||||
- name: Upload Sandhook release
|
- name: Upload debug
|
||||||
if: success()
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: EdXposed-SandHook-release
|
|
||||||
path: './EdXposed-SandHook-release/*'
|
|
||||||
- name: Upload YAHFA debug
|
|
||||||
# if: ${{ github.event_name == 'pull_request' && success() }}
|
# if: ${{ github.event_name == 'pull_request' && success() }}
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: EdXposed-YAHFA-debug
|
name: LSPosed-debug
|
||||||
path: './EdXposed-YAHFA-debug/*'
|
path: './LSPosed-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: Prepare publish artifact
|
# - name: Prepare publish artifact
|
||||||
# if: ${{ github.event_name == 'push' && success() }}
|
# 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
|
# 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()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
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
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// 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.apache.tools.ant.filters.FixCrLfFilter
|
||||||
import org.gradle.internal.os.OperatingSystem
|
import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
static def calcSha256(file) {
|
static def calcSha256(file) {
|
||||||
def md = MessageDigest.getInstance("SHA-256")
|
def md = MessageDigest.getInstance("SHA-256")
|
||||||
|
|
@ -30,16 +31,13 @@ if (System.env.APPVEYOR_BUILD_NUMBER != null) {
|
||||||
version buildVersionName
|
version buildVersionName
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
module_name = "EdXposed"
|
module_name = "LSPosed"
|
||||||
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
jar_dest_dir = "${projectDir}/template_override/system/framework/"
|
||||||
is_windows = OperatingSystem.current().isWindows()
|
is_windows = OperatingSystem.current().isWindows()
|
||||||
backends = ["YAHFA", "SandHook"]
|
module_id = "riru_lsposed"
|
||||||
yahfa_module_id = "riru_edxposed"
|
authors = "LSPosed Developers"
|
||||||
sandhook_module_id = yahfa_module_id + "_sandhook"
|
|
||||||
yahfa_authors = "solohsu, MlgmXyysd & rk700"
|
|
||||||
sandhook_authors = "solohsu, MlgmXyysd & ganyao114"
|
|
||||||
|
|
||||||
riruModuleId = "edxp"
|
riruModuleId = "lsposed"
|
||||||
|
|
||||||
moduleMinRiruApiVersion = 10
|
moduleMinRiruApiVersion = 10
|
||||||
moduleMinRiruVersionName = "v23.0"
|
moduleMinRiruVersionName = "v23.0"
|
||||||
|
|
@ -54,13 +52,18 @@ repositories {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'rikka.ndk:riru:10'
|
implementation 'rikka.ndk:riru:10'
|
||||||
|
implementation project(path: ':sandhook-hooklib')
|
||||||
|
compileOnly project(':hiddenapi-stubs')
|
||||||
|
compileOnly 'com.android.support:support-annotations:28.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion androidCompileSdkVersion.toInteger()
|
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
applicationId "com.elderdrivers.riru.edxp"
|
||||||
minSdkVersion androidMinSdkVersion.toInteger()
|
minSdkVersion androidMinSdkVersion.toInteger()
|
||||||
targetSdkVersion androidTargetSdkVersion.toInteger()
|
targetSdkVersion androidTargetSdkVersion.toInteger()
|
||||||
|
multiDexEnabled false
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
prefab true
|
prefab true
|
||||||
|
|
@ -76,6 +79,10 @@ android {
|
||||||
"-DRIRU_MODULE_VERSION_NAME:STRING=\"$rootProject.ext.versionName\""
|
"-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 {
|
buildTypes {
|
||||||
|
|
@ -88,14 +95,15 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer"
|
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"
|
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 {
|
externalNativeBuild {
|
||||||
|
|
@ -104,153 +112,178 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ndkVersion androidCompileNdkVersion
|
ndkVersion androidCompileNdkVersion
|
||||||
|
compileOptions {
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task cleanTemplate(type: Delete) {
|
task cleanTemplate(type: Delete) {
|
||||||
delete file(templateSystemx86Path)
|
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 {
|
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 variantCapped = variant.name.capitalize()
|
||||||
def variantLowered = variant.name.toLowerCase()
|
def variantLowered = variant.name.toLowerCase()
|
||||||
|
def zipFileName = "${module_name}-${project.version}-${variantLowered}.zip"
|
||||||
|
|
||||||
backends.each { backend ->
|
task("copyMainDex${variantCapped}", type: Copy) {
|
||||||
def backendLowered = backend.toLowerCase()
|
def dexOutPath = variant.name.contains("release") ?
|
||||||
def backendCapped = backendLowered.capitalize()
|
"${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" :
|
||||||
def authorList = property("${backendLowered}" + "_authors")
|
"${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}"
|
||||||
def magiskModuleId = property("${backendLowered}" + "_module_id")
|
from (dexOutPath){
|
||||||
|
rename("classes.dex", "edxp.dex")
|
||||||
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}")
|
|
||||||
}
|
}
|
||||||
|
destinationDir file(zipPathMagiskReleasePath + "system/framework/")
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
|
||||||
def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) {
|
delete file(zipPathMagiskReleasePath)
|
||||||
dependsOn prepareJarsTask, "assemble${variantCapped}"
|
|
||||||
doFirst {
|
def prepareMagiskFilesTask = task("prepareMagiskFiles${variantCapped}", type: Delete) {
|
||||||
copy {
|
dependsOn "assemble${variantCapped}"
|
||||||
from "${projectDir}/tpl/edconfig.tpl"
|
dependsOn tasks.getByPath(":sandhook-hooklib:copySandHook${variantCapped}LibraryToMagiskTemplate")
|
||||||
into templateFrameworkPath
|
doFirst {
|
||||||
rename "edconfig.tpl", "edconfig.jar"
|
copy {
|
||||||
expand(version: "$version", backend: "$backend", apiCode: "$apiCode")
|
from "${projectDir}/tpl/edconfig.tpl"
|
||||||
}
|
into templateFrameworkPath
|
||||||
copy {
|
rename "edconfig.tpl", "edconfig.jar"
|
||||||
from "${projectDir}/tpl/module.prop.tpl"
|
expand(version: "$version", apiCode: "$apiCode")
|
||||||
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"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj"
|
copy {
|
||||||
def exclude_list = ["riru.sh"]
|
from "${projectDir}/tpl/module.prop.tpl"
|
||||||
doLast {
|
into templateRootPath
|
||||||
copy {
|
rename "module.prop.tpl", "module.prop"
|
||||||
from "${projectDir}/template_override"
|
expand(moduleId: "$module_id",
|
||||||
into zipPathMagiskReleasePath
|
versionName: "$version",
|
||||||
exclude exclude_list
|
versionCode: "$versionCode", authorList: "$authors",
|
||||||
}
|
apiCode: "$apiCode", minApi: "$moduleMinRiruApiVersion")
|
||||||
copy {
|
filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf"))
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj"
|
||||||
def zipTask = task("zip${backendCapped}${variantCapped}", type: Zip) {
|
def exclude_list = ["riru.sh"]
|
||||||
dependsOn prepareMagiskFilesTask
|
doLast {
|
||||||
archiveName "${module_name}-${backend}-${project.version}-${variantLowered}.zip"
|
def dexOutPath = variant.name.contains("release") ?
|
||||||
destinationDir file("$projectDir/release")
|
"${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" :
|
||||||
from "$zipPathMagiskReleasePath"
|
"${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}"
|
||||||
}
|
copy {
|
||||||
|
from (dexOutPath){
|
||||||
task("push${backendCapped}${variantCapped}", type: Exec) {
|
rename("classes.dex", "edxp.dex")
|
||||||
dependsOn zipTask
|
}
|
||||||
workingDir "${projectDir}/release"
|
into file(zipPathMagiskReleasePath + "system/framework/")
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
copy {
|
||||||
task("flash${backendCapped}${variantCapped}", type: Exec) {
|
from "${projectDir}/template_override"
|
||||||
dependsOn tasks.getByPath("push${backendCapped}${variantCapped}")
|
into zipPathMagiskReleasePath
|
||||||
workingDir "${projectDir}/release"
|
exclude exclude_list
|
||||||
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 {
|
||||||
task("flashAndReboot${backendCapped}${variantCapped}", type: Exec) {
|
from "${projectDir}/template_override"
|
||||||
dependsOn tasks.getByPath("flash${backendCapped}${variantCapped}")
|
into zipPathMagiskReleasePath
|
||||||
workingDir "${projectDir}/release"
|
include 'util_functions.sh'
|
||||||
def commands = [android.adbExecutable, "shell", "reboot"]
|
filter { line ->
|
||||||
if (is_windows) {
|
line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId)
|
||||||
commandLine 'cmd', '/c', commands.join(" ")
|
.replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString())
|
||||||
} else {
|
.replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName)
|
||||||
commandLine commands
|
}
|
||||||
|
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
|
def zipTask = task("zip${variantCapped}", type: Zip) {
|
||||||
task("zip${variantCapped}") {
|
dependsOn prepareMagiskFilesTask
|
||||||
dependsOn "zipYahfa${variantCapped}"
|
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) :
|
ConfigManager::ConfigManager(uid_t user, bool initialized) :
|
||||||
user_(user),
|
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_)),
|
std::to_string(user_)),
|
||||||
base_config_path_(RetrieveBaseConfigPath()),
|
base_config_path_(RetrieveBaseConfigPath()),
|
||||||
initialized_(initialized || InitConfigPath()),
|
initialized_(initialized || InitConfigPath()),
|
||||||
|
|
@ -344,11 +344,7 @@ namespace edxp {
|
||||||
return !std::isspace(ch);
|
return !std::isspace(ch);
|
||||||
}).base(), path.end());
|
}).base(), path.end());
|
||||||
misc_path_ = fs::path("/data/misc") / path;
|
misc_path_ = fs::path("/data/misc") / path;
|
||||||
std::transform(kXposedInjectDexPath.begin(), kXposedInjectDexPath.end(),
|
inject_dex_path_ = GetFrameworkPath(kXposedInjectDexPath);
|
||||||
std::back_inserter(inject_dex_paths_),
|
|
||||||
[](auto i) {
|
|
||||||
return GetFrameworkPath(i);
|
|
||||||
});
|
|
||||||
LOGI("Got base config path: %s", misc_path_.c_str());
|
LOGI("Got base config path: %s", misc_path_.c_str());
|
||||||
} catch (const RirudSocket::RirudSocketException &e) {
|
} catch (const RirudSocket::RirudSocketException &e) {
|
||||||
LOGE("%s", e.what());
|
LOGE("%s", e.what());
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,11 @@
|
||||||
|
|
||||||
namespace edxp {
|
namespace edxp {
|
||||||
|
|
||||||
|
|
||||||
class ConfigManager {
|
class ConfigManager {
|
||||||
private:
|
private:
|
||||||
inline static const auto kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"s;
|
inline static const auto kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"s;
|
||||||
inline static const auto kXposedPropName = "edconfig.jar"s;
|
inline static const auto kXposedPropName = "edconfig.jar"s;
|
||||||
inline static const std::vector<std::string> kXposedInjectDexPath = {
|
inline static const auto kXposedInjectDexPath = "edxp.dex";
|
||||||
"edxp.dex",
|
|
||||||
"eddalvikdx.dex",
|
|
||||||
"eddexmaker.dex",
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
@ -105,22 +100,22 @@ namespace edxp {
|
||||||
|
|
||||||
void EnsurePermission(const std::string &pkg_name, uid_t uid) const;
|
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 {
|
bool IsInstaller(const std::string &pkg_name) const {
|
||||||
return pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName;
|
return pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static std::unordered_map<uid_t, std::unique_ptr<ConfigManager>> instances_{};
|
inline static std::unordered_map<uid_t, std::unique_ptr<ConfigManager>> instances_{};
|
||||||
inline static uid_t current_user_ = 0u;
|
inline static uid_t current_user_ = 0u;
|
||||||
inline static std::filesystem::path misc_path_;
|
inline static std::filesystem::path misc_path_; // /data/misc/edxp_xxxx
|
||||||
inline static std::vector<std::filesystem::path> inject_dex_paths_;
|
inline static std::filesystem::path inject_dex_path_;
|
||||||
inline static const bool use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__;
|
|
||||||
|
|
||||||
const uid_t user_;
|
const uid_t user_;
|
||||||
const std::filesystem::path data_path_prefix_;
|
const std::filesystem::path data_path_prefix_; // /data/user_de/{user}
|
||||||
const std::filesystem::path base_config_path_;
|
const std::filesystem::path base_config_path_; // /data/misc/edxp_xxxx/{user}
|
||||||
const bool initialized_ = false;
|
const bool initialized_ = false;
|
||||||
const std::filesystem::path installer_pkg_name_;
|
const std::filesystem::path installer_pkg_name_;
|
||||||
const bool white_list_enable_ = false;
|
const bool white_list_enable_ = false;
|
||||||
|
|
|
||||||
|
|
@ -54,18 +54,17 @@ namespace edxp {
|
||||||
CallPostFixupStaticTrampolinesCallback(class_ptr, post_fixup_static_mid_);
|
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;
|
if (LIKELY(!dexes.empty())) return;
|
||||||
for (const auto &path: dex_paths) {
|
|
||||||
std::ifstream is(path, std::ios::binary);
|
std::ifstream is(dex_path, std::ios::binary);
|
||||||
if (!is.good()) {
|
if (!is.good()) {
|
||||||
LOGE("Cannot load path %s", path.c_str());
|
LOGE("Cannot load path %s", dex_path.c_str());
|
||||||
continue;
|
return;
|
||||||
}
|
|
||||||
dexes.emplace_back(std::istreambuf_iterator<char>(is),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
LOGI("Loaded %s with size %zu", path.c_str(), dexes.back().size());
|
|
||||||
}
|
}
|
||||||
|
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) {
|
void Context::InjectDexAndInit(JNIEnv *env) {
|
||||||
|
|
@ -227,7 +226,7 @@ namespace edxp {
|
||||||
LOGD("skip injecting into android because no module hooks it");
|
LOGD("skip injecting into android because no module hooks it");
|
||||||
}
|
}
|
||||||
if (!skip_) {
|
if (!skip_) {
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPaths());
|
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||||
}
|
}
|
||||||
ConfigManager::GetInstance()->EnsurePermission("android", 1000);
|
ConfigManager::GetInstance()->EnsurePermission("android", 1000);
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +409,7 @@ namespace edxp {
|
||||||
}, is_child_zygote);
|
}, is_child_zygote);
|
||||||
if (!skip_) {
|
if (!skip_) {
|
||||||
ConfigManager::GetInstance()->EnsurePermission(package_name, uid);
|
ConfigManager::GetInstance()->EnsurePermission(package_name, uid);
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPaths());
|
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ namespace edxp {
|
||||||
|
|
||||||
Context() {}
|
Context() {}
|
||||||
|
|
||||||
void PreLoadDex(const std::vector<std::filesystem::path> &dex_path);
|
void PreLoadDex(const std::filesystem::path &dex_paths);
|
||||||
|
|
||||||
void InjectDexAndInit(JNIEnv *env);
|
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 android.annotation.SuppressLint;
|
||||||
|
|
||||||
import com.elderdrivers.riru.common.KeepAll;
|
import com.elderdrivers.riru.common.KeepAll;
|
||||||
|
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
|
|
||||||
import java.security.AccessController;
|
import java.nio.file.Files;
|
||||||
import java.security.PrivilegedAction;
|
import java.nio.file.Paths;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.edxp.core.EdxpImpl.NONE;
|
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public class Main implements KeepAll {
|
public class Main implements KeepAll {
|
||||||
private static final AtomicReference<EdxpImpl> edxpImplRef = new AtomicReference<>(null);
|
private static final AtomicReference<EdxpImpl> edxpImplRef = new AtomicReference<>(null);
|
||||||
|
|
@ -73,16 +70,31 @@ public class Main implements KeepAll {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadEdxpImpls() {
|
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 {
|
try {
|
||||||
Class.forName("com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl");
|
String f = new String(Files.readAllBytes(Paths.get(file_name)));
|
||||||
}catch(Throwable ignored) {
|
variant = Integer.parseInt(f);
|
||||||
Utils.logD("not using sandhook");
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils.logD("Loading variant " + variant);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class.forName("com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl");
|
switch (variant) {
|
||||||
}catch(Throwable ignored) {
|
case EdxpImpl.YAHFA:
|
||||||
Utils.logD("not using 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.ConfigManager;
|
||||||
import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal;
|
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.EdxpImpl;
|
||||||
import com.elderdrivers.riru.edxp.core.Main;
|
import com.elderdrivers.riru.edxp.core.Main;
|
||||||
import com.elderdrivers.riru.edxp.util.Utils;
|
import com.elderdrivers.riru.edxp.util.Utils;
|
||||||
|
|
@ -184,7 +184,7 @@ public class XposedInstallerHooker {
|
||||||
|
|
||||||
Object method = XposedHelpers.findMethodExact(clazz, methodName, params);
|
Object method = XposedHelpers.findMethodExact(clazz, methodName, params);
|
||||||
EdXpConfigGlobal.getHookProvider().deoptMethodNative(method);
|
EdXpConfigGlobal.getHookProvider().deoptMethodNative(method);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
Utils.logE("Error when deoptimizing " + className + ":" + methodName, 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.os.Build;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.common.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;
|
||||||
|
|
@ -21,7 +21,7 @@ import de.robv.android.xposed.annotation.Level;
|
||||||
@ApiSensitive(Level.LOW)
|
@ApiSensitive(Level.LOW)
|
||||||
public class ClassLoaderUtils {
|
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) {
|
public static void replaceParentClassLoader(ClassLoader appClassLoader) {
|
||||||
if (appClassLoader == null) {
|
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 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.XposedHelpers;
|
||||||
import de.robv.android.xposed.annotation.ApiSensitive;
|
import de.robv.android.xposed.annotation.ApiSensitive;
|
||||||
|
|
@ -2,7 +2,7 @@ package com.elderdrivers.riru.edxp.yahfa.dexmaker;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.elderdrivers.riru.edxp.yahfa.BuildConfig;
|
import com.elderdrivers.riru.edxp.BuildConfig;
|
||||||
|
|
||||||
public class DexLog {
|
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;
|
||||||
import com.elderdrivers.riru.edxp.core.yahfa.HookMain;
|
import com.elderdrivers.riru.edxp.core.yahfa.HookMain;
|
||||||
import com.elderdrivers.riru.edxp.util.ProxyClassLoader;
|
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.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
|
@ -2,7 +2,7 @@ package com.swift.sandhook.xposedcompat.hookstub;
|
||||||
|
|
||||||
import android.util.Log;
|
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.SandHook;
|
||||||
import com.swift.sandhook.SandHookMethodResolver;
|
import com.swift.sandhook.SandHookMethodResolver;
|
||||||
import com.swift.sandhook.utils.ParamWrapper;
|
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