Skip to content

Commit

Permalink
Add EdXposed Service to update module path
Browse files Browse the repository at this point in the history
  • Loading branch information
LoveSy committed Dec 4, 2020
1 parent aaf1239 commit a094e36
Show file tree
Hide file tree
Showing 16 changed files with 501 additions and 22 deletions.
1 change: 1 addition & 0 deletions edxp-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ afterEvaluate {
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}")
}

Expand Down
17 changes: 11 additions & 6 deletions edxp-core/src/main/cpp/main/src/config_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ namespace edxp {
scope.emplace(std::move(app_pkg_name));
}
scope.insert(module_pkg_name); // Always add module itself
if (module_pkg_name == installer_pkg_name_) scope.erase("android");
LOGI("scope of %s is:\n%s", module_pkg_name.c_str(), ([&scope = scope]() {
std::ostringstream join;
std::copy(scope.begin(), scope.end(),
Expand Down Expand Up @@ -296,7 +297,8 @@ namespace edxp {
fs::perms::others_exec);
path_chown(prefs_path, uid, 0);
}
if (pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName) {
if (pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName ||
pkg_name == "android") {
auto conf_path = GetConfigPath();
if (!path_exists<true>(conf_path)) {
fs::create_directories(conf_path);
Expand All @@ -307,11 +309,14 @@ namespace edxp {
}
fs::permissions(conf_path, fs::perms::owner_all | fs::perms::group_all);
fs::permissions(log_path, fs::perms::owner_all | fs::perms::group_all);
if (const auto &[r_uid, r_gid] = path_own(conf_path); r_uid != uid) {
path_chown(conf_path, uid, 0, true);
if (pkg_name == "android") uid = -1;
if (const auto &[r_uid, r_gid] = path_own(conf_path);
(uid != -1 && r_uid != uid) || r_gid != 1000u) {
path_chown(conf_path, uid, 1000u, true);
}
if (const auto &[r_uid, r_gid] = path_own(log_path); r_uid != uid) {
path_chown(log_path, uid, 0, true);
if (const auto &[r_uid, r_gid] = path_own(log_path);
(uid != -1 && r_uid != uid) || r_gid != 1000u) {
path_chown(log_path, uid, 1000u, true);
}

if (pkg_name == kPrimaryInstallerPkgName) {
Expand All @@ -330,7 +335,7 @@ namespace edxp {
}
}

void ConfigManager::Init(){
void ConfigManager::Init() {
fs::path misc_path("/data/adb/edxp/misc_path");
try {
RirudSocket rirud_socket{};
Expand Down
2 changes: 2 additions & 0 deletions edxp-core/src/main/cpp/main/src/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ namespace edxp {

inline const auto &GetDataPathPrefix() const { return data_path_prefix_; }

inline static const auto &GetMiscPath() {return misc_path_;}

inline static auto GetFrameworkPath(const std::string &suffix = {}) {
return misc_path_ / "framework" / suffix;
}
Expand Down
76 changes: 64 additions & 12 deletions edxp-core/src/main/cpp/main/src/edxp_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace edxp {
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>());
Expand All @@ -88,16 +89,11 @@ namespace edxp {
jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
"([Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
jclass byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer");
jmethodID byte_buffer_wrap = JNI_GetStaticMethodID(env, byte_buffer_class, "wrap",
"([B)Ljava/nio/ByteBuffer;");
auto buffer_array = env->NewObjectArray(dexes.size(), byte_buffer_class, nullptr);
for (size_t i = 0; i != dexes.size(); ++i) {
const auto dex = dexes.at(i);
auto byte_array = env->NewByteArray(dex.size());
env->SetByteArrayRegion(byte_array, 0, dex.size(),
dex.data());
auto buffer = JNI_CallStaticObjectMethod(env, byte_buffer_class, byte_buffer_wrap,
byte_array);
auto dex = dexes.at(i);
auto buffer = env->NewDirectByteBuffer(reinterpret_cast<void *>(dex.data()),
dex.size());
env->SetObjectArrayElement(buffer_array, i, buffer);
}
jobject my_cl = env->NewObject(in_memory_classloader, initMid,
Expand Down Expand Up @@ -240,8 +236,67 @@ namespace edxp {
if (!skip_) {
PreLoadDex(ConfigManager::GetInjectDexPaths());
}
ConfigManager::GetInstance()->EnsurePermission("android", 1000);
}

void Context::RegisterEdxpService(JNIEnv *env) {
auto path = ConfigManager::GetFrameworkPath("edservice.dex");
std::ifstream is(path, std::ios::binary);
if (!is.good()) {
LOGE("Cannot load path %s", path.c_str());
return;
}
std::vector<unsigned char> dex{std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>()};
LOGD("Loaded %s with size %zu", path.c_str(), dex.size());

jclass classloader = JNI_FindClass(env, "java/lang/ClassLoader");
jmethodID getsyscl_mid = JNI_GetStaticMethodID(
env, classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid);

if (UNLIKELY(!sys_classloader)) {
LOGE("getSystemClassLoader failed!!!");
return;
}
// load dex
jobject bufferDex = env->NewDirectByteBuffer(reinterpret_cast<void *>(dex.data()),
dex.size());

jclass in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader");
jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "<init>",
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
jobject my_cl = JNI_NewObject(env, in_memory_classloader,
initMid,
bufferDex,
sys_classloader);

env->DeleteLocalRef(classloader);
env->DeleteLocalRef(sys_classloader);
env->DeleteLocalRef(in_memory_classloader);

if (UNLIKELY(my_cl == nullptr)) {
LOGE("InMemoryDexClassLoader creation failed!!!");
return;
}

auto service_class = (jclass) env->NewGlobalRef(
FindClassFromLoader(env, my_cl, "com.elderdrivers.riru.edxp.service.ServiceProxy"));
if (LIKELY(service_class)) {
jfieldID path_fid = JNI_GetStaticFieldID(env, service_class, "CONFIG_PATH",
"Ljava/lang/String;");
if (LIKELY(path_fid)) {
env->SetStaticObjectField(service_class, path_fid, env->NewStringUTF(
ConfigManager::GetMiscPath().c_str()));
jmethodID install_mid = JNI_GetStaticMethodID(env, service_class,
"install", "()V");
if (LIKELY(install_mid)) {
JNI_CallStaticVoidMethod(env, service_class, install_mid);
LOGW("Installed EdXposed Service");
}
}
}
}

int
Context::OnNativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) {
Expand All @@ -262,11 +317,8 @@ namespace edxp {
PrepareJavaEnv(env);
// only do work in child since FindAndCall would print log
FindAndCall(env, "forkSystemServerPost", "(I)V", res);
} else {
[[maybe_unused]] auto config_managers = ConfigManager::ReleaseInstances();
auto context = Context::ReleaseInstance();
LOGD("skipped android");
}
RegisterEdxpService(env);
} else {
// in zygote process, res is child zygote pid
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
Expand Down
2 changes: 2 additions & 0 deletions edxp-core/src/main/cpp/main/src/edxp_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ namespace edxp {
static std::tuple<bool, uid_t, std::string> GetAppInfoFromDir(JNIEnv *env, jstring dir, jstring nice_name);

friend std::unique_ptr<Context> std::make_unique<Context>();

static void RegisterEdxpService(JNIEnv *env);
};

}
1 change: 1 addition & 0 deletions edxp-core/template_override/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ extract "${ZIPFILE}" 'uninstall.sh' "${MODPATH}"
extract "${ZIPFILE}" 'system/framework/edconfig.jar' "${MODPATH}"
extract "${ZIPFILE}" 'system/framework/eddalvikdx.dex' "${MODPATH}"
extract "${ZIPFILE}" 'system/framework/eddexmaker.dex' "${MODPATH}"
extract "${ZIPFILE}" 'system/framework/edservice.dex' "${MODPATH}"
extract "${ZIPFILE}" 'system/framework/edxp.dex' "${MODPATH}"

if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
Expand Down
7 changes: 4 additions & 3 deletions edxp-core/template_override/post-fs-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ sepolicy() {
#fi

DEFAULT_BASE_PATH="${PATH_PREFIX}${EDXP_MANAGER}"
BASE_PATH="/data/misc/$(cat /data/adb/edxp/misc_path)/0"
BASE_PATH="/data/misc/$(cat /data/adb/edxp/misc_path)"

LOG_PATH="${BASE_PATH}/log"
CONF_PATH="${BASE_PATH}/conf"
LOG_PATH="${BASE_PATH}/0/log"
CONF_PATH="${BASE_PATH}/0/conf"
DISABLE_VERBOSE_LOG_FILE="${CONF_PATH}/disable_verbose_log"
LOG_VERBOSE=true
OLD_PATH=${PATH}
Expand Down Expand Up @@ -164,5 +164,6 @@ fi

chcon -R u:object_r:system_file:s0 "${MODDIR}"
chcon -R ${PATH_CONTEXT} "${LOG_PATH}"
chcon -R u:object_r:magisk_file:s0 $BASE_PATH
chown -R ${PATH_OWNER} "${LOG_PATH}"
chmod -R 666 "${LOG_PATH}"
2 changes: 2 additions & 0 deletions edxp-service/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/build
/template_override/system/framework
73 changes: 73 additions & 0 deletions edxp-service/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
apply plugin: 'com.android.application'

sourceCompatibility = "7"
targetCompatibility = "7"

android {
compileSdkVersion androidCompileSdkVersion.toInteger()

defaultConfig {
applicationId "com.elderdrivers.riru.edxp.yahfa"
minSdkVersion 26
targetSdkVersion 28
versionCode 1
versionName "1.0"
multiDexEnabled false
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

ndkVersion androidCompileNdkVersion
}

dependencies {
compileOnly project(':hiddenapi-stubs')
implementation project(':edxp-common')
}


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 << "-Xbootclasspath/p:${hiddenApiStubJarFilePath}"
}

android.applicationVariants.all { variant ->

def variantNameCapped = variant.name.capitalize()
def variantNameLowered = variant.name.toLowerCase()

task("copyDex${variantNameCapped}", type: Copy) {
dependsOn "assemble${variantNameCapped}"
dependsOn tasks.getByPath(":edxp-common:copyCommonProperties")
def dexOutPath = variant.name.contains("release") ?
"${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" :
"${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}"
from (dexOutPath){
rename("classes.dex", "edservice.dex")
}
destinationDir file(templateRootPath + "system/framework/")
outputs.upToDateWhen { false }
}

}
}
34 changes: 34 additions & 0 deletions edxp-service/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-dontoptimize
-dontobfuscate

-keep interface com.elderdrivers.riru.common.KeepAll
-keep interface com.elderdrivers.riru.common.KeepMembers

-keep class * implements com.elderdrivers.riru.common.KeepAll { *; }
-keepclassmembers class * implements com.elderdrivers.riru.common.KeepMembers { *; }

-keepclasseswithmembers class * {
native <methods>;
}
1 change: 1 addition & 0 deletions edxp-service/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<manifest package="com.elderdrivers.riru.edxp.service" />
Loading

0 comments on commit a094e36

Please sign in to comment.