merge all subprojects into one dex

This commit is contained in:
kotori0 2021-01-24 14:35:12 +08:00
parent 7885999285
commit 0ca163d021
No known key found for this signature in database
GPG Key ID: 3FEE57ED0385A6B2
650 changed files with 37013 additions and 902 deletions

View File

@ -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

View File

@ -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

2
dalvikdx/.gitignore vendored
View File

@ -1,2 +0,0 @@
/build
dex

View File

@ -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)
}
}
}

View File

@ -1 +0,0 @@
<manifest package="com.elderdrivers.riru.edxp.eddalvikdx" />

2
dexmaker/.gitignore vendored
View File

@ -1,2 +0,0 @@
/build
dex

View File

@ -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)
}
}
}

View File

@ -1 +0,0 @@
<manifest package="com.elderdrivers.riru.edxp.dexmaker" />

View File

@ -1 +0,0 @@
/build

View File

@ -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)
}
}

View File

@ -1 +0,0 @@
<manifest package="com.elderdrivers.riru.edxp.common" />

View File

@ -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
}
}
}

View File

@ -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());

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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();
}
}
}

View File

@ -0,0 +1,4 @@
/**
* Contains {@link android.app.AndroidAppHelper} with various methods for information about the current app.
*/
package android.app;

View File

@ -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);
}
}

View File

@ -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

View File

@ -0,0 +1,4 @@
/**
* Contains classes that are required for replacing resources.
*/
package android.content.res;

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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