[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 {
|
||||
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
|
||||
|
||||
#include <base/object.h>
|
||||
#include <config_manager.h>
|
||||
|
||||
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 kClassLinkerClassName = "io.github.lsposed.lspd.nativebridge.ClassLinker"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 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 <android-base/macros.h>
|
||||
#include "JNIHelper.h"
|
||||
#include "jni/config_manager.h"
|
||||
#include "jni/art_class_linker.h"
|
||||
#include "jni/yahfa.h"
|
||||
#include "jni/resources_hook.h"
|
||||
|
|
@ -32,12 +31,13 @@
|
|||
#include <sandhook.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <nativehelper/scoped_local_ref.h>
|
||||
#include "context.h"
|
||||
#include "config_manager.h"
|
||||
#include "native_hook.h"
|
||||
#include "jni/logger.h"
|
||||
#include "jni/native_api.h"
|
||||
#include "service.h"
|
||||
#include "rirud_socket.h"
|
||||
|
||||
namespace lspd {
|
||||
namespace fs = std::filesystem;
|
||||
|
|
@ -66,13 +66,14 @@ namespace lspd {
|
|||
void Context::PreLoadDex(const fs::path &dex_path) {
|
||||
if (LIKELY(!dex.empty())) return;
|
||||
|
||||
std::ifstream is(dex_path, std::ios::binary);
|
||||
if (!is.good()) {
|
||||
LOGE("Cannot load path %s", dex_path.c_str());
|
||||
try {
|
||||
RirudSocket socket;
|
||||
auto dex_content = socket.ReadFile(dex_path);
|
||||
dex.assign(dex_content.begin(), dex_content.end());
|
||||
} catch (RirudSocket::RirudSocketException &e) {
|
||||
LOGE("%s", e.what());
|
||||
return;
|
||||
}
|
||||
dex.assign(std::istreambuf_iterator<char>(is),
|
||||
std::istreambuf_iterator<char>());
|
||||
LOGI("Loaded %s with size %zu", dex_path.c_str(), dex.size());
|
||||
}
|
||||
|
||||
|
|
@ -108,9 +109,6 @@ namespace lspd {
|
|||
env->DeleteLocalRef(my_cl);
|
||||
|
||||
env->GetJavaVM(&vm_);
|
||||
|
||||
// Make sure config manager is always working
|
||||
RegisterConfigManagerMethods(env);
|
||||
}
|
||||
|
||||
void Context::Init(JNIEnv *env) {
|
||||
|
|
@ -193,7 +191,6 @@ namespace lspd {
|
|||
void
|
||||
Context::OnNativeForkSystemServerPre(JNIEnv *env) {
|
||||
Service::instance()->InitService(env);
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
skip_ = false;
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +223,6 @@ namespace lspd {
|
|||
jstring nice_name,
|
||||
jboolean is_child_zygote,
|
||||
jstring app_data_dir) {
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
Service::instance()->InitService(env);
|
||||
const auto app_id = uid % PER_USER_RANGE;
|
||||
nice_name_ = nice_name;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ namespace lspd {
|
|||
|
||||
void OnNativeForkSystemServerPre(JNIEnv *env);
|
||||
|
||||
void PreLoadDex(const std::filesystem::path &dex_paths);
|
||||
|
||||
private:
|
||||
inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>();
|
||||
|
|
@ -79,8 +80,6 @@ namespace lspd {
|
|||
|
||||
Context() {}
|
||||
|
||||
void PreLoadDex(const std::filesystem::path &dex_paths);
|
||||
|
||||
void LoadDex(JNIEnv *env);
|
||||
|
||||
void Init(JNIEnv *env);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <nativehelper/jni_macros.h>
|
||||
#include <vector>
|
||||
#include <HookMain.h>
|
||||
#include <unordered_set>
|
||||
#include "art_class_linker.h"
|
||||
|
||||
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 "native_util.h"
|
||||
#include "JNIHelper.h"
|
||||
#include "../config_manager.h"
|
||||
#include <fstream>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace lspd {
|
||||
LSP_DEF_NATIVE_METHOD(void, Logger, nativeLog, jstring jstr) {
|
||||
static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGD("Logger fail: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
JUTFString str(env, jstr);
|
||||
int res = write(fd, str.get(), std::strlen(str.get()));
|
||||
if (res < 0) {
|
||||
LOGD("Logger fail: %s", strerror(errno));
|
||||
}
|
||||
// TODO: get log path
|
||||
// static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY);
|
||||
// if (fd < 0) {
|
||||
// LOGD("Logger fail: %s", strerror(errno));
|
||||
// return;
|
||||
// }
|
||||
// JUTFString str(env, jstr);
|
||||
// int res = write(fd, str.get(), std::strlen(str.get()));
|
||||
// if (res < 0) {
|
||||
// LOGD("Logger fail: %s", strerror(errno));
|
||||
// }
|
||||
}
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
|
|
|
|||
|
|
@ -26,15 +26,14 @@
|
|||
#include "config.h"
|
||||
#include "context.h"
|
||||
#include <riru.h>
|
||||
#include "config_manager.h"
|
||||
#include "symbol_cache.h"
|
||||
|
||||
namespace lspd {
|
||||
static void onModuleLoaded() {
|
||||
LOGI("onModuleLoaded: welcome to LSPosed!");
|
||||
// rirud must be used in onModuleLoaded
|
||||
Context::GetInstance()->PreLoadDex(kDexPath);
|
||||
InitSymbolCache();
|
||||
ConfigManager::Init();
|
||||
}
|
||||
|
||||
static int shouldSkipUid(int) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#include <dlfcn.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <config_manager.h>
|
||||
#include <art/runtime/runtime.h>
|
||||
#include <dl_util.h>
|
||||
#include <art/runtime/jni_env_ext.h>
|
||||
|
|
|
|||
|
|
@ -152,8 +152,10 @@ namespace lspd {
|
|||
|
||||
jobject service = nullptr;
|
||||
if (res) {
|
||||
JNI_CallVoidMethod(env, reply, readExceptionMethod_);
|
||||
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
||||
env->CallVoidMethod(reply, readExceptionMethod_);
|
||||
if (!ClearException(env)) {
|
||||
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
||||
}
|
||||
}
|
||||
JNI_CallVoidMethod(env, data, recycleMethod_);
|
||||
JNI_CallVoidMethod(env, reply, recycleMethod_);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ import java.util.Set;
|
|||
|
||||
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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
if (newModule && XposedInit.prefsBasePath != null) {
|
||||
mFile = new File(XposedInit.prefsBasePath, packageName + "/" + prefFileName + ".xml");
|
||||
if (newModule) {
|
||||
|
||||
mFile = new File(serviceClient.getPrefsPath( packageName ), prefFileName + ".xml");
|
||||
} else {
|
||||
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();
|
||||
try {
|
||||
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");
|
||||
}
|
||||
mWatchKey = path.getParent().register(sWatcher, StandardWatchEventKinds.ENTRY_CREATE,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import android.content.res.TypedArray;
|
|||
import android.util.Log;
|
||||
|
||||
import io.github.lsposed.lspd.BuildConfig;
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
|
|
@ -98,15 +97,6 @@ public final class 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 */
|
||||
// protected static final class ToolEntryPoint {
|
||||
// protected static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ import android.util.Log;
|
|||
|
||||
import com.android.internal.os.ZygoteInit;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
|
@ -49,6 +48,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
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.setStaticLongField;
|
||||
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
public final class XposedInit {
|
||||
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";
|
||||
public static volatile boolean disableResources = false;
|
||||
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
|
||||
public static String prefsBasePath = null;
|
||||
|
||||
private XposedInit() {
|
||||
}
|
||||
|
|
@ -113,7 +113,7 @@ public final class XposedInit {
|
|||
|
||||
@ApiSensitive(Level.MIDDLE)
|
||||
private static void hookResources() throws Throwable {
|
||||
if (!ConfigManager.isResourcesHookEnabled() || disableResources) {
|
||||
if (!serviceClient.isResourcesHookEnabled() || disableResources) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -353,12 +353,9 @@ public final class XposedInit {
|
|||
topClassLoader = parent;
|
||||
}
|
||||
|
||||
String moduleList = ConfigManager.getModulesList();
|
||||
InputStream stream = new ByteArrayInputStream(moduleList.getBytes());
|
||||
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
|
||||
List<String> moduleList = serviceClient.getModulesList();
|
||||
ArraySet<String> newLoadedApk = new ArraySet<>();
|
||||
String apk;
|
||||
while ((apk = apks.readLine()) != null) {
|
||||
for (String apk : moduleList)
|
||||
if (loadedModules.contains(apk)) {
|
||||
newLoadedApk.add(apk);
|
||||
} else {
|
||||
|
|
@ -368,10 +365,9 @@ public final class XposedInit {
|
|||
newLoadedApk.add(apk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadedModules.clear();
|
||||
loadedModules.addAll(newLoadedApk);
|
||||
apks.close();
|
||||
|
||||
// refresh callback according to current loaded module list
|
||||
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 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.ServiceManager;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
|
|
@ -43,15 +45,9 @@ public class Main implements KeepAll {
|
|||
private static final Binder heartBeatBinder = new Binder();
|
||||
|
||||
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
|
||||
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
||||
final int variant;
|
||||
try {
|
||||
service.registerHeartBeat(heartBeatBinder);
|
||||
variant = service.getVariant();
|
||||
} catch (RemoteException e) {
|
||||
Utils.logW("Register fail", e);
|
||||
return;
|
||||
}
|
||||
LSPApplicationServiceClient.Init(binder);
|
||||
serviceClient.registerHeartBeat(heartBeatBinder);
|
||||
final int variant = serviceClient.getVariant();
|
||||
EdxpImpl lspd = getEdxpImpl(variant);
|
||||
if (lspd == null || !lspd.isInitialized()) {
|
||||
Utils.logE("Not started up");
|
||||
|
|
@ -61,15 +57,9 @@ public class Main implements KeepAll {
|
|||
}
|
||||
|
||||
public static void forkSystemServerPost(IBinder binder) {
|
||||
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder);
|
||||
final int variant;
|
||||
try {
|
||||
service.registerHeartBeat(heartBeatBinder);
|
||||
variant = service.getVariant();
|
||||
} catch (RemoteException e) {
|
||||
Utils.logW("Register fail", e);
|
||||
return;
|
||||
}
|
||||
LSPApplicationServiceClient.Init(binder);
|
||||
serviceClient.registerHeartBeat(heartBeatBinder);
|
||||
final int variant = serviceClient.getVariant();
|
||||
EdxpImpl lspd = getEdxpImpl(variant);
|
||||
if (lspd == null || !lspd.isInitialized()) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ package io.github.lsposed.lspd.deopt;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.config.LSPdConfigGlobal;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
|
|
@ -30,6 +29,7 @@ import java.util.Arrays;
|
|||
|
||||
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_MIUI_RES;
|
||||
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
|
||||
deoptMethods(KEY_BOOT_IMAGE, null);
|
||||
if (!TextUtils.isEmpty(Utils.getSysProp("ro.miui.ui.version.code"))
|
||||
&& ConfigManager.isResourcesHookEnabled()) {
|
||||
&& serviceClient.isResourcesHookEnabled()) {
|
||||
//deopt these only for MIUI with resources hook enabled
|
||||
deoptMethods(KEY_BOOT_IMAGE_MIUI_RES, null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* Copyright (C) 2021 LSPosed Contributors
|
||||
*/
|
||||
|
||||
package io.github.lsposed.lspd._hooker.impl;
|
||||
package io.github.lsposed.lspd.hooker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityThread;
|
||||
|
|
@ -30,7 +30,6 @@ import android.content.pm.ApplicationInfo;
|
|||
import android.content.res.CompatibilityInfo;
|
||||
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.MetaDataReader;
|
||||
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.XposedInit;
|
||||
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
// 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
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
|
|
@ -57,10 +63,10 @@ public class HandleBindApp extends XC_MethodHook {
|
|||
Object bindData = param.args[0];
|
||||
final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo");
|
||||
// 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;
|
||||
Utils.logD("processName=" + ConfigManager.appProcessName +
|
||||
", packageName=" + reportedPackageName + ", appDataDir=" + ConfigManager.appDataDir);
|
||||
Utils.logD("processName=" + appProcessName +
|
||||
", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir);
|
||||
|
||||
ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName");
|
||||
if (instrumentationName != null) {
|
||||
|
|
@ -118,7 +124,7 @@ public class HandleBindApp extends XC_MethodHook {
|
|||
XposedHelpers.findAndHookMethod(ContextImpl.class, "getPreferencesDir", new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
File newDir = new File(ConfigManager.getPrefsPath(appInfo.packageName));
|
||||
File newDir = new File(serviceClient.getPrefsPath(appInfo.packageName));
|
||||
if (migratePrefs) {
|
||||
File oldDir = (File) param.getResult();
|
||||
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);
|
||||
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
||||
LoadedApk.class, "getClassLoader", hook));
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
* 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.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
|
||||
// ed: remove resources related hooking
|
||||
public class LoadedApkCstr extends XC_MethodHook {
|
||||
public class LoadedApkCstrHooker extends XC_MethodHook {
|
||||
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||
|
|
@ -70,7 +70,7 @@ public class LoadedApkCstr extends XC_MethodHook {
|
|||
return;
|
||||
}
|
||||
|
||||
LoadedApkGetCL hook = new LoadedApkGetCL(loadedApk, packageName,
|
||||
LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, packageName,
|
||||
AndroidAppHelper.currentProcessName(), false);
|
||||
hook.setUnhook(XposedHelpers.findAndHookMethod(
|
||||
LoadedApk.class, "getClassLoader", hook));
|
||||
|
|
@ -18,20 +18,22 @@
|
|||
* Copyright (C) 2021 LSPosed Contributors
|
||||
*/
|
||||
|
||||
package io.github.lsposed.lspd._hooker.impl;
|
||||
package io.github.lsposed.lspd.hooker;
|
||||
|
||||
import android.app.LoadedApk;
|
||||
import android.os.IBinder;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
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.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 String packageName;
|
||||
|
|
@ -39,8 +41,8 @@ public class LoadedApkGetCL extends XC_MethodHook {
|
|||
private final boolean isFirstApplication;
|
||||
private Unhook unhook;
|
||||
|
||||
public LoadedApkGetCL(LoadedApk loadedApk, String packageName, String processName,
|
||||
boolean isFirstApplication) {
|
||||
public LoadedApkGetCLHooker(LoadedApk loadedApk, String packageName, String processName,
|
||||
boolean isFirstApplication) {
|
||||
this.loadedApk = loadedApk;
|
||||
this.packageName = packageName;
|
||||
this.processName = processName;
|
||||
|
|
@ -76,9 +78,10 @@ public class LoadedApkGetCL extends XC_MethodHook {
|
|||
lpparam.appInfo = loadedApk.getApplicationInfo();
|
||||
lpparam.isFirstApplication = this.isFirstApplication;
|
||||
|
||||
if (packageName.equals(ConfigManager.getInstallerPackageName())) {
|
||||
IBinder binder = serviceClient.requestManagerBinder();
|
||||
if (binder != null) {
|
||||
if (InstallerVerifier.verifyInstallerSignature(loadedApk.getApplicationInfo())) {
|
||||
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader);
|
||||
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader, binder);
|
||||
} else {
|
||||
InstallerVerifier.hookXposedInstaller(classLoader);
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
* Copyright (C) 2021 LSPosed Contributors
|
||||
*/
|
||||
|
||||
package io.github.lsposed.lspd._hooker.impl;
|
||||
package io.github.lsposed.lspd.hooker;
|
||||
|
||||
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 de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||
|
||||
public class StartBootstrapServices extends XC_MethodHook {
|
||||
public class StartBootstrapServicesHooker extends XC_MethodHook {
|
||||
|
||||
@Override
|
||||
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);
|
||||
lpparam.packageName = "android";
|
||||
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.isFirstApplication = true;
|
||||
XC_LoadPackage.callAll(lpparam);
|
||||
|
|
@ -58,14 +58,14 @@ public class StartBootstrapServices extends XC_MethodHook {
|
|||
// Huawei
|
||||
try {
|
||||
findAndHookMethod("com.android.server.pm.HwPackageManagerService",
|
||||
SystemMain.systemServerCL, "isOdexMode",
|
||||
SystemMainHooker.systemServerCL, "isOdexMode",
|
||||
XC_MethodReplacement.returnConstant(false));
|
||||
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService");
|
||||
findAndHookMethod(className, SystemMain.systemServerCL,
|
||||
findAndHookMethod(className, SystemMainHooker.systemServerCL,
|
||||
"dexEntryExists", String.class,
|
||||
XC_MethodReplacement.returnConstant(true));
|
||||
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
* 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.deopt.PrebuiltMethodsDeopter;
|
||||
|
|
@ -29,7 +29,7 @@ import de.robv.android.xposed.XposedBridge;
|
|||
|
||||
// system_server initialization
|
||||
// ed: only support sdk >= 21 for now
|
||||
public class SystemMain extends XC_MethodHook {
|
||||
public class SystemMainHooker extends XC_MethodHook {
|
||||
|
||||
public static volatile ClassLoader systemServerCL;
|
||||
|
||||
|
|
@ -20,19 +20,16 @@
|
|||
|
||||
package io.github.lsposed.lspd.hooker;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodReplacement;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import android.os.IBinder;
|
||||
|
||||
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.Main;
|
||||
import io.github.lsposed.lspd.service.BridgeService;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
public class XposedInstallerHooker {
|
||||
|
||||
public static void hookXposedInstaller(final ClassLoader classLoader) {
|
||||
public static void hookXposedInstaller(final ClassLoader classLoader, IBinder binder) {
|
||||
final String variant;
|
||||
switch (Main.getEdxpVariant()) {
|
||||
case EdxpImpl.YAHFA:
|
||||
|
|
@ -51,72 +48,8 @@ public class XposedInstallerHooker {
|
|||
|
||||
// LSPosed Manager R
|
||||
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);
|
||||
// XposedHelpers.setStaticObjectField(serviceClass, "binder", BridgeService.requireBinder());
|
||||
XposedHelpers.setStaticObjectField(serviceClass, "binder", binder);
|
||||
|
||||
Utils.logI("Hooked LSPosed Manager");
|
||||
} 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.text.TextUtils;
|
||||
|
||||
import io.github.lsposed.lspd._hooker.impl.HandleBindApp;
|
||||
import io.github.lsposed.lspd._hooker.impl.LoadedApkCstr;
|
||||
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
|
||||
import io.github.lsposed.lspd._hooker.impl.SystemMain;
|
||||
import io.github.lsposed.lspd.hooker.HandleBindAppHooker;
|
||||
import io.github.lsposed.lspd.hooker.LoadedApkCstrHooker;
|
||||
import io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker;
|
||||
import io.github.lsposed.lspd.hooker.SystemMainHooker;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
import io.github.lsposed.lspd.util.Versions;
|
||||
|
||||
|
|
@ -53,13 +53,13 @@ public abstract class BaseRouter implements Router {
|
|||
XposedInit.startsSystemServer = isSystem;
|
||||
}
|
||||
|
||||
public void installBootstrapHooks(boolean isSystem) {
|
||||
public void installBootstrapHooks(boolean isSystem, String appDataDir) {
|
||||
// Initialize the Xposed framework
|
||||
try {
|
||||
if (!bootstrapHooked.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
startBootstrapHook(isSystem);
|
||||
startBootstrapHook(isSystem, appDataDir);
|
||||
XposedInit.initForZygote(isSystem);
|
||||
} catch (Throwable t) {
|
||||
Utils.logE("error during Xposed initialization", t);
|
||||
|
|
@ -88,30 +88,30 @@ public abstract class BaseRouter implements Router {
|
|||
|
||||
|
||||
@ApiSensitive(Level.LOW)
|
||||
public void startBootstrapHook(boolean isSystem) {
|
||||
public void startBootstrapHook(boolean isSystem, String appDataDir) {
|
||||
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
|
||||
ClassLoader classLoader = BaseRouter.class.getClassLoader();
|
||||
if (isSystem) {
|
||||
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
||||
"systemMain", new SystemMain());
|
||||
"systemMain", new SystemMainHooker());
|
||||
}
|
||||
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
|
||||
"handleBindApplication",
|
||||
"android.app.ActivityThread$AppBindData",
|
||||
new HandleBindApp());
|
||||
new HandleBindAppHooker(appDataDir));
|
||||
XposedHelpers.findAndHookConstructor("android.app.LoadedApk", classLoader,
|
||||
ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class,
|
||||
ClassLoader.class, boolean.class, boolean.class, boolean.class,
|
||||
new LoadedApkCstr());
|
||||
new LoadedApkCstrHooker());
|
||||
}
|
||||
|
||||
public void startSystemServerHook() {
|
||||
StartBootstrapServices sbsHooker = new StartBootstrapServices();
|
||||
StartBootstrapServicesHooker sbsHooker = new StartBootstrapServicesHooker();
|
||||
Object[] paramTypesAndCallback = Versions.hasR() ?
|
||||
new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} :
|
||||
new Object[]{sbsHooker};
|
||||
XposedHelpers.findAndHookMethod("com.android.server.SystemServer",
|
||||
SystemMain.systemServerCL,
|
||||
SystemMainHooker.systemServerCL,
|
||||
"startBootstrapServices", paramTypesAndCallback);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@
|
|||
|
||||
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.util.Utils;
|
||||
|
||||
import de.robv.android.xposed.SELinuxHelper;
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
|
||||
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
|
||||
|
||||
public class NormalProxy extends BaseProxy {
|
||||
|
||||
public NormalProxy(Router router) {
|
||||
|
|
@ -41,7 +42,7 @@ public class NormalProxy extends BaseProxy {
|
|||
|
||||
public void forkSystemServerPost() {
|
||||
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.prepare(isSystem);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||
ConfigManager.appDataDir = appDataDir;
|
||||
ConfigManager.niceName = niceName;
|
||||
mRouter.installBootstrapHooks(isSystem);
|
||||
XposedInit.prefsBasePath = ConfigManager.getPrefsPath("");
|
||||
mRouter.installBootstrapHooks(isSystem, appDataDir);
|
||||
mRouter.onEnterChildProcess();
|
||||
Utils.logI("Loading modules for " + niceName);
|
||||
mRouter.loadModulesSafely(true);
|
||||
|
|
|
|||
|
|
@ -26,13 +26,11 @@ public interface Router {
|
|||
|
||||
void prepare(boolean isSystem);
|
||||
|
||||
String parsePackageName(String appDataDir);
|
||||
|
||||
void installBootstrapHooks(boolean isSystem);
|
||||
void installBootstrapHooks(boolean isSystem, String appDataDir);
|
||||
|
||||
void loadModulesSafely(boolean callInitZygote);
|
||||
|
||||
void startBootstrapHook(boolean isSystem);
|
||||
void startBootstrapHook(boolean isSystem, String appDataDir);
|
||||
|
||||
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.proxy.BaseRouter;
|
||||
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 de.robv.android.xposed.XposedBridge;
|
||||
|
||||
public class SandHookRouter extends BaseRouter {
|
||||
|
||||
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() {
|
||||
SandHookXposedBridge.onForkPost();
|
||||
//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 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.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
|
|
@ -59,7 +59,7 @@ public class LoadedApkConstructorHooker implements KeepMembers {
|
|||
ApplicationInfo aInfo, CompatibilityInfo compatInfo,
|
||||
ClassLoader baseLoader, boolean securityViolation,
|
||||
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();
|
||||
param.thisObject = thiz;
|
||||
param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
package io.github.lsposed.lspd.sandhook.hooker;
|
||||
|
||||
import io.github.lsposed.common.KeepMembers;
|
||||
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
|
||||
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
|
|
@ -45,7 +45,7 @@ public class StartBootstrapServicesHooker implements KeepMembers {
|
|||
|
||||
@HookMethod("startBootstrapServices")
|
||||
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();
|
||||
param.thisObject = systemServer;
|
||||
param.args = new Object[]{};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
package io.github.lsposed.lspd.sandhook.hooker;
|
||||
|
||||
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.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
|
|
@ -49,7 +49,7 @@ public class StartBootstrapServicesHooker11 implements KeepMembers {
|
|||
|
||||
@HookMethod("startBootstrapServices")
|
||||
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();
|
||||
param.thisObject = systemServer;
|
||||
param.args = new Object[]{traceAndSlog};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ package io.github.lsposed.lspd.sandhook.hooker;
|
|||
import android.app.ActivityThread;
|
||||
|
||||
import io.github.lsposed.common.KeepMembers;
|
||||
import io.github.lsposed.lspd._hooker.impl.SystemMain;
|
||||
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
|
|
@ -53,7 +53,7 @@ public class SystemMainHooker implements KeepMembers {
|
|||
|
||||
@HookMethod("systemMain")
|
||||
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();
|
||||
param.thisObject = null;
|
||||
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.
|
||||
// Otherwise, user should maintain it manually.
|
||||
// TODO: manager package name supports
|
||||
public class ConfigManager {
|
||||
static ConfigManager instance = null;
|
||||
|
||||
|
|
@ -52,6 +51,9 @@ public class ConfigManager {
|
|||
private String manager = null;
|
||||
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");
|
||||
// only check on boot
|
||||
final private boolean isPermissive;
|
||||
|
|
@ -69,7 +71,7 @@ public class ConfigManager {
|
|||
};
|
||||
|
||||
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) {
|
||||
|
|
@ -108,6 +110,7 @@ public class ConfigManager {
|
|||
resourceHook = resourceHookSwitch.exists();
|
||||
variant = readInt(variantSwitch, -1);
|
||||
verboseLog = readInt(verboseLogSwitch, 0) == 1;
|
||||
miscPath = "/data/misc/" + readText(miscFile, "lspd");
|
||||
updateManager();
|
||||
}
|
||||
|
||||
|
|
@ -333,4 +336,12 @@ public class ConfigManager {
|
|||
public boolean isManager(int uid) {
|
||||
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.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
|
@ -35,6 +36,30 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
|||
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
|
||||
@Override
|
||||
public IBinder requestModuleBinder() throws RemoteException {
|
||||
|
|
@ -42,7 +67,6 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
|||
return ServiceManager.getModuleService();
|
||||
}
|
||||
|
||||
// TODO: check if manager
|
||||
@Override
|
||||
public IBinder requestManagerBinder() throws RemoteException {
|
||||
ensureRegistered();
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import android.os.RemoteException;
|
|||
import android.os.UserHandle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -78,63 +77,65 @@ public class PackageReceiver {
|
|||
|
||||
private Map<String, String> loadEnabledModules(int uid) {
|
||||
HashMap<String, String> result = new HashMap<>();
|
||||
try {
|
||||
File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||
if (!enabledModules.exists()) return result;
|
||||
Scanner scanner = new Scanner(enabledModules);
|
||||
while (scanner.hasNextLine()) {
|
||||
String packageName = scanner.nextLine();
|
||||
PackageInfo info = getPackageInfo(packageName, 0);
|
||||
if (info != null && isXposedModule(info.applicationInfo))
|
||||
result.put(packageName, info.applicationInfo.sourceDir);
|
||||
else if (info == null)
|
||||
result.put(packageName, null);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Utils.logE("Unable to read enabled modules", e);
|
||||
}
|
||||
// TODO: FIXME
|
||||
// try {
|
||||
// File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||
// if (!enabledModules.exists()) return result;
|
||||
// Scanner scanner = new Scanner(enabledModules);
|
||||
// while (scanner.hasNextLine()) {
|
||||
// String packageName = scanner.nextLine();
|
||||
// PackageInfo info = getPackageInfo(packageName, 0);
|
||||
// if (info != null && isXposedModule(info.applicationInfo))
|
||||
// result.put(packageName, info.applicationInfo.sourceDir);
|
||||
// else if (info == null)
|
||||
// result.put(packageName, null);
|
||||
// }
|
||||
// } catch (Throwable e) {
|
||||
// Utils.logE("Unable to read enabled modules", e);
|
||||
// }
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean updateModuleList(int uid, String packageName) {
|
||||
Map<String, String> enabledModules = loadEnabledModules(uid);
|
||||
|
||||
if (!enabledModules.containsKey(packageName)) return false;
|
||||
|
||||
try {
|
||||
File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME);
|
||||
File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||
if (moduleListFile.exists() && !moduleListFile.canWrite()) {
|
||||
moduleListFile.delete();
|
||||
moduleListFile.createNewFile();
|
||||
}
|
||||
if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) {
|
||||
enabledModuleListFile.delete();
|
||||
enabledModuleListFile.createNewFile();
|
||||
}
|
||||
PrintWriter modulesList = new PrintWriter(moduleListFile);
|
||||
PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile);
|
||||
for (Map.Entry<String, String> module : enabledModules.entrySet()) {
|
||||
String apkPath = module.getValue();
|
||||
if (apkPath != null) {
|
||||
modulesList.println(module.getValue());
|
||||
enabledModulesList.println(module.getKey());
|
||||
} else {
|
||||
Utils.logI(String.format("remove obsolete package %s", packageName));
|
||||
File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName);
|
||||
File[] fileList = prefsDir.listFiles();
|
||||
if (fileList != null) {
|
||||
for (File childFile : fileList) {
|
||||
childFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
modulesList.close();
|
||||
enabledModulesList.close();
|
||||
} catch (Throwable e) {
|
||||
Utils.logE("Fail to update module list", e);
|
||||
}
|
||||
// TODO: FIXME
|
||||
//
|
||||
// if (!enabledModules.containsKey(packageName)) return false;
|
||||
//
|
||||
// try {
|
||||
// File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME);
|
||||
// File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
|
||||
// if (moduleListFile.exists() && !moduleListFile.canWrite()) {
|
||||
// moduleListFile.delete();
|
||||
// moduleListFile.createNewFile();
|
||||
// }
|
||||
// if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) {
|
||||
// enabledModuleListFile.delete();
|
||||
// enabledModuleListFile.createNewFile();
|
||||
// }
|
||||
// PrintWriter modulesList = new PrintWriter(moduleListFile);
|
||||
// PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile);
|
||||
// for (Map.Entry<String, String> module : enabledModules.entrySet()) {
|
||||
// String apkPath = module.getValue();
|
||||
// if (apkPath != null) {
|
||||
// modulesList.println(module.getValue());
|
||||
// enabledModulesList.println(module.getKey());
|
||||
// } else {
|
||||
// Utils.logI(String.format("remove obsolete package %s", packageName));
|
||||
// File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName);
|
||||
// File[] fileList = prefsDir.listFiles();
|
||||
// if (fileList != null) {
|
||||
// for (File childFile : fileList) {
|
||||
// childFile.delete();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// modulesList.close();
|
||||
// enabledModulesList.close();
|
||||
// } catch (Throwable e) {
|
||||
// Utils.logE("Fail to update module list", e);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -168,36 +169,37 @@ public class PackageReceiver {
|
|||
PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0));
|
||||
|
||||
if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return;
|
||||
|
||||
try {
|
||||
for (int uid : UserService.getUsers()) {
|
||||
Utils.logI("updating uid: " + uid);
|
||||
boolean activated = updateModuleList(uid, packageName);
|
||||
UserHandle userHandle = null;
|
||||
try {
|
||||
userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid);
|
||||
} catch (Throwable t) {
|
||||
Utils.logW("get user handle failed", t);
|
||||
}
|
||||
if (userHandle != null) {
|
||||
try {
|
||||
Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED);
|
||||
broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000);
|
||||
broadCast.setData(intent.getData());
|
||||
broadCast.setPackage(ConfigManager.getInstallerPackageName());
|
||||
XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle);
|
||||
Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName());
|
||||
} catch (Throwable t) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Utils.logW("update failed", e);
|
||||
}
|
||||
// TODO: FIXME
|
||||
//
|
||||
// try {
|
||||
// for (int uid : UserService.getUsers()) {
|
||||
// Utils.logI("updating uid: " + uid);
|
||||
// boolean activated = updateModuleList(uid, packageName);
|
||||
// UserHandle userHandle = null;
|
||||
// try {
|
||||
// userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid);
|
||||
// } catch (Throwable t) {
|
||||
// Utils.logW("get user handle failed", t);
|
||||
// }
|
||||
// if (userHandle != null) {
|
||||
// try {
|
||||
// Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED);
|
||||
// broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000);
|
||||
// broadCast.setData(intent.getData());
|
||||
// broadCast.setPackage(ConfigManager.getInstallerPackageName());
|
||||
// XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle);
|
||||
// Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName());
|
||||
// } catch (Throwable t) {
|
||||
// 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();
|
||||
// }
|
||||
// }
|
||||
// } catch (Throwable e) {
|
||||
// Utils.logW("update failed", e);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import android.os.ServiceManager;
|
|||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.utils.ParceledListSlice;
|
||||
|
||||
public class PackageService {
|
||||
|
|
@ -35,15 +34,6 @@ public class PackageService {
|
|||
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 {
|
||||
ArrayList<PackageInfo> res = new ArrayList<>();
|
||||
IPackageManager pm = getPackageManager();
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ package io.github.lsposed.lspd.util;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
|
|
@ -90,8 +88,4 @@ public class FileUtils {
|
|||
}
|
||||
return dataDir.substring(lastIndex + 1);
|
||||
}
|
||||
|
||||
public static String getDataPathPrefix() {
|
||||
return ConfigManager.getDataPathPrefix() + "/";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
package io.github.lsposed.lspd.yahfa.dexmaker;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
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.TypeId;
|
||||
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class DexMakerUtils {
|
||||
|
||||
public static boolean canCache = true;
|
||||
|
||||
static {
|
||||
File cacheDir = new File(ConfigManager.getCachePath(""));
|
||||
File cacheDir = new File(serviceClient.getCachePath(""));
|
||||
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
||||
Utils.logW("Cache disabled");
|
||||
Utils.logW("Cache disabled with path " + cacheDir.getAbsolutePath());
|
||||
canCache = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import android.annotation.TargetApi;
|
|||
import android.os.Build;
|
||||
|
||||
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.util.ProxyClassLoader;
|
||||
|
||||
|
|
@ -46,6 +45,7 @@ import external.com.android.dx.Local;
|
|||
import external.com.android.dx.MethodId;
|
||||
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.autoUnboxIfNecessary;
|
||||
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.canCache;
|
||||
|
|
@ -167,17 +167,17 @@ public class HookerDexMaker {
|
|||
String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
|
||||
className = className + suffix;
|
||||
String dexFileName = className + ".jar";
|
||||
File dexFile = new File(ConfigManager.getCachePath(dexFileName));
|
||||
File dexFile = new File(serviceClient.getCachePath(dexFileName));
|
||||
if (!dexFile.exists()) {
|
||||
// if file exists, reuse it and skip generating
|
||||
DexLog.d("Generating " + dexFileName);
|
||||
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.setReadable(true, false);
|
||||
} else {
|
||||
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;
|
||||
} catch (Throwable ignored) {}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.swift.sandhook.xposedcompat;
|
|||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.util.FileUtils;
|
||||
import io.github.lsposed.lspd.util.ProcessUtils;
|
||||
import io.github.lsposed.lspd.util.ProxyClassLoader;
|
||||
|
|
@ -16,8 +15,6 @@ import java.lang.reflect.Member;
|
|||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
|
||||
|
||||
public class XposedCompat {
|
||||
|
||||
// TODO initialize these variables
|
||||
|
|
@ -49,11 +46,12 @@ public class XposedCompat {
|
|||
}
|
||||
|
||||
public static File getCacheDir() {
|
||||
if (cacheDir == null) {
|
||||
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
|
||||
cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
|
||||
+ ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
|
||||
}
|
||||
// TODO: cache path?
|
||||
// if (cacheDir == null) {
|
||||
// String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
|
||||
// cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
|
||||
// + ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
|
||||
// }
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.swift.sandhook.xposedcompat.methodgen;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.SandHookMethodResolver;
|
||||
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.getObjTypeIdIfPrimitive;
|
||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
public class HookerDexMaker implements HookMaker {
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ public class HookerDexMaker implements HookMaker {
|
|||
HookWrapper.HookEntity hookEntity = null;
|
||||
//try load cache first
|
||||
try {
|
||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName);
|
||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
|
||||
if (loader != null) {
|
||||
hookEntity = loadHookerClass(loader, className);
|
||||
}
|
||||
|
|
@ -215,8 +215,8 @@ public class HookerDexMaker implements HookMaker {
|
|||
|
||||
ClassLoader loader;
|
||||
if (canCache) {
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true);
|
||||
File dexFile = new File(ConfigManager.getCachePath(dexName));
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
|
||||
File dexFile = new File(serviceClient.getCachePath(dexName));
|
||||
dexFile.setWritable(true, false);
|
||||
dexFile.setReadable(true, false);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.swift.sandhook.xposedcompat.methodgen;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.wrapper.HookWrapper;
|
||||
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.getObjTypeIdIfPrimitive;
|
||||
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
public class HookerDexMakerNew implements HookMaker {
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ public class HookerDexMakerNew implements HookMaker {
|
|||
HookWrapper.HookEntity hookEntity = null;
|
||||
//try load cache first
|
||||
try {
|
||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName);
|
||||
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
|
||||
if (loader != null) {
|
||||
hookEntity = loadHookerClass(loader, className);
|
||||
}
|
||||
|
|
@ -176,8 +176,8 @@ public class HookerDexMakerNew implements HookMaker {
|
|||
}
|
||||
// Create the dex file and load it.
|
||||
try {
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true);
|
||||
File dexFile = new File(ConfigManager.getCachePath(dexName));
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
|
||||
File dexFile = new File(serviceClient.getCachePath(dexName));
|
||||
dexFile.setWritable(true, false);
|
||||
dexFile.setReadable(true, false);
|
||||
} catch (IOException e) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import android.os.Build;
|
|||
import android.os.Process;
|
||||
import android.os.Trace;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.nativebridge.Yahfa;
|
||||
import io.github.lsposed.lspd.util.ClassLoaderUtils;
|
||||
import io.github.lsposed.lspd.util.FileUtils;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
package com.swift.sandhook.xposedcompat.utils;
|
||||
import io.github.lsposed.lspd.nativebridge.ConfigManager;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
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.TypeId;
|
||||
|
||||
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
|
||||
|
||||
public class DexMakerUtils {
|
||||
|
||||
public static boolean canCache = true;
|
||||
|
||||
static {
|
||||
File cacheDir = new File(ConfigManager.getCachePath(""));
|
||||
File cacheDir = new File(serviceClient.getCachePath(""));
|
||||
if(!cacheDir.canRead() || !cacheDir.canWrite()) {
|
||||
Utils.logW("Cache disabled");
|
||||
canCache = false;
|
||||
|
|
|
|||
|
|
@ -223,6 +223,10 @@ else
|
|||
fi
|
||||
fi
|
||||
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}"
|
||||
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}"
|
||||
|
|
@ -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}"
|
||||
|
||||
if [ $VARIANT == 17 ]; then # YAHFA
|
||||
echo "1" > /data/misc/$MISC_PATH/variant
|
||||
echo "1" > /data/adb/lspd/config/variant
|
||||
elif [ $VARIANT == 18 ]; then # SandHook
|
||||
echo "2" > /data/misc/$MISC_PATH/variant
|
||||
echo "2" > /data/adb/lspd/config/variant
|
||||
else
|
||||
abortC "${LANG_UTIL_ERR_VARIANT_UNSUPPORT} ${VARIANT}"
|
||||
fi
|
||||
|
|
@ -241,12 +245,6 @@ if [[ ! -e /data/misc/$MISC_PATH/disable_verbose_log ]]; then
|
|||
echo "1" > /data/misc/$MISC_PATH/disable_verbose_log
|
||||
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
|
||||
rm /data/misc/$MISC_PATH/cache/*
|
||||
|
|
|
|||
|
|
@ -27,7 +27,4 @@ if [[ -f "${MODDIR}/reboot_twice_flag" ]]; then
|
|||
reboot
|
||||
fi
|
||||
|
||||
MISC_PATH=$(cat /data/adb/lspd/misc_path)
|
||||
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
|
||||
/system/bin/app_process -Djava.class.path=/data/adb/lspd/framework/lspd.dex /system/bin --nice-name=lspd io.github.lsposed.lspd.core.Main
|
||||
|
|
|
|||
Loading…
Reference in New Issue