[core] Delete native config manager
This commit is contained in:
parent
2890aec54f
commit
374c8cac11
|
|
@ -3,9 +3,17 @@ package io.github.lsposed.lspd.service;
|
||||||
interface ILSPApplicationService {
|
interface ILSPApplicationService {
|
||||||
void registerHeartBeat(IBinder handle) = 1;
|
void registerHeartBeat(IBinder handle) = 1;
|
||||||
|
|
||||||
int getVariant() = 2;
|
IBinder requestModuleBinder() = 2;
|
||||||
|
|
||||||
IBinder requestModuleBinder() = 3;
|
IBinder requestManagerBinder() = 3;
|
||||||
|
|
||||||
IBinder requestManagerBinder() = 4;
|
int getVariant() = 4;
|
||||||
|
|
||||||
|
boolean isResourcesHookEnabled() = 5;
|
||||||
|
|
||||||
|
List<String> getModulesList() = 6;
|
||||||
|
|
||||||
|
String getPrefsPath(String packageName) = 7;
|
||||||
|
|
||||||
|
String getCachePath(String fileName) = 8;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <base/object.h>
|
#include <base/object.h>
|
||||||
#include <config_manager.h>
|
|
||||||
|
|
||||||
namespace art {
|
namespace art {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ inline constexpr bool is64 = Is64();
|
||||||
static const auto kEntryClassName = "io.github.lsposed.lspd.core.Main"s;
|
static const auto kEntryClassName = "io.github.lsposed.lspd.core.Main"s;
|
||||||
static const auto kClassLinkerClassName = "io.github.lsposed.lspd.nativebridge.ClassLinker"s;
|
static const auto kClassLinkerClassName = "io.github.lsposed.lspd.nativebridge.ClassLinker"s;
|
||||||
static const auto kBridgeServiceClassName = "io.github.lsposed.lspd.service.BridgeService"s;
|
static const auto kBridgeServiceClassName = "io.github.lsposed.lspd.service.BridgeService"s;
|
||||||
|
static const auto kDexPath = "/data/adb/lspd/framework/lspd.dex"s;
|
||||||
static const auto kSandHookClassName = "com.swift.sandhook.SandHook"s;
|
static const auto kSandHookClassName = "com.swift.sandhook.SandHook"s;
|
||||||
static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"s;
|
static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"s;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,355 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <jni.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <array>
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <logging.h>
|
|
||||||
#include <climits>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include "art/runtime/native/native_util.h"
|
|
||||||
#include "config_manager.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "rirud_socket.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Logic:
|
|
||||||
* check if /data/adb/lspd exists and is readable, if so, read misc_path and the config base path is
|
|
||||||
* /data/misc/$misc_path; if not so, fall back to the installer's path
|
|
||||||
* config manager is const. and it should be updated if the module list is updated
|
|
||||||
* each user owns one config manager
|
|
||||||
* before the process started, update current user
|
|
||||||
* module list and modules scopes are preloaded
|
|
||||||
* can get app module list by call a const function
|
|
||||||
* for installer's pkg name, it's retrieved by /data/misc/$misc_path/$uid/conf/installer.
|
|
||||||
*
|
|
||||||
* Permission:
|
|
||||||
* /data/adb/lspd should be accessible by zygote by sepolicy
|
|
||||||
* /data/misc/$misc_path is random path, and mounted by magisk
|
|
||||||
* it should have context `u:object_r:magisk_file:s0`, which should be readable by normal app
|
|
||||||
* and zygote
|
|
||||||
*
|
|
||||||
* /data/misc/$misc_path's owner should be root:root, with permission 771
|
|
||||||
* so does /data/misc/$misc_path/$uid
|
|
||||||
* /data/misc/$misc_path/$uid/conf should be um:root, with permission 770
|
|
||||||
* where um is the user of manager
|
|
||||||
* /data/misc/$misc_path/$uid/prefs should be root:root, with permission 771
|
|
||||||
* /data/misc/$misc_path/$uid/prefs/$pkg should be up:root, with permission 771
|
|
||||||
* this path is used for XSharePreference, where up is the user of package $pkg
|
|
||||||
* other's permission is 5 because it should be read by all the other apps but not writable
|
|
||||||
* it's only writeable by $pkg itself
|
|
||||||
* root group's 7 permission's for updating the permission & deleting it
|
|
||||||
*
|
|
||||||
* Initialization:
|
|
||||||
* This is only done for config path in /data/misc
|
|
||||||
* check if /data/misc/$misc_path/$uid exists. if not create one with 771
|
|
||||||
* check if /data/misc/$misc_path/$uid/conf exists. if not create one with 770
|
|
||||||
* check if /data/misc/$misc_path/$uid/prefs exists. if not create one with 771
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* when the launching app is installer, change the user owner of /data/misc/$misc_path/$uid/conf
|
|
||||||
* to be the installer, and change the permission to be 770
|
|
||||||
*
|
|
||||||
* when the launching app is in the module lists, ensure existence of
|
|
||||||
* /data/misc/$misc_path/$uid/prefs/$pkg
|
|
||||||
* with the owner the user of the pkg and permission 774
|
|
||||||
* if this paths exists but with different owner, delete it recursively and create a new one
|
|
||||||
* this is when package reinstalled
|
|
||||||
* but I heard that some devices change uid when upgrading system, so I didn't do this
|
|
||||||
*
|
|
||||||
* Side effect:
|
|
||||||
* data exists if the module uninstalled
|
|
||||||
* One way to release the storage space is to uninstall lspd
|
|
||||||
* because /data/misc/$misc_path is mounted by magisk.
|
|
||||||
*
|
|
||||||
* lspd works without manager
|
|
||||||
*
|
|
||||||
* uninstall removes all configs (this can be restored if manager store another copy
|
|
||||||
* of the conf on its own data dir)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace lspd {
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
fs::path ConfigManager::RetrieveBaseConfigPath() const {
|
|
||||||
if (!misc_path_.empty()) {
|
|
||||||
return misc_path_ / std::to_string(user_);
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ConfigManager::RetrieveInstallerPkgName() const {
|
|
||||||
std::string installer_pkg_name_path = GetConfigPath("installer");
|
|
||||||
if (!path_exists<true>(installer_pkg_name_path)) {
|
|
||||||
LOGW("installer not set, using default one %s", kPrimaryInstallerPkgName.c_str());
|
|
||||||
return kPrimaryInstallerPkgName;
|
|
||||||
}
|
|
||||||
std::ifstream ifs(installer_pkg_name_path);
|
|
||||||
if (!ifs.good()) {
|
|
||||||
LOGW("cannot access %s, using default one %s", installer_pkg_name_path.c_str(),
|
|
||||||
kPrimaryInstallerPkgName.c_str());
|
|
||||||
return kPrimaryInstallerPkgName;
|
|
||||||
}
|
|
||||||
return {std::istream_iterator<char>(ifs), std::istream_iterator<char>()};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ConfigManager::GetPackageNameFromBaseApkPath(const fs::path &path) {
|
|
||||||
std::vector<std::string> paths(path.begin(), path.end());
|
|
||||||
if (paths.empty()) return {};
|
|
||||||
auto base_apk = paths.back(); // base.apk
|
|
||||||
if (base_apk != "base.apk") return {};
|
|
||||||
paths.pop_back();
|
|
||||||
auto pkg_name_with_obfuscation = paths.back();
|
|
||||||
if (auto pos = pkg_name_with_obfuscation.find('-'); pos != std::string::npos) {
|
|
||||||
return pkg_name_with_obfuscation.substr(0, pos);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigManager::ConfigManager(uid_t user, bool initialized) :
|
|
||||||
user_(user),
|
|
||||||
data_path_prefix_(fs::path("/data/user_de") /
|
|
||||||
std::to_string(user_)),
|
|
||||||
base_config_path_(RetrieveBaseConfigPath()),
|
|
||||||
initialized_(initialized || InitConfigPath()),
|
|
||||||
installer_pkg_name_(RetrieveInstallerPkgName()),
|
|
||||||
no_module_log_enabled_(path_exists(GetConfigPath("disable_modules_log"))),
|
|
||||||
resources_hook_enabled_(path_exists(GetConfigPath("enable_resources"))),
|
|
||||||
modules_list_(GetModuleList()),
|
|
||||||
last_write_time_(GetLastWriteTime()),
|
|
||||||
variant_(ReadInt(GetVariantPath())),
|
|
||||||
selinux_permissive_(ReadInt(GetSelinuxStatusPath()) != 1) {
|
|
||||||
LOGI("base config path: %s", base_config_path_.c_str());
|
|
||||||
LOGI(" using installer package name: %s", installer_pkg_name_.c_str());
|
|
||||||
LOGI(" no module log: %s", BoolToString(no_module_log_enabled_));
|
|
||||||
LOGI(" resources hook: %s", BoolToString(resources_hook_enabled_));
|
|
||||||
LOGI(" selinux permissive: %s", BoolToString(selinux_permissive_));
|
|
||||||
LOGI(" module list: \n %s", ([this]() {
|
|
||||||
std::ostringstream join;
|
|
||||||
std::vector<std::string> module_list;
|
|
||||||
std::transform(modules_list_.begin(), modules_list_.end(),
|
|
||||||
std::back_inserter(module_list),
|
|
||||||
[](auto i) { return i.first; });
|
|
||||||
std::copy(module_list.begin(), module_list.end(),
|
|
||||||
std::ostream_iterator<std::string>(join, "\n"));
|
|
||||||
return join.str();
|
|
||||||
})().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
int ConfigManager::ReadInt(const fs::path &dir) {
|
|
||||||
if (!path_exists(dir)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
std::ifstream ifs(dir);
|
|
||||||
if (!ifs.good()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int result;
|
|
||||||
ifs >> result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ConfigManager::GetModuleList() -> std::remove_const_t<decltype(modules_list_)> {
|
|
||||||
std::remove_const_t<decltype(modules_list_)> modules_list;
|
|
||||||
auto global_modules_list = GetConfigPath("modules.list");
|
|
||||||
if (!path_exists(global_modules_list)) {
|
|
||||||
LOGE("Cannot access path %s", global_modules_list.c_str());
|
|
||||||
return modules_list;
|
|
||||||
}
|
|
||||||
std::ifstream ifs(global_modules_list);
|
|
||||||
if (!ifs.good()) {
|
|
||||||
LOGE("Cannot access path %s", global_modules_list.c_str());
|
|
||||||
return modules_list;
|
|
||||||
}
|
|
||||||
std::string module;
|
|
||||||
while (std::getline(ifs, module)) {
|
|
||||||
const auto &module_pkg_name = GetPackageNameFromBaseApkPath(module);
|
|
||||||
auto &[module_path, scope] = modules_list[module_pkg_name];
|
|
||||||
scope.insert(module_pkg_name); // Always add module itself
|
|
||||||
module_path.assign(std::move(module));
|
|
||||||
const auto &module_scope_conf = GetConfigPath(module_pkg_name + ".conf");
|
|
||||||
if (!path_exists<true>(module_scope_conf)) {
|
|
||||||
LOGD("module scope is not set for %s", module_pkg_name.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::ifstream ifs_c(module_scope_conf);
|
|
||||||
if (!ifs_c.good()) {
|
|
||||||
LOGE("Cannot access path %s", module_scope_conf.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string app_pkg_name;
|
|
||||||
while (std::getline(ifs_c, app_pkg_name)) {
|
|
||||||
if (!app_pkg_name.empty())
|
|
||||||
scope.emplace(std::move(app_pkg_name));
|
|
||||||
}
|
|
||||||
if (IsInstaller(module_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(),
|
|
||||||
std::ostream_iterator<std::string>(join, "\n "));
|
|
||||||
return join.str();
|
|
||||||
})().c_str());
|
|
||||||
}
|
|
||||||
return modules_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> ConfigManager::GetAppModuleList(const std::string &pkg_name) const {
|
|
||||||
std::vector<std::string> app_modules_list;
|
|
||||||
for (const auto&[module, scope]: modules_list_) {
|
|
||||||
if (scope.second.count(pkg_name))
|
|
||||||
app_modules_list.push_back(scope.first);
|
|
||||||
}
|
|
||||||
return app_modules_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::file_time_type ConfigManager::GetLastWriteTime() const {
|
|
||||||
auto last_write_time = [](std::string_view path) __attribute__((always_inline)) {
|
|
||||||
return path_exists<true>(path) ? fs::last_write_time(path) : fs::file_time_type{};
|
|
||||||
};
|
|
||||||
std::string config_path = GetConfigPath();
|
|
||||||
std::string list_path = GetConfigPath("modules.list");
|
|
||||||
std::string variant_path = GetVariantPath();
|
|
||||||
return std::max({
|
|
||||||
last_write_time(config_path),
|
|
||||||
last_write_time(list_path),
|
|
||||||
last_write_time(variant_path)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConfigManager::InitConfigPath() const {
|
|
||||||
if (base_config_path_.empty()) return false;
|
|
||||||
try {
|
|
||||||
fs::create_directories(base_config_path_);
|
|
||||||
fs::permissions(misc_path_,
|
|
||||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
|
||||||
fs::permissions(base_config_path_,
|
|
||||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
|
||||||
fs::create_directories(GetLogPath());
|
|
||||||
fs::permissions(GetLogPath(),
|
|
||||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
|
||||||
fs::create_directories(GetConfigPath());
|
|
||||||
fs::permissions(GetConfigPath(), fs::perms::owner_all | fs::perms::group_all);
|
|
||||||
fs::create_directories(GetPrefsPath(""));
|
|
||||||
fs::permissions(GetPrefsPath(""),
|
|
||||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
|
||||||
auto log_path = GetLogPath();
|
|
||||||
auto modules_log_path = GetModulesLogPath();
|
|
||||||
if (!fs::is_directory(log_path)) {
|
|
||||||
fs::remove(log_path);
|
|
||||||
}
|
|
||||||
if (!path_exists(log_path)) {
|
|
||||||
fs::create_directories(modules_log_path);
|
|
||||||
}
|
|
||||||
if (!path_exists<true>(modules_log_path)) {
|
|
||||||
std::ofstream(modules_log_path, std::ios::out);
|
|
||||||
}
|
|
||||||
fs::permissions(log_path,
|
|
||||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all);
|
|
||||||
recursive_permissions(log_path,
|
|
||||||
fs::perms::owner_read | fs::perms::owner_write |
|
|
||||||
fs::perms::group_read |
|
|
||||||
fs::perms::group_write | fs::perms::others_read |
|
|
||||||
fs::perms::others_write, fs::perm_options::add);
|
|
||||||
} catch (const fs::filesystem_error &e) {
|
|
||||||
LOGE("init: %s", e.what());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigManager::EnsurePermission(const std::string &pkg_name, uid_t uid) const {
|
|
||||||
if (!initialized_) return;
|
|
||||||
try {
|
|
||||||
if (modules_list_.count(pkg_name)) {
|
|
||||||
auto prefs_path = GetPrefsPath(pkg_name);
|
|
||||||
if (!path_exists<true>(prefs_path)) {
|
|
||||||
fs::create_directories(prefs_path);
|
|
||||||
} else {
|
|
||||||
const auto &[r_uid, r_gid] = path_own(prefs_path);
|
|
||||||
if (r_uid != uid) {
|
|
||||||
fs::remove_all(prefs_path);
|
|
||||||
fs::create_directories(prefs_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs::permissions(prefs_path, fs::perms::owner_all | fs::perms::group_all |
|
|
||||||
fs::perms::others_exec | fs::perms::set_gid);
|
|
||||||
if (const auto &[r_uid, r_gid] = path_own(prefs_path);
|
|
||||||
(uid != -1 && r_uid != uid) || r_gid != 1000u) {
|
|
||||||
path_chown(prefs_path, uid, 1000u, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (IsInstaller(pkg_name) || pkg_name == "android") {
|
|
||||||
auto conf_path = GetConfigPath();
|
|
||||||
if (!path_exists<true>(conf_path)) {
|
|
||||||
fs::create_directories(conf_path);
|
|
||||||
}
|
|
||||||
recursive_permissions(conf_path, fs::perms::owner_all | fs::perms::group_all |
|
|
||||||
fs::perms::set_gid);
|
|
||||||
if (pkg_name == "android") uid = -1;
|
|
||||||
path_chown(conf_path, uid, 1000u, true);
|
|
||||||
if (current_user_ == 0) {
|
|
||||||
auto variant = GetVariantPath();
|
|
||||||
fs::permissions(variant, fs::perms::owner_all | fs::perms::group_all);
|
|
||||||
path_chown(variant, uid, 1000u);
|
|
||||||
auto disable_verbose_log = misc_path_ / "disable_verbose_log";
|
|
||||||
fs::permissions(disable_verbose_log,
|
|
||||||
fs::perms::owner_all | fs::perms::group_all);
|
|
||||||
path_chown(disable_verbose_log, uid, 1000u);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pkg_name == kPrimaryInstallerPkgName) {
|
|
||||||
umask(0007);
|
|
||||||
auto installer_pkg_name_path = GetConfigPath("installer");
|
|
||||||
if (path_exists<true>(installer_pkg_name_path)) {
|
|
||||||
fs::remove(installer_pkg_name_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (const fs::filesystem_error &e) {
|
|
||||||
LOGE("%s", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigManager::Init() {
|
|
||||||
fs::path misc_path("/data/adb/lspd/misc_path");
|
|
||||||
try {
|
|
||||||
RirudSocket rirud_socket{};
|
|
||||||
auto path = rirud_socket.ReadFile(misc_path);
|
|
||||||
path.erase(std::find_if(path.rbegin(), path.rend(), [](unsigned char ch) {
|
|
||||||
return !std::isspace(ch);
|
|
||||||
}).base(), path.end());
|
|
||||||
misc_path_ = fs::path("/data/misc") / path;
|
|
||||||
inject_dex_path_ = GetFrameworkPath(kXposedInjectDexPath);
|
|
||||||
LOGI("Got base config path: %s", misc_path_.c_str());
|
|
||||||
} catch (const RirudSocket::RirudSocketException &e) {
|
|
||||||
LOGE("%s", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include "JNIHelper.h"
|
|
||||||
#include <utility>
|
|
||||||
#include <art/runtime/native/native_util.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "config.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
namespace lspd {
|
|
||||||
|
|
||||||
class ConfigManager {
|
|
||||||
private:
|
|
||||||
inline static const auto kPrimaryInstallerPkgName = "io.github.lsposed.manager"s;
|
|
||||||
inline static const auto kXposedInjectDexPath = "lspd.dex";
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void Init();
|
|
||||||
|
|
||||||
inline static ConfigManager *GetInstance() {
|
|
||||||
return instances_[current_user_].get();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto IsInitialized() const { return initialized_; }
|
|
||||||
|
|
||||||
inline static void SetCurrentUser(uid_t user) {
|
|
||||||
if (auto instance = instances_.find(user);
|
|
||||||
instance == instances_.end() || !instance->second) {
|
|
||||||
instances_[user] = std::make_unique<ConfigManager>(user);
|
|
||||||
} else if (instance->second->NeedUpdateConfig()) {
|
|
||||||
instances_[user] = std::make_unique<ConfigManager>(user,
|
|
||||||
instance->second->IsInitialized());
|
|
||||||
}
|
|
||||||
current_user_ = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static auto ReleaseInstances() {
|
|
||||||
return std::move(instances_);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const auto &GetVariant() const { return variant_; }
|
|
||||||
|
|
||||||
inline const auto &IsResourcesHookEnabled() const { return resources_hook_enabled_; }
|
|
||||||
|
|
||||||
inline const auto &IsNoModuleLogEnabled() const { return no_module_log_enabled_; }
|
|
||||||
|
|
||||||
inline const auto &GetInstallerPackageName() const { return installer_pkg_name_; }
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static auto GetCachePath(const std::string &suffix = {}) {
|
|
||||||
return misc_path_ / "cache" / suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto GetConfigPath(const std::string &suffix = {}) const {
|
|
||||||
return base_config_path_ / "conf" / suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static auto GetLogPath(const std::string &suffix = {}) {
|
|
||||||
return misc_path_ / "log" / suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const auto &GetBaseConfigPath() const { return base_config_path_; }
|
|
||||||
|
|
||||||
inline auto GetPrefsPath(const std::string &pkg_name) const {
|
|
||||||
return base_config_path_ / "prefs" / pkg_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static auto GetVariantPath() {
|
|
||||||
return misc_path_ / "variant";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static std::filesystem::path GetSelinuxStatusPath() {
|
|
||||||
return "/sys/fs/selinux/enforce";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static auto GetModulesLogPath() {
|
|
||||||
return GetLogPath("modules.log");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> GetAppModuleList(const std::string &pkg_name) const;
|
|
||||||
|
|
||||||
bool NeedUpdateConfig() const {
|
|
||||||
return last_write_time_ < GetLastWriteTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnsurePermission(const std::string &pkg_name, uid_t uid) const;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsPermissive() const {
|
|
||||||
return selinux_permissive_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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_; // /data/misc/lspd_xxxx
|
|
||||||
inline static std::filesystem::path inject_dex_path_;
|
|
||||||
|
|
||||||
const uid_t user_;
|
|
||||||
const int variant_;
|
|
||||||
const std::filesystem::path data_path_prefix_; // /data/user_de/{user}
|
|
||||||
const std::filesystem::path base_config_path_; // /data/misc/lspd_xxxx/{user}
|
|
||||||
const bool initialized_ = false;
|
|
||||||
const std::filesystem::path installer_pkg_name_;
|
|
||||||
const bool no_module_log_enabled_ = false;
|
|
||||||
const bool resources_hook_enabled_ = false;
|
|
||||||
const bool selinux_permissive_ = false;
|
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::pair<std::string, std::unordered_set<std::string>>> modules_list_;
|
|
||||||
|
|
||||||
const std::filesystem::file_time_type last_write_time_;
|
|
||||||
|
|
||||||
ConfigManager(uid_t uid, bool initialized = false);
|
|
||||||
|
|
||||||
std::string RetrieveInstallerPkgName() const;
|
|
||||||
|
|
||||||
static std::string GetPackageNameFromBaseApkPath(const std::filesystem::path &path);
|
|
||||||
|
|
||||||
std::remove_const_t<decltype(modules_list_)> GetModuleList();
|
|
||||||
|
|
||||||
std::filesystem::file_time_type GetLastWriteTime() const;
|
|
||||||
|
|
||||||
bool InitConfigPath() const;
|
|
||||||
|
|
||||||
friend std::unique_ptr<ConfigManager> std::make_unique<ConfigManager>(uid_t &);
|
|
||||||
|
|
||||||
friend std::unique_ptr<ConfigManager> std::make_unique<ConfigManager>(uid_t &, bool &&);
|
|
||||||
|
|
||||||
std::filesystem::path RetrieveBaseConfigPath() const;
|
|
||||||
|
|
||||||
static int ReadInt(const std::filesystem::path &dir);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lspd
|
|
||||||
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
#include "JNIHelper.h"
|
#include "JNIHelper.h"
|
||||||
#include "jni/config_manager.h"
|
|
||||||
#include "jni/art_class_linker.h"
|
#include "jni/art_class_linker.h"
|
||||||
#include "jni/yahfa.h"
|
#include "jni/yahfa.h"
|
||||||
#include "jni/resources_hook.h"
|
#include "jni/resources_hook.h"
|
||||||
|
|
@ -32,12 +31,13 @@
|
||||||
#include <sandhook.h>
|
#include <sandhook.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <nativehelper/scoped_local_ref.h>
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "config_manager.h"
|
|
||||||
#include "native_hook.h"
|
#include "native_hook.h"
|
||||||
#include "jni/logger.h"
|
#include "jni/logger.h"
|
||||||
#include "jni/native_api.h"
|
#include "jni/native_api.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "rirud_socket.h"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
@ -66,13 +66,14 @@ namespace lspd {
|
||||||
void Context::PreLoadDex(const fs::path &dex_path) {
|
void Context::PreLoadDex(const fs::path &dex_path) {
|
||||||
if (LIKELY(!dex.empty())) return;
|
if (LIKELY(!dex.empty())) return;
|
||||||
|
|
||||||
std::ifstream is(dex_path, std::ios::binary);
|
try {
|
||||||
if (!is.good()) {
|
RirudSocket socket;
|
||||||
LOGE("Cannot load path %s", dex_path.c_str());
|
auto dex_content = socket.ReadFile(dex_path);
|
||||||
|
dex.assign(dex_content.begin(), dex_content.end());
|
||||||
|
} catch (RirudSocket::RirudSocketException &e) {
|
||||||
|
LOGE("%s", e.what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dex.assign(std::istreambuf_iterator<char>(is),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
LOGI("Loaded %s with size %zu", dex_path.c_str(), dex.size());
|
LOGI("Loaded %s with size %zu", dex_path.c_str(), dex.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,9 +109,6 @@ namespace lspd {
|
||||||
env->DeleteLocalRef(my_cl);
|
env->DeleteLocalRef(my_cl);
|
||||||
|
|
||||||
env->GetJavaVM(&vm_);
|
env->GetJavaVM(&vm_);
|
||||||
|
|
||||||
// Make sure config manager is always working
|
|
||||||
RegisterConfigManagerMethods(env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::Init(JNIEnv *env) {
|
void Context::Init(JNIEnv *env) {
|
||||||
|
|
@ -193,7 +191,6 @@ namespace lspd {
|
||||||
void
|
void
|
||||||
Context::OnNativeForkSystemServerPre(JNIEnv *env) {
|
Context::OnNativeForkSystemServerPre(JNIEnv *env) {
|
||||||
Service::instance()->InitService(env);
|
Service::instance()->InitService(env);
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
|
||||||
skip_ = false;
|
skip_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,7 +223,6 @@ namespace lspd {
|
||||||
jstring nice_name,
|
jstring nice_name,
|
||||||
jboolean is_child_zygote,
|
jboolean is_child_zygote,
|
||||||
jstring app_data_dir) {
|
jstring app_data_dir) {
|
||||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
|
||||||
Service::instance()->InitService(env);
|
Service::instance()->InitService(env);
|
||||||
const auto app_id = uid % PER_USER_RANGE;
|
const auto app_id = uid % PER_USER_RANGE;
|
||||||
nice_name_ = nice_name;
|
nice_name_ = nice_name;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ namespace lspd {
|
||||||
|
|
||||||
void OnNativeForkSystemServerPre(JNIEnv *env);
|
void OnNativeForkSystemServerPre(JNIEnv *env);
|
||||||
|
|
||||||
|
void PreLoadDex(const std::filesystem::path &dex_paths);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>();
|
inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>();
|
||||||
|
|
@ -79,8 +80,6 @@ namespace lspd {
|
||||||
|
|
||||||
Context() {}
|
Context() {}
|
||||||
|
|
||||||
void PreLoadDex(const std::filesystem::path &dex_paths);
|
|
||||||
|
|
||||||
void LoadDex(JNIEnv *env);
|
void LoadDex(JNIEnv *env);
|
||||||
|
|
||||||
void Init(JNIEnv *env);
|
void Init(JNIEnv *env);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <nativehelper/jni_macros.h>
|
#include <nativehelper/jni_macros.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <HookMain.h>
|
#include <HookMain.h>
|
||||||
|
#include <unordered_set>
|
||||||
#include "art_class_linker.h"
|
#include "art_class_linker.h"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
|
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config_manager.h>
|
|
||||||
#include <nativehelper/jni_macros.h>
|
|
||||||
#include <native_util.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include "config_manager.h"
|
|
||||||
|
|
||||||
namespace lspd {
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isResourcesHookEnabled) {
|
|
||||||
return (jboolean) ConfigManager::GetInstance()->IsResourcesHookEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getInstallerPackageName) {
|
|
||||||
return env->NewStringUTF(ConfigManager::GetInstance()->GetInstallerPackageName().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getDataPathPrefix) {
|
|
||||||
return env->NewStringUTF(ConfigManager::GetInstance()->GetDataPathPrefix().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getLogPath) {
|
|
||||||
return env->NewStringUTF(ConfigManager::GetLogPath().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getConfigPath, jstring jSuffix) {
|
|
||||||
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
|
|
||||||
auto result = ConfigManager::GetInstance()->GetConfigPath(suffix);
|
|
||||||
env->ReleaseStringUTFChars(jSuffix, suffix);
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getPrefsPath, jstring jSuffix) {
|
|
||||||
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
|
|
||||||
auto result = ConfigManager::GetInstance()->GetPrefsPath(suffix);
|
|
||||||
env->ReleaseStringUTFChars(jSuffix, suffix);
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getCachePath, jstring jSuffix) {
|
|
||||||
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
|
|
||||||
auto result = ConfigManager::GetCachePath(suffix);
|
|
||||||
env->ReleaseStringUTFChars(jSuffix, suffix);
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getBaseConfigPath) {
|
|
||||||
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getMiscPath) {
|
|
||||||
auto result = ConfigManager::GetMiscPath();
|
|
||||||
return env->NewStringUTF(result.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getModulesList) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isPermissive) {
|
|
||||||
return ConfigManager::GetInstance()->IsPermissive();
|
|
||||||
}
|
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, isResourcesHookEnabled, "()Z"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getInstallerPackageName, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getDataPathPrefix, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getMiscPath, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getLogPath, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getPrefsPath,
|
|
||||||
"(Ljava/lang/String;)Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getCachePath,
|
|
||||||
"(Ljava/lang/String;)Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getBaseConfigPath, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
|
|
||||||
LSP_NATIVE_METHOD(ConfigManager, isPermissive, "()Z"),
|
|
||||||
};
|
|
||||||
|
|
||||||
void RegisterConfigManagerMethods(JNIEnv *env) {
|
|
||||||
REGISTER_LSP_NATIVE_METHODS(ConfigManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "jni.h"
|
|
||||||
|
|
||||||
namespace lspd {
|
|
||||||
|
|
||||||
void RegisterConfigManagerMethods(JNIEnv *env);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -22,22 +22,22 @@
|
||||||
#include "nativehelper/jni_macros.h"
|
#include "nativehelper/jni_macros.h"
|
||||||
#include "native_util.h"
|
#include "native_util.h"
|
||||||
#include "JNIHelper.h"
|
#include "JNIHelper.h"
|
||||||
#include "../config_manager.h"
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
LSP_DEF_NATIVE_METHOD(void, Logger, nativeLog, jstring jstr) {
|
LSP_DEF_NATIVE_METHOD(void, Logger, nativeLog, jstring jstr) {
|
||||||
static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY);
|
// TODO: get log path
|
||||||
if (fd < 0) {
|
// static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY);
|
||||||
LOGD("Logger fail: %s", strerror(errno));
|
// if (fd < 0) {
|
||||||
return;
|
// LOGD("Logger fail: %s", strerror(errno));
|
||||||
}
|
// return;
|
||||||
JUTFString str(env, jstr);
|
// }
|
||||||
int res = write(fd, str.get(), std::strlen(str.get()));
|
// JUTFString str(env, jstr);
|
||||||
if (res < 0) {
|
// int res = write(fd, str.get(), std::strlen(str.get()));
|
||||||
LOGD("Logger fail: %s", strerror(errno));
|
// if (res < 0) {
|
||||||
}
|
// LOGD("Logger fail: %s", strerror(errno));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,14 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include <riru.h>
|
#include <riru.h>
|
||||||
#include "config_manager.h"
|
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
static void onModuleLoaded() {
|
static void onModuleLoaded() {
|
||||||
LOGI("onModuleLoaded: welcome to LSPosed!");
|
LOGI("onModuleLoaded: welcome to LSPosed!");
|
||||||
// rirud must be used in onModuleLoaded
|
// rirud must be used in onModuleLoaded
|
||||||
|
Context::GetInstance()->PreLoadDex(kDexPath);
|
||||||
InitSymbolCache();
|
InitSymbolCache();
|
||||||
ConfigManager::Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shouldSkipUid(int) {
|
static int shouldSkipUid(int) {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <config_manager.h>
|
|
||||||
#include <art/runtime/runtime.h>
|
#include <art/runtime/runtime.h>
|
||||||
#include <dl_util.h>
|
#include <dl_util.h>
|
||||||
#include <art/runtime/jni_env_ext.h>
|
#include <art/runtime/jni_env_ext.h>
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,10 @@ namespace lspd {
|
||||||
|
|
||||||
jobject service = nullptr;
|
jobject service = nullptr;
|
||||||
if (res) {
|
if (res) {
|
||||||
JNI_CallVoidMethod(env, reply, readExceptionMethod_);
|
env->CallVoidMethod(reply, readExceptionMethod_);
|
||||||
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
if (!ClearException(env)) {
|
||||||
|
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
JNI_CallVoidMethod(env, data, recycleMethod_);
|
JNI_CallVoidMethod(env, data, recycleMethod_);
|
||||||
JNI_CallVoidMethod(env, reply, recycleMethod_);
|
JNI_CallVoidMethod(env, reply, recycleMethod_);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ import java.util.Set;
|
||||||
|
|
||||||
import de.robv.android.xposed.services.FileResult;
|
import de.robv.android.xposed.services.FileResult;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is basically the same as SharedPreferencesImpl from AOSP, but
|
* This class is basically the same as SharedPreferencesImpl from AOSP, but
|
||||||
* read-only and without listeners support. Instead, it is made to be
|
* read-only and without listeners support. Instead, it is made to be
|
||||||
|
|
@ -180,8 +182,9 @@ public final class XSharedPreferences implements SharedPreferences {
|
||||||
newModule = isModule && (xposedminversion > 92 || xposedsharedprefs);
|
newModule = isModule && (xposedminversion > 92 || xposedsharedprefs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newModule && XposedInit.prefsBasePath != null) {
|
if (newModule) {
|
||||||
mFile = new File(XposedInit.prefsBasePath, packageName + "/" + prefFileName + ".xml");
|
|
||||||
|
mFile = new File(serviceClient.getPrefsPath( packageName ), prefFileName + ".xml");
|
||||||
} else {
|
} else {
|
||||||
mFile = new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/" + prefFileName + ".xml");
|
mFile = new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/" + prefFileName + ".xml");
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +201,8 @@ public final class XSharedPreferences implements SharedPreferences {
|
||||||
Path path = mFile.toPath();
|
Path path = mFile.toPath();
|
||||||
try {
|
try {
|
||||||
if (sWatcher == null) {
|
if (sWatcher == null) {
|
||||||
sWatcher = new File(XposedInit.prefsBasePath).toPath().getFileSystem().newWatchService();
|
// TODO
|
||||||
|
// sWatcher = new File(XposedInit.prefsBasePath).toPath().getFileSystem().newWatchService();
|
||||||
if (BuildConfig.DEBUG) Log.d(TAG, "Created WatchService instance");
|
if (BuildConfig.DEBUG) Log.d(TAG, "Created WatchService instance");
|
||||||
}
|
}
|
||||||
mWatchKey = path.getParent().register(sWatcher, StandardWatchEventKinds.ENTRY_CREATE,
|
mWatchKey = path.getParent().register(sWatcher, StandardWatchEventKinds.ENTRY_CREATE,
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import android.content.res.TypedArray;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.BuildConfig;
|
import io.github.lsposed.lspd.BuildConfig;
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||||
|
|
||||||
import java.lang.reflect.AccessibleObject;
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
|
@ -98,15 +97,6 @@ public final class XposedBridge {
|
||||||
|
|
||||||
private XposedBridge() {}
|
private XposedBridge() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when native methods and other things are initialized, but before preloading classes etc.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void main(String[] args) {
|
|
||||||
// ed: moved
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
// protected static final class ToolEntryPoint {
|
// protected static final class ToolEntryPoint {
|
||||||
// protected static void main(String[] args) {
|
// protected static void main(String[] args) {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.os.ZygoteInit;
|
import com.android.internal.os.ZygoteInit;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
|
@ -49,6 +48,7 @@ import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
@ -77,6 +77,7 @@ import static de.robv.android.xposed.XposedHelpers.getParameterIndexByType;
|
||||||
import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField;
|
import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField;
|
||||||
import static de.robv.android.xposed.XposedHelpers.setStaticLongField;
|
import static de.robv.android.xposed.XposedHelpers.setStaticLongField;
|
||||||
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
|
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
public final class XposedInit {
|
public final class XposedInit {
|
||||||
private static final String TAG = XposedBridge.TAG;
|
private static final String TAG = XposedBridge.TAG;
|
||||||
|
|
@ -86,7 +87,6 @@ public final class XposedInit {
|
||||||
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
|
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
|
||||||
public static volatile boolean disableResources = false;
|
public static volatile boolean disableResources = false;
|
||||||
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
|
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
|
||||||
public static String prefsBasePath = null;
|
|
||||||
|
|
||||||
private XposedInit() {
|
private XposedInit() {
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +113,7 @@ public final class XposedInit {
|
||||||
|
|
||||||
@ApiSensitive(Level.MIDDLE)
|
@ApiSensitive(Level.MIDDLE)
|
||||||
private static void hookResources() throws Throwable {
|
private static void hookResources() throws Throwable {
|
||||||
if (!ConfigManager.isResourcesHookEnabled() || disableResources) {
|
if (!serviceClient.isResourcesHookEnabled() || disableResources) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -353,12 +353,9 @@ public final class XposedInit {
|
||||||
topClassLoader = parent;
|
topClassLoader = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
String moduleList = ConfigManager.getModulesList();
|
List<String> moduleList = serviceClient.getModulesList();
|
||||||
InputStream stream = new ByteArrayInputStream(moduleList.getBytes());
|
|
||||||
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
|
|
||||||
ArraySet<String> newLoadedApk = new ArraySet<>();
|
ArraySet<String> newLoadedApk = new ArraySet<>();
|
||||||
String apk;
|
for (String apk : moduleList)
|
||||||
while ((apk = apks.readLine()) != null) {
|
|
||||||
if (loadedModules.contains(apk)) {
|
if (loadedModules.contains(apk)) {
|
||||||
newLoadedApk.add(apk);
|
newLoadedApk.add(apk);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -368,10 +365,9 @@ public final class XposedInit {
|
||||||
newLoadedApk.add(apk);
|
newLoadedApk.add(apk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
loadedModules.clear();
|
loadedModules.clear();
|
||||||
loadedModules.addAll(newLoadedApk);
|
loadedModules.addAll(newLoadedApk);
|
||||||
apks.close();
|
|
||||||
|
|
||||||
// refresh callback according to current loaded module list
|
// refresh callback according to current loaded module list
|
||||||
pruneCallbacks(loadedModules);
|
pruneCallbacks(loadedModules);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
package io.github.lsposed.lspd.config;
|
||||||
|
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.github.lsposed.lspd.service.ILSPApplicationService;
|
||||||
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
|
public class LSPApplicationServiceClient implements ILSPApplicationService {
|
||||||
|
static ILSPApplicationService service = null;
|
||||||
|
static IBinder serviceBinder = null;
|
||||||
|
|
||||||
|
static String baseCachePath = null;
|
||||||
|
static String basePrefsPath = null;
|
||||||
|
|
||||||
|
public static LSPApplicationServiceClient serviceClient = null;
|
||||||
|
|
||||||
|
public static void Init(IBinder binder) {
|
||||||
|
if (serviceClient == null && binder != null && serviceBinder == null && service == null) {
|
||||||
|
serviceBinder = binder;
|
||||||
|
try {
|
||||||
|
serviceBinder.linkToDeath(() -> {
|
||||||
|
serviceBinder = null;
|
||||||
|
service = null;
|
||||||
|
}, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Utils.logE("link to death error: ", e);
|
||||||
|
}
|
||||||
|
service = ILSPApplicationService.Stub.asInterface(binder);
|
||||||
|
serviceClient = new LSPApplicationServiceClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerHeartBeat(IBinder handle) {
|
||||||
|
if (service == null || serviceBinder == null) {
|
||||||
|
Utils.logE("Register Failed: service is null");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
service.registerHeartBeat(handle);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Utils.logE("register heart beat failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder requestModuleBinder() {
|
||||||
|
try {
|
||||||
|
return service.requestModuleBinder();
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder requestManagerBinder() {
|
||||||
|
try {
|
||||||
|
return service.requestManagerBinder();
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getVariant() {
|
||||||
|
try {
|
||||||
|
return service.getVariant();
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResourcesHookEnabled() {
|
||||||
|
try {
|
||||||
|
return service.isResourcesHookEnabled();
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getModulesList() {
|
||||||
|
try {
|
||||||
|
return service.getModulesList();
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrefsPath(String packageName) {
|
||||||
|
try {
|
||||||
|
if (basePrefsPath == null)
|
||||||
|
basePrefsPath = service.getPrefsPath("");
|
||||||
|
return basePrefsPath + File.separator + packageName;
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCachePath(String fileName) {
|
||||||
|
try {
|
||||||
|
if (baseCachePath == null)
|
||||||
|
baseCachePath = service.getCachePath("");
|
||||||
|
return baseCachePath + File.separator + fileName;
|
||||||
|
} catch (RemoteException | NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder asBinder() {
|
||||||
|
return serviceBinder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,12 +29,14 @@ import android.util.Log;
|
||||||
import android.ddm.DdmHandleAppName;
|
import android.ddm.DdmHandleAppName;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepAll;
|
import io.github.lsposed.common.KeepAll;
|
||||||
|
import io.github.lsposed.lspd.config.LSPApplicationServiceClient;
|
||||||
import io.github.lsposed.lspd.service.ILSPApplicationService;
|
import io.github.lsposed.lspd.service.ILSPApplicationService;
|
||||||
import io.github.lsposed.lspd.service.ServiceManager;
|
import io.github.lsposed.lspd.service.ServiceManager;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
|
|
@ -43,15 +45,9 @@ public class Main implements KeepAll {
|
||||||
private static final Binder heartBeatBinder = new Binder();
|
private static final Binder heartBeatBinder = new Binder();
|
||||||
|
|
||||||
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
|
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
|
||||||
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
LSPApplicationServiceClient.Init(binder);
|
||||||
final int variant;
|
serviceClient.registerHeartBeat(heartBeatBinder);
|
||||||
try {
|
final int variant = serviceClient.getVariant();
|
||||||
service.registerHeartBeat(heartBeatBinder);
|
|
||||||
variant = service.getVariant();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Utils.logW("Register fail", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EdxpImpl lspd = getEdxpImpl(variant);
|
EdxpImpl lspd = getEdxpImpl(variant);
|
||||||
if (lspd == null || !lspd.isInitialized()) {
|
if (lspd == null || !lspd.isInitialized()) {
|
||||||
Utils.logE("Not started up");
|
Utils.logE("Not started up");
|
||||||
|
|
@ -61,15 +57,9 @@ public class Main implements KeepAll {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPost(IBinder binder) {
|
public static void forkSystemServerPost(IBinder binder) {
|
||||||
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
LSPApplicationServiceClient.Init(binder);
|
||||||
final int variant;
|
serviceClient.registerHeartBeat(heartBeatBinder);
|
||||||
try {
|
final int variant = serviceClient.getVariant();
|
||||||
service.registerHeartBeat(heartBeatBinder);
|
|
||||||
variant = service.getVariant();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Utils.logW("Register fail", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EdxpImpl lspd = getEdxpImpl(variant);
|
EdxpImpl lspd = getEdxpImpl(variant);
|
||||||
if (lspd == null || !lspd.isInitialized()) {
|
if (lspd == null || !lspd.isInitialized()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ package io.github.lsposed.lspd.deopt;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
|
|
@ -30,6 +29,7 @@ import java.util.Arrays;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE;
|
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE;
|
||||||
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE_MIUI_RES;
|
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE_MIUI_RES;
|
||||||
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_SYSTEM_SERVER;
|
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_SYSTEM_SERVER;
|
||||||
|
|
@ -62,7 +62,7 @@ public class PrebuiltMethodsDeopter {
|
||||||
// todo check if has been done before
|
// todo check if has been done before
|
||||||
deoptMethods(KEY_BOOT_IMAGE, null);
|
deoptMethods(KEY_BOOT_IMAGE, null);
|
||||||
if (!TextUtils.isEmpty(Utils.getSysProp("ro.miui.ui.version.code"))
|
if (!TextUtils.isEmpty(Utils.getSysProp("ro.miui.ui.version.code"))
|
||||||
&& ConfigManager.isResourcesHookEnabled()) {
|
&& serviceClient.isResourcesHookEnabled()) {
|
||||||
//deopt these only for MIUI with resources hook enabled
|
//deopt these only for MIUI with resources hook enabled
|
||||||
deoptMethods(KEY_BOOT_IMAGE_MIUI_RES, null);
|
deoptMethods(KEY_BOOT_IMAGE_MIUI_RES, null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
* Copyright (C) 2021 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.lsposed.lspd._hooker.impl;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
|
|
@ -30,7 +30,6 @@ import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
import android.content.res.XResources;
|
import android.content.res.XResources;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.Hookers;
|
import io.github.lsposed.lspd.util.Hookers;
|
||||||
import io.github.lsposed.lspd.util.MetaDataReader;
|
import io.github.lsposed.lspd.util.MetaDataReader;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
@ -46,8 +45,15 @@ import de.robv.android.xposed.XposedBridge;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
|
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
|
||||||
public class HandleBindApp extends XC_MethodHook {
|
public class HandleBindAppHooker extends XC_MethodHook {
|
||||||
|
String appDataDir = null;
|
||||||
|
|
||||||
|
public HandleBindAppHooker(String appDataDir) {
|
||||||
|
this.appDataDir = appDataDir;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) {
|
protected void beforeHookedMethod(MethodHookParam param) {
|
||||||
|
|
@ -57,10 +63,10 @@ public class HandleBindApp extends XC_MethodHook {
|
||||||
Object bindData = param.args[0];
|
Object bindData = param.args[0];
|
||||||
final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo");
|
final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo");
|
||||||
// save app process name here for later use
|
// save app process name here for later use
|
||||||
ConfigManager.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName");
|
String appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName");
|
||||||
String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
|
String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
|
||||||
Utils.logD("processName=" + ConfigManager.appProcessName +
|
Utils.logD("processName=" + appProcessName +
|
||||||
", packageName=" + reportedPackageName + ", appDataDir=" + ConfigManager.appDataDir);
|
", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir);
|
||||||
|
|
||||||
ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName");
|
ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName");
|
||||||
if (instrumentationName != null) {
|
if (instrumentationName != null) {
|
||||||
|
|
@ -118,7 +124,7 @@ public class HandleBindApp extends XC_MethodHook {
|
||||||
XposedHelpers.findAndHookMethod(ContextImpl.class, "getPreferencesDir", new XC_MethodHook() {
|
XposedHelpers.findAndHookMethod(ContextImpl.class, "getPreferencesDir", new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) {
|
protected void afterHookedMethod(MethodHookParam param) {
|
||||||
File newDir = new File(ConfigManager.getPrefsPath(appInfo.packageName));
|
File newDir = new File(serviceClient.getPrefsPath(appInfo.packageName));
|
||||||
if (migratePrefs) {
|
if (migratePrefs) {
|
||||||
File oldDir = (File) param.getResult();
|
File oldDir = (File) param.getResult();
|
||||||
for (File oldFile : oldDir.listFiles()) {
|
for (File oldFile : oldDir.listFiles()) {
|
||||||
|
|
@ -143,7 +149,7 @@ public class HandleBindApp extends XC_MethodHook {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
LoadedApkGetCL hook = new LoadedApkGetCL(loadedApk, reportedPackageName,
|
LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, reportedPackageName,
|
||||||
processName, true);
|
processName, true);
|
||||||
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
||||||
LoadedApk.class, "getClassLoader", hook));
|
LoadedApk.class, "getClassLoader", hook));
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
* Copyright (C) 2021 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.lsposed.lspd._hooker.impl;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import android.app.AndroidAppHelper;
|
import android.app.AndroidAppHelper;
|
||||||
import android.app.LoadedApk;
|
import android.app.LoadedApk;
|
||||||
|
|
@ -33,7 +33,7 @@ import de.robv.android.xposed.XposedInit;
|
||||||
|
|
||||||
// when a package is loaded for an existing process, trigger the callbacks as well
|
// when a package is loaded for an existing process, trigger the callbacks as well
|
||||||
// ed: remove resources related hooking
|
// ed: remove resources related hooking
|
||||||
public class LoadedApkCstr extends XC_MethodHook {
|
public class LoadedApkCstrHooker extends XC_MethodHook {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
|
|
@ -70,7 +70,7 @@ public class LoadedApkCstr extends XC_MethodHook {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadedApkGetCL hook = new LoadedApkGetCL(loadedApk, packageName,
|
LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, packageName,
|
||||||
AndroidAppHelper.currentProcessName(), false);
|
AndroidAppHelper.currentProcessName(), false);
|
||||||
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
||||||
LoadedApk.class, "getClassLoader", hook));
|
LoadedApk.class, "getClassLoader", hook));
|
||||||
|
|
@ -18,20 +18,22 @@
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
* Copyright (C) 2021 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.lsposed.lspd._hooker.impl;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import android.app.LoadedApk;
|
import android.app.LoadedApk;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
import de.robv.android.xposed.XC_MethodHook;
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||||
import io.github.lsposed.lspd.hooker.XposedInstallerHooker;
|
import io.github.lsposed.lspd.hooker.XposedInstallerHooker;
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.Hookers;
|
import io.github.lsposed.lspd.util.Hookers;
|
||||||
import io.github.lsposed.lspd.util.InstallerVerifier;
|
import io.github.lsposed.lspd.util.InstallerVerifier;
|
||||||
|
|
||||||
public class LoadedApkGetCL extends XC_MethodHook {
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
|
public class LoadedApkGetCLHooker extends XC_MethodHook {
|
||||||
|
|
||||||
private final LoadedApk loadedApk;
|
private final LoadedApk loadedApk;
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
|
|
@ -39,8 +41,8 @@ public class LoadedApkGetCL extends XC_MethodHook {
|
||||||
private final boolean isFirstApplication;
|
private final boolean isFirstApplication;
|
||||||
private Unhook unhook;
|
private Unhook unhook;
|
||||||
|
|
||||||
public LoadedApkGetCL(LoadedApk loadedApk, String packageName, String processName,
|
public LoadedApkGetCLHooker(LoadedApk loadedApk, String packageName, String processName,
|
||||||
boolean isFirstApplication) {
|
boolean isFirstApplication) {
|
||||||
this.loadedApk = loadedApk;
|
this.loadedApk = loadedApk;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.processName = processName;
|
this.processName = processName;
|
||||||
|
|
@ -76,9 +78,10 @@ public class LoadedApkGetCL extends XC_MethodHook {
|
||||||
lpparam.appInfo = loadedApk.getApplicationInfo();
|
lpparam.appInfo = loadedApk.getApplicationInfo();
|
||||||
lpparam.isFirstApplication = this.isFirstApplication;
|
lpparam.isFirstApplication = this.isFirstApplication;
|
||||||
|
|
||||||
if (packageName.equals(ConfigManager.getInstallerPackageName())) {
|
IBinder binder = serviceClient.requestManagerBinder();
|
||||||
|
if (binder != null) {
|
||||||
if (InstallerVerifier.verifyInstallerSignature(loadedApk.getApplicationInfo())) {
|
if (InstallerVerifier.verifyInstallerSignature(loadedApk.getApplicationInfo())) {
|
||||||
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader);
|
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader, binder);
|
||||||
} else {
|
} else {
|
||||||
InstallerVerifier.hookXposedInstaller(classLoader);
|
InstallerVerifier.hookXposedInstaller(classLoader);
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
* Copyright (C) 2021 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.lsposed.lspd._hooker.impl;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||||
import static io.github.lsposed.lspd.util.Utils.logD;
|
import static io.github.lsposed.lspd.util.Utils.logD;
|
||||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||||
|
|
||||||
public class StartBootstrapServices extends XC_MethodHook {
|
public class StartBootstrapServicesHooker extends XC_MethodHook {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
|
|
@ -50,7 +50,7 @@ public class StartBootstrapServices extends XC_MethodHook {
|
||||||
XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
|
XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
|
||||||
lpparam.packageName = "android";
|
lpparam.packageName = "android";
|
||||||
lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
|
lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
|
||||||
lpparam.classLoader = SystemMain.systemServerCL;
|
lpparam.classLoader = SystemMainHooker.systemServerCL;
|
||||||
lpparam.appInfo = null;
|
lpparam.appInfo = null;
|
||||||
lpparam.isFirstApplication = true;
|
lpparam.isFirstApplication = true;
|
||||||
XC_LoadPackage.callAll(lpparam);
|
XC_LoadPackage.callAll(lpparam);
|
||||||
|
|
@ -58,14 +58,14 @@ public class StartBootstrapServices extends XC_MethodHook {
|
||||||
// Huawei
|
// Huawei
|
||||||
try {
|
try {
|
||||||
findAndHookMethod("com.android.server.pm.HwPackageManagerService",
|
findAndHookMethod("com.android.server.pm.HwPackageManagerService",
|
||||||
SystemMain.systemServerCL, "isOdexMode",
|
SystemMainHooker.systemServerCL, "isOdexMode",
|
||||||
XC_MethodReplacement.returnConstant(false));
|
XC_MethodReplacement.returnConstant(false));
|
||||||
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService");
|
String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService");
|
||||||
findAndHookMethod(className, SystemMain.systemServerCL,
|
findAndHookMethod(className, SystemMainHooker.systemServerCL,
|
||||||
"dexEntryExists", String.class,
|
"dexEntryExists", String.class,
|
||||||
XC_MethodReplacement.returnConstant(true));
|
XC_MethodReplacement.returnConstant(true));
|
||||||
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
* Copyright (C) 2021 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.github.lsposed.lspd._hooker.impl;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.core.Main;
|
import io.github.lsposed.lspd.core.Main;
|
||||||
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
|
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
|
||||||
|
|
@ -29,7 +29,7 @@ import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
// system_server initialization
|
// system_server initialization
|
||||||
// ed: only support sdk >= 21 for now
|
// ed: only support sdk >= 21 for now
|
||||||
public class SystemMain extends XC_MethodHook {
|
public class SystemMainHooker extends XC_MethodHook {
|
||||||
|
|
||||||
public static volatile ClassLoader systemServerCL;
|
public static volatile ClassLoader systemServerCL;
|
||||||
|
|
||||||
|
|
@ -20,19 +20,16 @@
|
||||||
|
|
||||||
package io.github.lsposed.lspd.hooker;
|
package io.github.lsposed.lspd.hooker;
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodReplacement;
|
import android.os.IBinder;
|
||||||
import de.robv.android.xposed.XposedBridge;
|
|
||||||
import de.robv.android.xposed.XposedHelpers;
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import io.github.lsposed.lspd.BuildConfig;
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.core.EdxpImpl;
|
import io.github.lsposed.lspd.core.EdxpImpl;
|
||||||
import io.github.lsposed.lspd.core.Main;
|
import io.github.lsposed.lspd.core.Main;
|
||||||
import io.github.lsposed.lspd.service.BridgeService;
|
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
public class XposedInstallerHooker {
|
public class XposedInstallerHooker {
|
||||||
|
|
||||||
public static void hookXposedInstaller(final ClassLoader classLoader) {
|
public static void hookXposedInstaller(final ClassLoader classLoader, IBinder binder) {
|
||||||
final String variant;
|
final String variant;
|
||||||
switch (Main.getEdxpVariant()) {
|
switch (Main.getEdxpVariant()) {
|
||||||
case EdxpImpl.YAHFA:
|
case EdxpImpl.YAHFA:
|
||||||
|
|
@ -51,72 +48,8 @@ public class XposedInstallerHooker {
|
||||||
|
|
||||||
// LSPosed Manager R
|
// LSPosed Manager R
|
||||||
try {
|
try {
|
||||||
Class<?> ConstantsClass = XposedHelpers.findClass("io.github.lsposed.manager.Constants", classLoader);
|
|
||||||
try {
|
|
||||||
XposedHelpers.setStaticIntField(ConstantsClass, "xposedApiVersion", XposedBridge.getXposedVersion());
|
|
||||||
XposedHelpers.setStaticObjectField(ConstantsClass, "xposedVersion", BuildConfig.VERSION_NAME);
|
|
||||||
XposedHelpers.setStaticIntField(ConstantsClass, "xposedVersionCode", BuildConfig.VERSION_CODE);
|
|
||||||
XposedHelpers.setStaticObjectField(ConstantsClass, "xposedVariant", variant);
|
|
||||||
XposedHelpers.setStaticObjectField(ConstantsClass, "baseDir", ConfigManager.getBaseConfigPath() + "/");
|
|
||||||
XposedHelpers.setStaticObjectField(ConstantsClass, "logDir", ConfigManager.getLogPath());
|
|
||||||
XposedHelpers.setStaticObjectField(ConstantsClass, "miscDir", ConfigManager.getMiscPath());
|
|
||||||
XposedHelpers.setStaticBooleanField(ConstantsClass, "permissive", ConfigManager.isPermissive());
|
|
||||||
|
|
||||||
Utils.logI("Hooked LSPosed Manager");
|
|
||||||
return;
|
|
||||||
} catch (Throwable ignored) {
|
|
||||||
// fallback
|
|
||||||
}
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedApiVersion", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return XposedBridge.getXposedVersion();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVersion", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return BuildConfig.VERSION_NAME;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVersionCode", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return BuildConfig.VERSION_CODE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVariant", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return variant;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getBaseDir", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return ConfigManager.getBaseConfigPath() + "/";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "isPermissive", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return ConfigManager.isPermissive();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getLogDir", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return ConfigManager.getLogPath();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
XposedHelpers.findAndHookMethod(ConstantsClass, "getMiscDir", new XC_MethodReplacement() {
|
|
||||||
@Override
|
|
||||||
protected Object replaceHookedMethod(MethodHookParam param) {
|
|
||||||
return ConfigManager.getMiscPath();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Class<?> serviceClass = XposedHelpers.findClass("io.github.lsposed.manager.receivers.LSPosedManagerServiceClient", classLoader);
|
Class<?> serviceClass = XposedHelpers.findClass("io.github.lsposed.manager.receivers.LSPosedManagerServiceClient", classLoader);
|
||||||
// XposedHelpers.setStaticObjectField(serviceClass, "binder", BridgeService.requireBinder());
|
XposedHelpers.setStaticObjectField(serviceClass, "binder", binder);
|
||||||
|
|
||||||
Utils.logI("Hooked LSPosed Manager");
|
Utils.logI("Hooked LSPosed Manager");
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.lsposed.lspd.nativebridge;
|
|
||||||
|
|
||||||
public class ConfigManager {
|
|
||||||
|
|
||||||
public static String appDataDir = "";
|
|
||||||
public static String niceName = "";
|
|
||||||
public static String appProcessName = "";
|
|
||||||
|
|
||||||
public static native boolean isResourcesHookEnabled();
|
|
||||||
|
|
||||||
public static native String getInstallerPackageName();
|
|
||||||
|
|
||||||
public static native String getPrefsPath(String suffix);
|
|
||||||
|
|
||||||
public static native String getCachePath(String suffix);
|
|
||||||
|
|
||||||
public static native String getLogPath();
|
|
||||||
|
|
||||||
public static native String getMiscPath();
|
|
||||||
|
|
||||||
public static native String getBaseConfigPath();
|
|
||||||
|
|
||||||
public static native String getDataPathPrefix();
|
|
||||||
|
|
||||||
public static native String getModulesList();
|
|
||||||
|
|
||||||
public static native boolean isPermissive();
|
|
||||||
}
|
|
||||||
|
|
@ -25,10 +25,10 @@ import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import io.github.lsposed.lspd._hooker.impl.HandleBindApp;
|
import io.github.lsposed.lspd.hooker.HandleBindAppHooker;
|
||||||
import io.github.lsposed.lspd._hooker.impl.LoadedApkCstr;
|
import io.github.lsposed.lspd.hooker.LoadedApkCstrHooker;
|
||||||
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
|
import io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker;
|
||||||
import io.github.lsposed.lspd._hooker.impl.SystemMain;
|
import io.github.lsposed.lspd.hooker.SystemMainHooker;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
import io.github.lsposed.lspd.util.Versions;
|
import io.github.lsposed.lspd.util.Versions;
|
||||||
|
|
||||||
|
|
@ -53,13 +53,13 @@ public abstract class BaseRouter implements Router {
|
||||||
XposedInit.startsSystemServer = isSystem;
|
XposedInit.startsSystemServer = isSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void installBootstrapHooks(boolean isSystem) {
|
public void installBootstrapHooks(boolean isSystem, String appDataDir) {
|
||||||
// Initialize the Xposed framework
|
// Initialize the Xposed framework
|
||||||
try {
|
try {
|
||||||
if (!bootstrapHooked.compareAndSet(false, true)) {
|
if (!bootstrapHooked.compareAndSet(false, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startBootstrapHook(isSystem);
|
startBootstrapHook(isSystem, appDataDir);
|
||||||
XposedInit.initForZygote(isSystem);
|
XposedInit.initForZygote(isSystem);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Utils.logE("error during Xposed initialization", t);
|
Utils.logE("error during Xposed initialization", t);
|
||||||
|
|
@ -88,30 +88,30 @@ public abstract class BaseRouter implements Router {
|
||||||
|
|
||||||
|
|
||||||
@ApiSensitive(Level.LOW)
|
@ApiSensitive(Level.LOW)
|
||||||
public void startBootstrapHook(boolean isSystem) {
|
public void startBootstrapHook(boolean isSystem, String appDataDir) {
|
||||||
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
|
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
|
||||||
ClassLoader classLoader = BaseRouter.class.getClassLoader();
|
ClassLoader classLoader = BaseRouter.class.getClassLoader();
|
||||||
if (isSystem) {
|
if (isSystem) {
|
||||||
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
||||||
"systemMain", new SystemMain());
|
"systemMain", new SystemMainHooker());
|
||||||
}
|
}
|
||||||
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
||||||
"handleBindApplication",
|
"handleBindApplication",
|
||||||
"android.app.ActivityThread$AppBindData",
|
"android.app.ActivityThread$AppBindData",
|
||||||
new HandleBindApp());
|
new HandleBindAppHooker(appDataDir));
|
||||||
XposedHelpers.findAndHookConstructor("android.app.LoadedApk", classLoader,
|
XposedHelpers.findAndHookConstructor("android.app.LoadedApk", classLoader,
|
||||||
ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class,
|
ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class,
|
||||||
ClassLoader.class, boolean.class, boolean.class, boolean.class,
|
ClassLoader.class, boolean.class, boolean.class, boolean.class,
|
||||||
new LoadedApkCstr());
|
new LoadedApkCstrHooker());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startSystemServerHook() {
|
public void startSystemServerHook() {
|
||||||
StartBootstrapServices sbsHooker = new StartBootstrapServices();
|
StartBootstrapServicesHooker sbsHooker = new StartBootstrapServicesHooker();
|
||||||
Object[] paramTypesAndCallback = Versions.hasR() ?
|
Object[] paramTypesAndCallback = Versions.hasR() ?
|
||||||
new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} :
|
new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} :
|
||||||
new Object[]{sbsHooker};
|
new Object[]{sbsHooker};
|
||||||
XposedHelpers.findAndHookMethod("com.android.server.SystemServer",
|
XposedHelpers.findAndHookMethod("com.android.server.SystemServer",
|
||||||
SystemMain.systemServerCL,
|
SystemMainHooker.systemServerCL,
|
||||||
"startBootstrapServices", paramTypesAndCallback);
|
"startBootstrapServices", paramTypesAndCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,16 @@
|
||||||
|
|
||||||
package io.github.lsposed.lspd.proxy;
|
package io.github.lsposed.lspd.proxy;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
|
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
import de.robv.android.xposed.SELinuxHelper;
|
import de.robv.android.xposed.SELinuxHelper;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
||||||
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
|
|
||||||
|
|
||||||
public class NormalProxy extends BaseProxy {
|
public class NormalProxy extends BaseProxy {
|
||||||
|
|
||||||
public NormalProxy(Router router) {
|
public NormalProxy(Router router) {
|
||||||
|
|
@ -41,7 +42,7 @@ public class NormalProxy extends BaseProxy {
|
||||||
|
|
||||||
public void forkSystemServerPost() {
|
public void forkSystemServerPost() {
|
||||||
forkPostCommon(true,
|
forkPostCommon(true,
|
||||||
getDataPathPrefix() + "android", "system_server");
|
new File(Environment.getDataDirectory(), "android").toString(), "system_server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -50,10 +51,7 @@ public class NormalProxy extends BaseProxy {
|
||||||
mRouter.initResourcesHook();
|
mRouter.initResourcesHook();
|
||||||
mRouter.prepare(isSystem);
|
mRouter.prepare(isSystem);
|
||||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||||
ConfigManager.appDataDir = appDataDir;
|
mRouter.installBootstrapHooks(isSystem, appDataDir);
|
||||||
ConfigManager.niceName = niceName;
|
|
||||||
mRouter.installBootstrapHooks(isSystem);
|
|
||||||
XposedInit.prefsBasePath = ConfigManager.getPrefsPath("");
|
|
||||||
mRouter.onEnterChildProcess();
|
mRouter.onEnterChildProcess();
|
||||||
Utils.logI("Loading modules for " + niceName);
|
Utils.logI("Loading modules for " + niceName);
|
||||||
mRouter.loadModulesSafely(true);
|
mRouter.loadModulesSafely(true);
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,11 @@ public interface Router {
|
||||||
|
|
||||||
void prepare(boolean isSystem);
|
void prepare(boolean isSystem);
|
||||||
|
|
||||||
String parsePackageName(String appDataDir);
|
void installBootstrapHooks(boolean isSystem, String appDataDir);
|
||||||
|
|
||||||
void installBootstrapHooks(boolean isSystem);
|
|
||||||
|
|
||||||
void loadModulesSafely(boolean callInitZygote);
|
void loadModulesSafely(boolean callInitZygote);
|
||||||
|
|
||||||
void startBootstrapHook(boolean isSystem);
|
void startBootstrapHook(boolean isSystem, String appDataDir);
|
||||||
|
|
||||||
void startSystemServerHook();
|
void startSystemServerHook();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,45 +23,13 @@ package io.github.lsposed.lspd.sandhook.core;
|
||||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||||
import io.github.lsposed.lspd.proxy.BaseRouter;
|
import io.github.lsposed.lspd.proxy.BaseRouter;
|
||||||
import io.github.lsposed.lspd.sandhook.config.SandHookProvider;
|
import io.github.lsposed.lspd.sandhook.config.SandHookProvider;
|
||||||
import io.github.lsposed.lspd.sandhook.entry.AppBootstrapHookInfo;
|
|
||||||
import io.github.lsposed.lspd.sandhook.entry.SysBootstrapHookInfo;
|
|
||||||
import io.github.lsposed.lspd.sandhook.entry.SysInnerHookInfo;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.SystemMainHooker;
|
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
|
||||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
|
||||||
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
|
||||||
|
|
||||||
public class SandHookRouter extends BaseRouter {
|
public class SandHookRouter extends BaseRouter {
|
||||||
|
|
||||||
public SandHookRouter() {
|
public SandHookRouter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean useSandHook = false;
|
|
||||||
|
|
||||||
public void startBootstrapHook(boolean isSystem) {
|
|
||||||
if (useSandHook) {
|
|
||||||
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
|
|
||||||
ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER;
|
|
||||||
if (isSystem) {
|
|
||||||
XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems);
|
|
||||||
} else {
|
|
||||||
XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.startBootstrapHook(isSystem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startSystemServerHook() {
|
|
||||||
if (useSandHook) {
|
|
||||||
XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems);
|
|
||||||
} else {
|
|
||||||
super.startSystemServerHook();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onEnterChildProcess() {
|
public void onEnterChildProcess() {
|
||||||
SandHookXposedBridge.onForkPost();
|
SandHookXposedBridge.onForkPost();
|
||||||
//enable compile in child process
|
//enable compile in child process
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.lsposed.lspd.sandhook.entry;
|
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.HandleBindAppHooker;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.LoadedApkConstructorHooker;
|
|
||||||
|
|
||||||
public class AppBootstrapHookInfo implements KeepMembers {
|
|
||||||
public static String[] hookItemNames = {
|
|
||||||
HandleBindAppHooker.class.getName(),
|
|
||||||
LoadedApkConstructorHooker.class.getName(),
|
|
||||||
};
|
|
||||||
|
|
||||||
public static Class[] hookItems = {
|
|
||||||
HandleBindAppHooker.class,
|
|
||||||
LoadedApkConstructorHooker.class,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.lsposed.lspd.sandhook.entry;
|
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.HandleBindAppHooker;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.LoadedApkConstructorHooker;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.SystemMainHooker;
|
|
||||||
|
|
||||||
public class SysBootstrapHookInfo implements KeepMembers {
|
|
||||||
public static String[] hookItemNames = {
|
|
||||||
HandleBindAppHooker.class.getName(),
|
|
||||||
SystemMainHooker.class.getName(),
|
|
||||||
LoadedApkConstructorHooker.class.getName()
|
|
||||||
};
|
|
||||||
|
|
||||||
public static Class[] hookItems = {
|
|
||||||
HandleBindAppHooker.class,
|
|
||||||
SystemMainHooker.class,
|
|
||||||
LoadedApkConstructorHooker.class,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.lsposed.lspd.sandhook.entry;
|
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.StartBootstrapServicesHooker;
|
|
||||||
import io.github.lsposed.lspd.sandhook.hooker.StartBootstrapServicesHooker11;
|
|
||||||
import io.github.lsposed.lspd.util.Versions;
|
|
||||||
|
|
||||||
public class SysInnerHookInfo implements KeepMembers {
|
|
||||||
|
|
||||||
public static Class<?> getSysInnerHookerClass() {
|
|
||||||
return Versions.hasR() ?
|
|
||||||
StartBootstrapServicesHooker11.class :
|
|
||||||
StartBootstrapServicesHooker.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] hookItemNames = {
|
|
||||||
getSysInnerHookerClass().getName()
|
|
||||||
};
|
|
||||||
|
|
||||||
public static Class[] hookItems = {
|
|
||||||
getSysInnerHookerClass()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of LSPosed.
|
|
||||||
*
|
|
||||||
* LSPosed is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LSPosed is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 EdXposed Contributors
|
|
||||||
* Copyright (C) 2021 LSPosed Contributors
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.github.lsposed.lspd.sandhook.hooker;
|
|
||||||
|
|
||||||
import android.app.ActivityThread;
|
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
|
||||||
import io.github.lsposed.lspd._hooker.impl.HandleBindApp;
|
|
||||||
import com.swift.sandhook.SandHook;
|
|
||||||
import com.swift.sandhook.annotation.HookClass;
|
|
||||||
import com.swift.sandhook.annotation.HookMethod;
|
|
||||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
|
||||||
import com.swift.sandhook.annotation.Param;
|
|
||||||
import com.swift.sandhook.annotation.SkipParamCheck;
|
|
||||||
import com.swift.sandhook.annotation.ThisObject;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
import de.robv.android.xposed.XC_MethodHook;
|
|
||||||
import de.robv.android.xposed.annotation.ApiSensitive;
|
|
||||||
import de.robv.android.xposed.annotation.Level;
|
|
||||||
|
|
||||||
@ApiSensitive(Level.LOW)
|
|
||||||
@HookClass(ActivityThread.class)
|
|
||||||
public class HandleBindAppHooker implements KeepMembers {
|
|
||||||
|
|
||||||
public static String className = "android.app.ActivityThread";
|
|
||||||
public static String methodName = "handleBindApplication";
|
|
||||||
public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V";
|
|
||||||
|
|
||||||
@HookMethodBackup("handleBindApplication")
|
|
||||||
@SkipParamCheck
|
|
||||||
static Method backup;
|
|
||||||
|
|
||||||
@HookMethod("handleBindApplication")
|
|
||||||
public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable {
|
|
||||||
final XC_MethodHook methodHook = new HandleBindApp();
|
|
||||||
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
|
||||||
param.thisObject = thiz;
|
|
||||||
param.args = new Object[]{bindData};
|
|
||||||
methodHook.callBeforeHookedMethod(param);
|
|
||||||
if (!param.returnEarly) {
|
|
||||||
backup(thiz, bindData);
|
|
||||||
}
|
|
||||||
methodHook.callAfterHookedMethod(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void backup(Object thiz, Object bindData) throws Throwable {
|
|
||||||
SandHook.callOriginByBackup(backup, thiz, bindData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -26,7 +26,7 @@ import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
import io.github.lsposed.common.KeepMembers;
|
||||||
import io.github.lsposed.lspd._hooker.impl.LoadedApkCstr;
|
import io.github.lsposed.lspd.hooker.LoadedApkCstrHooker;
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.annotation.HookClass;
|
import com.swift.sandhook.annotation.HookClass;
|
||||||
import com.swift.sandhook.annotation.HookMethod;
|
import com.swift.sandhook.annotation.HookMethod;
|
||||||
|
|
@ -59,7 +59,7 @@ public class LoadedApkConstructorHooker implements KeepMembers {
|
||||||
ApplicationInfo aInfo, CompatibilityInfo compatInfo,
|
ApplicationInfo aInfo, CompatibilityInfo compatInfo,
|
||||||
ClassLoader baseLoader, boolean securityViolation,
|
ClassLoader baseLoader, boolean securityViolation,
|
||||||
boolean includeCode, boolean registerPackage) throws Throwable {
|
boolean includeCode, boolean registerPackage) throws Throwable {
|
||||||
final XC_MethodHook methodHook = new LoadedApkCstr();
|
final XC_MethodHook methodHook = new LoadedApkCstrHooker();
|
||||||
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
||||||
param.thisObject = thiz;
|
param.thisObject = thiz;
|
||||||
param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
package io.github.lsposed.lspd.sandhook.hooker;
|
package io.github.lsposed.lspd.sandhook.hooker;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
import io.github.lsposed.common.KeepMembers;
|
||||||
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
|
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.annotation.HookMethod;
|
import com.swift.sandhook.annotation.HookMethod;
|
||||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||||
|
|
@ -45,7 +45,7 @@ public class StartBootstrapServicesHooker implements KeepMembers {
|
||||||
|
|
||||||
@HookMethod("startBootstrapServices")
|
@HookMethod("startBootstrapServices")
|
||||||
public static void hook(@ThisObject Object systemServer) throws Throwable {
|
public static void hook(@ThisObject Object systemServer) throws Throwable {
|
||||||
final XC_MethodHook methodHook = new StartBootstrapServices();
|
final XC_MethodHook methodHook = new io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker();
|
||||||
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
||||||
param.thisObject = systemServer;
|
param.thisObject = systemServer;
|
||||||
param.args = new Object[]{};
|
param.args = new Object[]{};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
package io.github.lsposed.lspd.sandhook.hooker;
|
package io.github.lsposed.lspd.sandhook.hooker;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
import io.github.lsposed.common.KeepMembers;
|
||||||
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
|
import io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker;
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.annotation.HookMethod;
|
import com.swift.sandhook.annotation.HookMethod;
|
||||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||||
|
|
@ -49,7 +49,7 @@ public class StartBootstrapServicesHooker11 implements KeepMembers {
|
||||||
|
|
||||||
@HookMethod("startBootstrapServices")
|
@HookMethod("startBootstrapServices")
|
||||||
public static void hook(@ThisObject Object systemServer, @Param("com.android.server.utils.TimingsTraceAndSlog") Object traceAndSlog) throws Throwable {
|
public static void hook(@ThisObject Object systemServer, @Param("com.android.server.utils.TimingsTraceAndSlog") Object traceAndSlog) throws Throwable {
|
||||||
final XC_MethodHook methodHook = new StartBootstrapServices();
|
final XC_MethodHook methodHook = new StartBootstrapServicesHooker();
|
||||||
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
||||||
param.thisObject = systemServer;
|
param.thisObject = systemServer;
|
||||||
param.args = new Object[]{traceAndSlog};
|
param.args = new Object[]{traceAndSlog};
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ package io.github.lsposed.lspd.sandhook.hooker;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
|
|
||||||
import io.github.lsposed.common.KeepMembers;
|
import io.github.lsposed.common.KeepMembers;
|
||||||
import io.github.lsposed.lspd._hooker.impl.SystemMain;
|
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.annotation.HookClass;
|
import com.swift.sandhook.annotation.HookClass;
|
||||||
import com.swift.sandhook.annotation.HookMethod;
|
import com.swift.sandhook.annotation.HookMethod;
|
||||||
|
|
@ -53,7 +53,7 @@ public class SystemMainHooker implements KeepMembers {
|
||||||
|
|
||||||
@HookMethod("systemMain")
|
@HookMethod("systemMain")
|
||||||
public static ActivityThread hook() throws Throwable {
|
public static ActivityThread hook() throws Throwable {
|
||||||
final XC_MethodHook methodHook = new SystemMain();
|
final XC_MethodHook methodHook = new io.github.lsposed.lspd.hooker.SystemMainHooker();
|
||||||
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
|
||||||
param.thisObject = null;
|
param.thisObject = null;
|
||||||
param.args = new Object[]{};
|
param.args = new Object[]{};
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||||
|
|
||||||
// This config manager assume uid won't change when our service is off.
|
// This config manager assume uid won't change when our service is off.
|
||||||
// Otherwise, user should maintain it manually.
|
// Otherwise, user should maintain it manually.
|
||||||
// TODO: manager package name supports
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
static ConfigManager instance = null;
|
static ConfigManager instance = null;
|
||||||
|
|
||||||
|
|
@ -52,6 +51,9 @@ public class ConfigManager {
|
||||||
private String manager = null;
|
private String manager = null;
|
||||||
private int managerUid = -1;
|
private int managerUid = -1;
|
||||||
|
|
||||||
|
final private File miscFile = new File(basePath, "misc_path");
|
||||||
|
private String miscPath = null;
|
||||||
|
|
||||||
final private File selinuxPath = new File("/sys/fs/selinux/enforce");
|
final private File selinuxPath = new File("/sys/fs/selinux/enforce");
|
||||||
// only check on boot
|
// only check on boot
|
||||||
final private boolean isPermissive;
|
final private boolean isPermissive;
|
||||||
|
|
@ -69,7 +71,7 @@ public class ConfigManager {
|
||||||
};
|
};
|
||||||
|
|
||||||
private String readText(@NonNull File file) throws IOException {
|
private String readText(@NonNull File file) throws IOException {
|
||||||
return new String(Files.readAllBytes(file.toPath()));
|
return new String(Files.readAllBytes(file.toPath())).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readText(@NonNull File file, String defaultValue) {
|
private String readText(@NonNull File file, String defaultValue) {
|
||||||
|
|
@ -108,6 +110,7 @@ public class ConfigManager {
|
||||||
resourceHook = resourceHookSwitch.exists();
|
resourceHook = resourceHookSwitch.exists();
|
||||||
variant = readInt(variantSwitch, -1);
|
variant = readInt(variantSwitch, -1);
|
||||||
verboseLog = readInt(verboseLogSwitch, 0) == 1;
|
verboseLog = readInt(verboseLogSwitch, 0) == 1;
|
||||||
|
miscPath = "/data/misc/" + readText(miscFile, "lspd");
|
||||||
updateManager();
|
updateManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,4 +336,12 @@ public class ConfigManager {
|
||||||
public boolean isManager(int uid) {
|
public boolean isManager(int uid) {
|
||||||
return uid == managerUid;
|
return uid == managerUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCachePath(String fileName) {
|
||||||
|
return miscPath + File.separator + "cache" + File.separator + fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefsPath(String fileName) {
|
||||||
|
return miscPath + File.separator + "prefs" + File.separator + fileName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -35,6 +36,30 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
||||||
return ConfigManager.getInstance().variant();
|
return ConfigManager.getInstance().variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResourcesHookEnabled() throws RemoteException {
|
||||||
|
ensureRegistered();
|
||||||
|
return ConfigManager.getInstance().resourceHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getModulesList() throws RemoteException {
|
||||||
|
ensureRegistered();
|
||||||
|
return ConfigManager.getInstance().getModulesPathForUid(Binder.getCallingUid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrefsPath(String packageName) throws RemoteException {
|
||||||
|
ensureRegistered();
|
||||||
|
return ConfigManager.getInstance().getPrefsPath(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCachePath(String fileName) throws RemoteException {
|
||||||
|
ensureRegistered();
|
||||||
|
return ConfigManager.getInstance().getCachePath(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check if module
|
// TODO: check if module
|
||||||
@Override
|
@Override
|
||||||
public IBinder requestModuleBinder() throws RemoteException {
|
public IBinder requestModuleBinder() throws RemoteException {
|
||||||
|
|
@ -42,7 +67,6 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
||||||
return ServiceManager.getModuleService();
|
return ServiceManager.getModuleService();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if manager
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder requestManagerBinder() throws RemoteException {
|
public IBinder requestManagerBinder() throws RemoteException {
|
||||||
ensureRegistered();
|
ensureRegistered();
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -78,63 +77,65 @@ public class PackageReceiver {
|
||||||
|
|
||||||
private Map<String, String> loadEnabledModules(int uid) {
|
private Map<String, String> loadEnabledModules(int uid) {
|
||||||
HashMap<String, String> result = new HashMap<>();
|
HashMap<String, String> result = new HashMap<>();
|
||||||
try {
|
// TODO: FIXME
|
||||||
File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
// try {
|
||||||
if (!enabledModules.exists()) return result;
|
// File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||||
Scanner scanner = new Scanner(enabledModules);
|
// if (!enabledModules.exists()) return result;
|
||||||
while (scanner.hasNextLine()) {
|
// Scanner scanner = new Scanner(enabledModules);
|
||||||
String packageName = scanner.nextLine();
|
// while (scanner.hasNextLine()) {
|
||||||
PackageInfo info = getPackageInfo(packageName, 0);
|
// String packageName = scanner.nextLine();
|
||||||
if (info != null && isXposedModule(info.applicationInfo))
|
// PackageInfo info = getPackageInfo(packageName, 0);
|
||||||
result.put(packageName, info.applicationInfo.sourceDir);
|
// if (info != null && isXposedModule(info.applicationInfo))
|
||||||
else if (info == null)
|
// result.put(packageName, info.applicationInfo.sourceDir);
|
||||||
result.put(packageName, null);
|
// else if (info == null)
|
||||||
}
|
// result.put(packageName, null);
|
||||||
} catch (Throwable e) {
|
// }
|
||||||
Utils.logE("Unable to read enabled modules", e);
|
// } catch (Throwable e) {
|
||||||
}
|
// Utils.logE("Unable to read enabled modules", e);
|
||||||
|
// }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean updateModuleList(int uid, String packageName) {
|
private boolean updateModuleList(int uid, String packageName) {
|
||||||
Map<String, String> enabledModules = loadEnabledModules(uid);
|
Map<String, String> enabledModules = loadEnabledModules(uid);
|
||||||
|
// TODO: FIXME
|
||||||
if (!enabledModules.containsKey(packageName)) return false;
|
//
|
||||||
|
// if (!enabledModules.containsKey(packageName)) return false;
|
||||||
try {
|
//
|
||||||
File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME);
|
// try {
|
||||||
File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
// File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME);
|
||||||
if (moduleListFile.exists() && !moduleListFile.canWrite()) {
|
// File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||||
moduleListFile.delete();
|
// if (moduleListFile.exists() && !moduleListFile.canWrite()) {
|
||||||
moduleListFile.createNewFile();
|
// moduleListFile.delete();
|
||||||
}
|
// moduleListFile.createNewFile();
|
||||||
if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) {
|
// }
|
||||||
enabledModuleListFile.delete();
|
// if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) {
|
||||||
enabledModuleListFile.createNewFile();
|
// enabledModuleListFile.delete();
|
||||||
}
|
// enabledModuleListFile.createNewFile();
|
||||||
PrintWriter modulesList = new PrintWriter(moduleListFile);
|
// }
|
||||||
PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile);
|
// PrintWriter modulesList = new PrintWriter(moduleListFile);
|
||||||
for (Map.Entry<String, String> module : enabledModules.entrySet()) {
|
// PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile);
|
||||||
String apkPath = module.getValue();
|
// for (Map.Entry<String, String> module : enabledModules.entrySet()) {
|
||||||
if (apkPath != null) {
|
// String apkPath = module.getValue();
|
||||||
modulesList.println(module.getValue());
|
// if (apkPath != null) {
|
||||||
enabledModulesList.println(module.getKey());
|
// modulesList.println(module.getValue());
|
||||||
} else {
|
// enabledModulesList.println(module.getKey());
|
||||||
Utils.logI(String.format("remove obsolete package %s", packageName));
|
// } else {
|
||||||
File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName);
|
// Utils.logI(String.format("remove obsolete package %s", packageName));
|
||||||
File[] fileList = prefsDir.listFiles();
|
// File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName);
|
||||||
if (fileList != null) {
|
// File[] fileList = prefsDir.listFiles();
|
||||||
for (File childFile : fileList) {
|
// if (fileList != null) {
|
||||||
childFile.delete();
|
// for (File childFile : fileList) {
|
||||||
}
|
// childFile.delete();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
modulesList.close();
|
// }
|
||||||
enabledModulesList.close();
|
// modulesList.close();
|
||||||
} catch (Throwable e) {
|
// enabledModulesList.close();
|
||||||
Utils.logE("Fail to update module list", e);
|
// } catch (Throwable e) {
|
||||||
}
|
// Utils.logE("Fail to update module list", e);
|
||||||
|
// }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,36 +169,37 @@ public class PackageReceiver {
|
||||||
PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0));
|
PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0));
|
||||||
|
|
||||||
if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return;
|
if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return;
|
||||||
|
// TODO: FIXME
|
||||||
try {
|
//
|
||||||
for (int uid : UserService.getUsers()) {
|
// try {
|
||||||
Utils.logI("updating uid: " + uid);
|
// for (int uid : UserService.getUsers()) {
|
||||||
boolean activated = updateModuleList(uid, packageName);
|
// Utils.logI("updating uid: " + uid);
|
||||||
UserHandle userHandle = null;
|
// boolean activated = updateModuleList(uid, packageName);
|
||||||
try {
|
// UserHandle userHandle = null;
|
||||||
userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid);
|
// try {
|
||||||
} catch (Throwable t) {
|
// userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid);
|
||||||
Utils.logW("get user handle failed", t);
|
// } catch (Throwable t) {
|
||||||
}
|
// Utils.logW("get user handle failed", t);
|
||||||
if (userHandle != null) {
|
// }
|
||||||
try {
|
// if (userHandle != null) {
|
||||||
Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED);
|
// try {
|
||||||
broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000);
|
// Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED);
|
||||||
broadCast.setData(intent.getData());
|
// broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000);
|
||||||
broadCast.setPackage(ConfigManager.getInstallerPackageName());
|
// broadCast.setData(intent.getData());
|
||||||
XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle);
|
// broadCast.setPackage(ConfigManager.getInstallerPackageName());
|
||||||
Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName());
|
// XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle);
|
||||||
} catch (Throwable t) {
|
// Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName());
|
||||||
Utils.logW("send broadcast failed", t);
|
// } catch (Throwable t) {
|
||||||
Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
|
// Utils.logW("send broadcast failed", t);
|
||||||
}
|
// Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
|
||||||
} else if (activated) {
|
// }
|
||||||
Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
|
// } else if (activated) {
|
||||||
}
|
// Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
|
||||||
}
|
// }
|
||||||
} catch (Throwable e) {
|
// }
|
||||||
Utils.logW("update failed", e);
|
// } catch (Throwable e) {
|
||||||
}
|
// Utils.logW("update failed", e);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import android.os.ServiceManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.utils.ParceledListSlice;
|
import io.github.lsposed.lspd.utils.ParceledListSlice;
|
||||||
|
|
||||||
public class PackageService {
|
public class PackageService {
|
||||||
|
|
@ -35,15 +34,6 @@ public class PackageService {
|
||||||
return pm.getPackagesForUid(uid);
|
return pm.getPackagesForUid(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isInstaller(int uid) throws RemoteException {
|
|
||||||
boolean res = false;
|
|
||||||
String InstallerPackageName = ConfigManager.getInstallerPackageName();
|
|
||||||
for (String pkg : getPackagesForUid(uid)) {
|
|
||||||
res = res || InstallerPackageName.equals(pkg);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ParceledListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException {
|
public static ParceledListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException {
|
||||||
ArrayList<PackageInfo> res = new ArrayList<>();
|
ArrayList<PackageInfo> res = new ArrayList<>();
|
||||||
IPackageManager pm = getPackageManager();
|
IPackageManager pm = getPackageManager();
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ package io.github.lsposed.lspd.util;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -90,8 +88,4 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
return dataDir.substring(lastIndex + 1);
|
return dataDir.substring(lastIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDataPathPrefix() {
|
|
||||||
return ConfigManager.getDataPathPrefix() + "/";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
package io.github.lsposed.lspd.yahfa.dexmaker;
|
package io.github.lsposed.lspd.yahfa.dexmaker;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -33,15 +32,17 @@ import external.com.android.dx.Code;
|
||||||
import external.com.android.dx.Local;
|
import external.com.android.dx.Local;
|
||||||
import external.com.android.dx.TypeId;
|
import external.com.android.dx.TypeId;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public class DexMakerUtils {
|
public class DexMakerUtils {
|
||||||
|
|
||||||
public static boolean canCache = true;
|
public static boolean canCache = true;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
File cacheDir = new File(ConfigManager.getCachePath(""));
|
File cacheDir = new File(serviceClient.getCachePath(""));
|
||||||
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
||||||
Utils.logW("Cache disabled");
|
Utils.logW("Cache disabled with path " + cacheDir.getAbsolutePath());
|
||||||
canCache = false;
|
canCache = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import android.annotation.TargetApi;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.BuildConfig;
|
import io.github.lsposed.lspd.BuildConfig;
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.core.yahfa.HookMain;
|
import io.github.lsposed.lspd.core.yahfa.HookMain;
|
||||||
import io.github.lsposed.lspd.util.ProxyClassLoader;
|
import io.github.lsposed.lspd.util.ProxyClassLoader;
|
||||||
|
|
||||||
|
|
@ -46,6 +45,7 @@ import external.com.android.dx.Local;
|
||||||
import external.com.android.dx.MethodId;
|
import external.com.android.dx.MethodId;
|
||||||
import external.com.android.dx.TypeId;
|
import external.com.android.dx.TypeId;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary;
|
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary;
|
||||||
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary;
|
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary;
|
||||||
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.canCache;
|
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.canCache;
|
||||||
|
|
@ -167,17 +167,17 @@ public class HookerDexMaker {
|
||||||
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
|
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
|
||||||
className = className + suffix;
|
className = className + suffix;
|
||||||
String dexFileName = className + ".jar";
|
String dexFileName = className + ".jar";
|
||||||
File dexFile = new File(ConfigManager.getCachePath(dexFileName));
|
File dexFile = new File(serviceClient.getCachePath(dexFileName));
|
||||||
if (!dexFile.exists()) {
|
if (!dexFile.exists()) {
|
||||||
// if file exists, reuse it and skip generating
|
// if file exists, reuse it and skip generating
|
||||||
DexLog.d("Generating " + dexFileName);
|
DexLog.d("Generating " + dexFileName);
|
||||||
doGenerate(className);
|
doGenerate(className);
|
||||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName, false);
|
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName, false);
|
||||||
dexFile.setWritable(true, false);
|
dexFile.setWritable(true, false);
|
||||||
dexFile.setReadable(true, false);
|
dexFile.setReadable(true, false);
|
||||||
} else {
|
} else {
|
||||||
DexLog.d("Using cache " + dexFileName);
|
DexLog.d("Using cache " + dexFileName);
|
||||||
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName);
|
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName);
|
||||||
}
|
}
|
||||||
usedCache = true;
|
usedCache = true;
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.swift.sandhook.xposedcompat;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.FileUtils;
|
import io.github.lsposed.lspd.util.FileUtils;
|
||||||
import io.github.lsposed.lspd.util.ProcessUtils;
|
import io.github.lsposed.lspd.util.ProcessUtils;
|
||||||
import io.github.lsposed.lspd.util.ProxyClassLoader;
|
import io.github.lsposed.lspd.util.ProxyClassLoader;
|
||||||
|
|
@ -16,8 +15,6 @@ import java.lang.reflect.Member;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
|
|
||||||
|
|
||||||
public class XposedCompat {
|
public class XposedCompat {
|
||||||
|
|
||||||
// TODO initialize these variables
|
// TODO initialize these variables
|
||||||
|
|
@ -49,11 +46,12 @@ public class XposedCompat {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getCacheDir() {
|
public static File getCacheDir() {
|
||||||
if (cacheDir == null) {
|
// TODO: cache path?
|
||||||
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
|
// if (cacheDir == null) {
|
||||||
cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
|
// String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
|
||||||
+ ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
|
// cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
|
||||||
}
|
// + ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
|
||||||
|
// }
|
||||||
return cacheDir;
|
return cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.swift.sandhook.xposedcompat.methodgen;
|
package com.swift.sandhook.xposedcompat.methodgen;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.SandHookMethodResolver;
|
import com.swift.sandhook.SandHookMethodResolver;
|
||||||
import com.swift.sandhook.wrapper.HookWrapper;
|
import com.swift.sandhook.wrapper.HookWrapper;
|
||||||
|
|
@ -34,6 +33,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
public class HookerDexMaker implements HookMaker {
|
public class HookerDexMaker implements HookMaker {
|
||||||
|
|
||||||
|
|
@ -187,7 +187,7 @@ public class HookerDexMaker implements HookMaker {
|
||||||
HookWrapper.HookEntity hookEntity = null;
|
HookWrapper.HookEntity hookEntity = null;
|
||||||
//try load cache first
|
//try load cache first
|
||||||
try {
|
try {
|
||||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName);
|
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
hookEntity = loadHookerClass(loader, className);
|
hookEntity = loadHookerClass(loader, className);
|
||||||
}
|
}
|
||||||
|
|
@ -215,8 +215,8 @@ public class HookerDexMaker implements HookMaker {
|
||||||
|
|
||||||
ClassLoader loader;
|
ClassLoader loader;
|
||||||
if (canCache) {
|
if (canCache) {
|
||||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true);
|
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
|
||||||
File dexFile = new File(ConfigManager.getCachePath(dexName));
|
File dexFile = new File(serviceClient.getCachePath(dexName));
|
||||||
dexFile.setWritable(true, false);
|
dexFile.setWritable(true, false);
|
||||||
dexFile.setReadable(true, false);
|
dexFile.setReadable(true, false);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.swift.sandhook.xposedcompat.methodgen;
|
package com.swift.sandhook.xposedcompat.methodgen;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import com.swift.sandhook.SandHook;
|
import com.swift.sandhook.SandHook;
|
||||||
import com.swift.sandhook.wrapper.HookWrapper;
|
import com.swift.sandhook.wrapper.HookWrapper;
|
||||||
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
|
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
|
||||||
|
|
@ -30,6 +29,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
|
||||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
public class HookerDexMakerNew implements HookMaker {
|
public class HookerDexMakerNew implements HookMaker {
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ public class HookerDexMakerNew implements HookMaker {
|
||||||
HookWrapper.HookEntity hookEntity = null;
|
HookWrapper.HookEntity hookEntity = null;
|
||||||
//try load cache first
|
//try load cache first
|
||||||
try {
|
try {
|
||||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName);
|
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
hookEntity = loadHookerClass(loader, className);
|
hookEntity = loadHookerClass(loader, className);
|
||||||
}
|
}
|
||||||
|
|
@ -176,8 +176,8 @@ public class HookerDexMakerNew implements HookMaker {
|
||||||
}
|
}
|
||||||
// Create the dex file and load it.
|
// Create the dex file and load it.
|
||||||
try {
|
try {
|
||||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true);
|
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
|
||||||
File dexFile = new File(ConfigManager.getCachePath(dexName));
|
File dexFile = new File(serviceClient.getCachePath(dexName));
|
||||||
dexFile.setWritable(true, false);
|
dexFile.setWritable(true, false);
|
||||||
dexFile.setReadable(true, false);
|
dexFile.setReadable(true, false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.os.Build;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
|
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.nativebridge.Yahfa;
|
import io.github.lsposed.lspd.nativebridge.Yahfa;
|
||||||
import io.github.lsposed.lspd.util.ClassLoaderUtils;
|
import io.github.lsposed.lspd.util.ClassLoaderUtils;
|
||||||
import io.github.lsposed.lspd.util.FileUtils;
|
import io.github.lsposed.lspd.util.FileUtils;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package com.swift.sandhook.xposedcompat.utils;
|
package com.swift.sandhook.xposedcompat.utils;
|
||||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
|
||||||
import io.github.lsposed.lspd.util.Utils;
|
import io.github.lsposed.lspd.util.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -15,12 +14,14 @@ import external.com.android.dx.Code;
|
||||||
import external.com.android.dx.Local;
|
import external.com.android.dx.Local;
|
||||||
import external.com.android.dx.TypeId;
|
import external.com.android.dx.TypeId;
|
||||||
|
|
||||||
|
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||||
|
|
||||||
public class DexMakerUtils {
|
public class DexMakerUtils {
|
||||||
|
|
||||||
public static boolean canCache = true;
|
public static boolean canCache = true;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
File cacheDir = new File(ConfigManager.getCachePath(""));
|
File cacheDir = new File(serviceClient.getCachePath(""));
|
||||||
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
||||||
Utils.logW("Cache disabled");
|
Utils.logW("Cache disabled");
|
||||||
canCache = false;
|
canCache = false;
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,10 @@ else
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
touch /data/adb/lspd/new_install || abortC "! ${LANG_CUST_ERR_CONF_FIRST}"
|
touch /data/adb/lspd/new_install || abortC "! ${LANG_CUST_ERR_CONF_FIRST}"
|
||||||
|
ui_print "- ${LANG_CUST_INST_COPY_LIB}"
|
||||||
|
mkdir -p /data/adb/lspd/config
|
||||||
|
rm -rf "/data/adb/lspd/framework"
|
||||||
|
mv "${MODPATH}/system/framework" "/data/adb/lspd/framework"
|
||||||
set_perm_recursive /data/adb/lspd root root 0700 0600 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
|
set_perm_recursive /data/adb/lspd root root 0700 0600 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
|
||||||
mkdir -p /data/misc/$MISC_PATH/0/conf/ || abortC "! ${LANG_CUST_ERR_CONF_CREATE}"
|
mkdir -p /data/misc/$MISC_PATH/0/conf/ || abortC "! ${LANG_CUST_ERR_CONF_CREATE}"
|
||||||
set_perm /data/misc/$MISC_PATH root root 0771 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
|
set_perm /data/misc/$MISC_PATH root root 0771 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
|
||||||
|
|
@ -230,9 +234,9 @@ echo "rm -rf /data/misc/$MISC_PATH" >> "${MODPATH}/uninstall.sh" || abortC "! ${
|
||||||
echo "[[ -f /data/adb/lspd/new_install ]] || rm -rf /data/adb/lspd" >> "${MODPATH}/uninstall.sh" || abortC "! ${LANG_CUST_ERR_CONF_UNINST}"
|
echo "[[ -f /data/adb/lspd/new_install ]] || rm -rf /data/adb/lspd" >> "${MODPATH}/uninstall.sh" || abortC "! ${LANG_CUST_ERR_CONF_UNINST}"
|
||||||
|
|
||||||
if [ $VARIANT == 17 ]; then # YAHFA
|
if [ $VARIANT == 17 ]; then # YAHFA
|
||||||
echo "1" > /data/misc/$MISC_PATH/variant
|
echo "1" > /data/adb/lspd/config/variant
|
||||||
elif [ $VARIANT == 18 ]; then # SandHook
|
elif [ $VARIANT == 18 ]; then # SandHook
|
||||||
echo "2" > /data/misc/$MISC_PATH/variant
|
echo "2" > /data/adb/lspd/config/variant
|
||||||
else
|
else
|
||||||
abortC "${LANG_UTIL_ERR_VARIANT_UNSUPPORT} ${VARIANT}"
|
abortC "${LANG_UTIL_ERR_VARIANT_UNSUPPORT} ${VARIANT}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -241,12 +245,6 @@ if [[ ! -e /data/misc/$MISC_PATH/disable_verbose_log ]]; then
|
||||||
echo "1" > /data/misc/$MISC_PATH/disable_verbose_log
|
echo "1" > /data/misc/$MISC_PATH/disable_verbose_log
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_print "- ${LANG_CUST_INST_COPY_LIB}"
|
|
||||||
|
|
||||||
rm -rf "/data/misc/$MISC_PATH/framework"
|
|
||||||
mv "${MODPATH}/system/framework" "/data/misc/$MISC_PATH/framework"
|
|
||||||
|
|
||||||
set_perm_recursive /data/misc/$MISC_PATH/framework root root 0755 0644 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
|
|
||||||
|
|
||||||
mkdir -p /data/misc/$MISC_PATH/cache
|
mkdir -p /data/misc/$MISC_PATH/cache
|
||||||
rm /data/misc/$MISC_PATH/cache/*
|
rm /data/misc/$MISC_PATH/cache/*
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,4 @@ if [[ -f "${MODDIR}/reboot_twice_flag" ]]; then
|
||||||
reboot
|
reboot
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MISC_PATH=$(cat /data/adb/lspd/misc_path)
|
/system/bin/app_process -Djava.class.path=/data/adb/lspd/framework/lspd.dex /system/bin --nice-name=lspd io.github.lsposed.lspd.core.Main
|
||||||
BASE_PATH="/data/misc/$MISC_PATH"
|
|
||||||
|
|
||||||
/system/bin/app_process -Djava.class.path=${BASE_PATH}/framework/lspd.dex /system/bin --nice-name=lspd io.github.lsposed.lspd.core.Main
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue