Commit 22c9d836 authored by topjohnwu's avatar topjohnwu

Merge branch 'master' into feature/redesign

parents fcedd06e 984997e7
...@@ -6,7 +6,7 @@ import java.io.File ...@@ -6,7 +6,7 @@ import java.io.File
object Const { object Const {
// Paths // Paths
const val MAGISK_PATH = "/sbin/.magisk/img" const val MAGISK_PATH = "/sbin/.magisk/modules"
var MAGISK_DISABLE_FILE = File("xxx") var MAGISK_DISABLE_FILE = File("xxx")
const val TMP_FOLDER_PATH = "/dev/tmp" const val TMP_FOLDER_PATH = "/dev/tmp"
const val MAGISK_LOG = "/cache/magisk.log" const val MAGISK_LOG = "/cache/magisk.log"
...@@ -23,8 +23,8 @@ object Const { ...@@ -23,8 +23,8 @@ object Const {
val USER_ID = Process.myUid() / 100000 val USER_ID = Process.myUid() / 100000
object Version { object Version {
const val MIN_VERSION = "v18.0" const val MIN_VERSION = "v19.0"
const val MIN_VERCODE = 18000 const val MIN_VERCODE = 19000
const val CONNECT_MODE = 20100 const val CONNECT_MODE = 20100
const val PROVIDER_CONNECT = 20102 const val PROVIDER_CONNECT = 20102
} }
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:clickable="false"
android:focusable="false"
android:onClick="@{() -> item.toggle()}"> android:onClick="@{() -> item.toggle()}">
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
...@@ -38,10 +41,11 @@ ...@@ -38,10 +41,11 @@
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/hide_process_icon" android:id="@+id/hide_process_icon"
android:focusable="true"
android:clickable="true"
style="@style/Widget.Icon" style="@style/Widget.Icon"
isChecked="@{item.isHidden}" isChecked="@{item.isHidden}"
android:background="@null"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
......
# v7.5.0 # v7.5.1
- Support new communication method (ContentProvider) - Fix toggling app components in MagiskHide screen
- Fix several issues with hidden stub APK - Update translations
- Support using BiometricPrompt (face unlock)
...@@ -89,8 +89,8 @@ EOF ...@@ -89,8 +89,8 @@ EOF
add_hosts_module() { add_hosts_module() {
# Do not touch existing hosts module # Do not touch existing hosts module
[ -d /sbin/.magisk/img/hosts ] && return [ -d /sbin/.magisk/modules/hosts ] && return
cd /sbin/.magisk/img cd /sbin/.magisk/modules
mkdir -p hosts/system/etc mkdir -p hosts/system/etc
cat << EOF > hosts/module.prop cat << EOF > hosts/module.prop
id=hosts id=hosts
...@@ -99,17 +99,10 @@ version=1.0 ...@@ -99,17 +99,10 @@ version=1.0
versionCode=1 versionCode=1
author=Magisk Manager author=Magisk Manager
description=Magisk Manager built-in systemless hosts module description=Magisk Manager built-in systemless hosts module
minMagisk=17000
EOF EOF
if [ -f .core/hosts ]; then cp -f /system/etc/hosts hosts/system/etc/hosts
# Migrate old hosts file to new module
mv -f .core/hosts hosts/system/etc/hosts
else
cp -f /system/etc/hosts hosts/system/etc/hosts
fi
magisk --clone-attr /system/etc/hosts hosts/system/etc/hosts magisk --clone-attr /system/etc/hosts hosts/system/etc/hosts
touch hosts/update touch hosts/update
touch hosts/auto_mount
cd / cd /
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<string name="settings">Configuració</string> <string name="settings">Configuració</string>
<string name="install">Instal·lar</string> <string name="install">Instal·lar</string>
<string name="unsupport_magisk_title">Versió de Magisk incompatible</string> <string name="unsupport_magisk_title">Versió de Magisk incompatible</string>
<string name="unsupport_magisk_msg">Aquesta versió de Magisk Manager no suporta versions de Magisk més petites que la %1$s.\n\nL\'App es comportarà com si Magisk no estigués instal·lat, si us plau actualitzi Magisk el més aviat possible.</string>
<!--Status Fragment--> <!--Status Fragment-->
<string name="magisk_version_error">Magisk no està instal·lat</string> <string name="magisk_version_error">Magisk no està instal·lat</string>
......
This diff is collapsed.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<string name="settings">Ustawienia</string> <string name="settings">Ustawienia</string>
<string name="install">Instaluj</string> <string name="install">Instaluj</string>
<string name="unsupport_magisk_title">Nieobsługiwana Wersja Magisk</string> <string name="unsupport_magisk_title">Nieobsługiwana Wersja Magisk</string>
<string name="unsupport_magisk_msg">Ta wersja Magisk Managera nie obsługuje wersji Magiska poniżej %1$s.\n\nZaktualizuj Magisk.</string>
<!--Status Fragment--> <!--Status Fragment-->
<string name="magisk_version_error">Magisk nie jest zainstalowany.</string> <string name="magisk_version_error">Magisk nie jest zainstalowany.</string>
...@@ -166,7 +167,10 @@ ...@@ -166,7 +167,10 @@
<string name="request_timeout_summary">%1$d sekund</string> <string name="request_timeout_summary">%1$d sekund</string>
<string name="settings_su_reauth_title">Ponowienie uwierzytelnienia po aktualizacji</string> <string name="settings_su_reauth_title">Ponowienie uwierzytelnienia po aktualizacji</string>
<string name="settings_su_reauth_summary">Ponowne uwierzytelnianie uprawnienia superużytkownika po aktualizacji aplikacji</string> <string name="settings_su_reauth_summary">Ponowne uwierzytelnianie uprawnienia superużytkownika po aktualizacji aplikacji</string>
<string name="settings_su_biometric_title">Uwierzytelnianie odciskiem palca</string>
<string name="settings_su_biometric_summary">Użyj odcisku palca aby przyznać uprawnienia superużytkownika</string>
<string name="no_biometric">Niewspierane urządzenie lub brak odcisku palca</string>
<string name="multiuser_mode">Tryb Multiusera</string> <string name="multiuser_mode">Tryb Multiusera</string>
<string name="settings_owner_only">Tylko Właściciel Urządzenia</string> <string name="settings_owner_only">Tylko Właściciel Urządzenia</string>
<string name="settings_owner_manage">Zarządzanie Właścicielami Urządzenia</string> <string name="settings_owner_manage">Zarządzanie Właścicielami Urządzenia</string>
......
...@@ -90,11 +90,10 @@ ...@@ -90,11 +90,10 @@
<string name="repo_install_title">Nainštalovať %1$s</string> <string name="repo_install_title">Nainštalovať %1$s</string>
<string name="repo_install_msg">Chcete teraz nainštalovať %1$s?</string> <string name="repo_install_msg">Chcete teraz nainštalovať %1$s?</string>
<string name="download">Stiahnuť</string> <string name="download">Stiahnuť</string>
<string name="reboot">Reštart</string> <string name="reboot">Reštartovať</string>
<string name="settings_reboot_toast">Pre aplikovanie nastavení je potrebný reštart</string> <string name="settings_reboot_toast">Pre aplikovanie nastavení je potrebný reštart</string>
<string name="release_notes">Poznámky k vydaniu</string> <string name="release_notes">Poznámky k vydaniu</string>
<string name="repo_cache_cleared">Cache repo odstránená</string> <string name="repo_cache_cleared">Cache repo odstránená</string>
<string name="dtbo_patched_title">DTBO bol zaplátaný!</string> <string name="dtbo_patched_title">DTBO bol zaplátaný!</string>
<string name="dtbo_patched_reboot">Magisk Manager zaplátal dtbo.img, prosím, reštartujte.</string> <string name="dtbo_patched_reboot">Magisk Manager zaplátal dtbo.img, prosím, reštartujte.</string>
<string name="flashing">Flashovanie</string> <string name="flashing">Flashovanie</string>
...@@ -115,6 +114,7 @@ ...@@ -115,6 +114,7 @@
<string name="env_fix_title">Vyžaduje sa ďalšie nastavenie</string> <string name="env_fix_title">Vyžaduje sa ďalšie nastavenie</string>
<string name="env_fix_msg">Vaše zariadenie si vyžaduje ďalšie nastavenie pre správne fungovanie Magisk. Stiahne sa inštalačný zip súbor Magisk, chcete pokračovať teraz?</string> <string name="env_fix_msg">Vaše zariadenie si vyžaduje ďalšie nastavenie pre správne fungovanie Magisk. Stiahne sa inštalačný zip súbor Magisk, chcete pokračovať teraz?</string>
<string name="setup_msg">Nastavenie je spustené…</string> <string name="setup_msg">Nastavenie je spustené…</string>
<string name="authenticate">Autentifikácia</string>
<!--Settings Activity --> <!--Settings Activity -->
<string name="settings_general_category">Všeobecné</string> <string name="settings_general_category">Všeobecné</string>
...@@ -166,6 +166,9 @@ ...@@ -166,6 +166,9 @@
<string name="request_timeout_summary">%1$d sekúnd</string> <string name="request_timeout_summary">%1$d sekúnd</string>
<string name="settings_su_reauth_title">Overenie autentifikácie po upgrade</string> <string name="settings_su_reauth_title">Overenie autentifikácie po upgrade</string>
<string name="settings_su_reauth_summary">Overí autentifikáciu oprávnení superuser po upgrade aplikácie</string> <string name="settings_su_reauth_summary">Overí autentifikáciu oprávnení superuser po upgrade aplikácie</string>
<string name="settings_su_biometric_title">Povoliť biometrickú autentifikáciu</string>
<string name="settings_su_biometric_summary">Použite biometrickú autentifikáciu pre povolenie žiadostí superuser</string>
<string name="no_biometric">Nepodporované zariadenia alebo biometria nie je povolená v nastaveniach</string>
<string name="multiuser_mode">Režim viacerých používateľov</string> <string name="multiuser_mode">Režim viacerých používateľov</string>
<string name="settings_owner_only">Iba majiteľ zariadenia</string> <string name="settings_owner_only">Iba majiteľ zariadenia</string>
......
...@@ -13,6 +13,7 @@ LIBNANOPB := $(EXT_PATH)/nanopb ...@@ -13,6 +13,7 @@ LIBNANOPB := $(EXT_PATH)/nanopb
LIBSYSTEMPROPERTIES := jni/systemproperties/include LIBSYSTEMPROPERTIES := jni/systemproperties/include
LIBUTILS := jni/utils/include LIBUTILS := jni/utils/include
LIBMINCRYPT := $(EXT_PATH)/mincrypt/include LIBMINCRYPT := $(EXT_PATH)/mincrypt/include
LIBXZ := $(EXT_PATH)/xz-embedded
######################## ########################
# Binaries # Binaries
...@@ -22,11 +23,9 @@ ifdef B_MAGISK ...@@ -22,11 +23,9 @@ ifdef B_MAGISK
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := magisk LOCAL_MODULE := magisk
LOCAL_SHARED_LIBRARIES := libsqlite
LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties libutils LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties libutils
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
jni/include \ jni/include \
$(EXT_PATH)/include \
$(LIBNANOPB) \ $(LIBNANOPB) \
$(LIBSYSTEMPROPERTIES) \ $(LIBSYSTEMPROPERTIES) \
$(LIBUTILS) $(LIBUTILS)
...@@ -98,9 +97,9 @@ ifdef BB_INIT ...@@ -98,9 +97,9 @@ ifdef BB_INIT
LOCAL_STATIC_LIBRARIES := libsepol libxz libutils LOCAL_STATIC_LIBRARIES := libsepol libxz libutils
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
jni/include \ jni/include \
$(EXT_PATH)/include \
out \ out \
out/$(TARGET_ARCH_ABI) \ out/$(TARGET_ARCH_ABI) \
$(LIBXZ) \
$(LIBSEPOL) \ $(LIBSEPOL) \
$(LIBUTILS) $(LIBUTILS)
......
...@@ -341,13 +341,10 @@ static bool magisk_env() { ...@@ -341,13 +341,10 @@ static bool magisk_env() {
// Remove stuffs // Remove stuffs
rm_rf("/cache/data_adb"); rm_rf("/cache/data_adb");
rm_rf("/data/adb/modules/.core");
unlink("/data/magisk.img"); unlink("/data/magisk.img");
unlink("/data/magisk_debug.log"); unlink("/data/magisk_debug.log");
// Backwards compatibility
symlink("./.magisk", "/sbin/.core");
symlink("./modules", MAGISKTMP "/img");
// Directories in tmpfs overlay // Directories in tmpfs overlay
xmkdir(MIRRDIR, 0); xmkdir(MIRRDIR, 0);
xmkdir(BLOCKDIR, 0); xmkdir(BLOCKDIR, 0);
...@@ -431,10 +428,6 @@ static void prepare_modules() { ...@@ -431,10 +428,6 @@ static void prepare_modules() {
rm_rf(MODULEUPGRADE); rm_rf(MODULEUPGRADE);
} }
bind_mount(MIRRDIR MODULEROOT, MODULEMNT, false); bind_mount(MIRRDIR MODULEROOT, MODULEMNT, false);
// Legacy support
xmkdir(LEGACYCORE, 0755);
symlink(SECURE_DIR "/post-fs-data.d", LEGACYCORE "/post-fs-data.d");
symlink(SECURE_DIR "/service.d", LEGACYCORE "/service.d");
restorecon(); restorecon();
chmod(SECURE_DIR, 0700); chmod(SECURE_DIR, 0700);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <dlfcn.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <magisk.h> #include <magisk.h>
...@@ -14,8 +15,93 @@ ...@@ -14,8 +15,93 @@
using namespace std; using namespace std;
typedef struct sqlite3 sqlite3;
static sqlite3 *mDB = nullptr; static sqlite3 *mDB = nullptr;
// SQLite APIs
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
static int (*sqlite3_open_v2)(
const char *filename,
sqlite3 **ppDb,
int flags,
const char *zVfs);
static const char *(*sqlite3_errmsg)(sqlite3 *db);
static int (*sqlite3_close)(sqlite3 *db);
static void (*sqlite3_free)(void *v);
static int (*sqlite3_exec)(
sqlite3 *db,
const char *sql,
int (*callback)(void*, int, char**, char**),
void *v,
char **errmsg);
// Internal Android linker APIs
static void (*android_get_LD_LIBRARY_PATH)(char *buffer, size_t buffer_size);
static void (*android_update_LD_LIBRARY_PATH)(const char *ld_library_path);
#define DLERR(ptr) if (!(ptr)) { \
LOGE("db: %s\n", dlerror()); \
return false; \
}
#define DLOAD(handle, arg) {\
auto f = dlsym(handle, #arg); \
DLERR(f) \
*(void **) &(arg) = f; \
}
#if defined(__aarch64__) || defined(__x86_64__)
constexpr char apex_path[] = ":/apex/com.android.runtime/lib64";
#else
constexpr char apex_path[] = ":/apex/com.android.runtime/lib";
#endif
static int dl_init = 0;
static bool dload_sqlite() {
if (dl_init)
return dl_init > 0;
dl_init = -1;
auto sqlite = dlopen("libsqlite.so", RTLD_LAZY);
if (!sqlite) {
// Should only happen on Android 10+
auto dl = dlopen("libdl_android.so", RTLD_LAZY);
DLERR(dl);
DLOAD(dl, android_get_LD_LIBRARY_PATH);
DLOAD(dl, android_update_LD_LIBRARY_PATH);
// Inject APEX into LD_LIBRARY_PATH
char ld_path[4096];
android_get_LD_LIBRARY_PATH(ld_path, sizeof(ld_path));
int len = strlen(ld_path);
strcpy(ld_path + len, apex_path);
android_update_LD_LIBRARY_PATH(ld_path);
sqlite = dlopen("libsqlite.so", RTLD_LAZY);
// Revert LD_LIBRARY_PATH just in case
ld_path[len] = '\0';
android_update_LD_LIBRARY_PATH(ld_path);
}
DLERR(sqlite);
DLOAD(sqlite, sqlite3_open_v2);
DLOAD(sqlite, sqlite3_errmsg);
DLOAD(sqlite, sqlite3_close);
DLOAD(sqlite, sqlite3_exec);
DLOAD(sqlite, sqlite3_free);
dl_init = 1;
return true;
}
int db_strings::getKeyIdx(string_view key) const { int db_strings::getKeyIdx(string_view key) const {
int idx = DB_STRING_NUM; int idx = DB_STRING_NUM;
for (int i = 0; i < DB_STRING_NUM; ++i) { for (int i = 0; i < DB_STRING_NUM; ++i) {
...@@ -50,6 +136,9 @@ static int ver_cb(void *ver, int, char **data, char **) { ...@@ -50,6 +136,9 @@ static int ver_cb(void *ver, int, char **data, char **) {
#define err_ret(e) if (e) return e; #define err_ret(e) if (e) return e;
static char *open_and_init_db(sqlite3 *&db) { static char *open_and_init_db(sqlite3 *&db) {
if (!dload_sqlite())
return strdup("Cannot load libsqlite.so");
int ret = sqlite3_open_v2(MAGISKDB, &db, int ret = sqlite3_open_v2(MAGISKDB, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr); SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr);
if (ret) if (ret)
...@@ -304,3 +393,12 @@ void exec_sql(int client) { ...@@ -304,3 +393,12 @@ void exec_sql(int client) {
write_int(client, 0); write_int(client, 0);
db_err_cmd(err, return; ); db_err_cmd(err, return; );
} }
bool db_err(char *e) {
if (e) {
LOGE("sqlite3_exec: %s\n", e);
sqlite3_free(e);
return true;
}
return false;
}
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
ifdef B_MAGISK
# libsqlite.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libsqlite
LOCAL_C_INCLUDES := $(EXT_PATH)/include
LOCAL_SRC_FILES := stubs/sqlite3_stub.c
include $(BUILD_SHARED_LIBRARY)
endif
# libselinux.so (stub)
#include $(CLEAR_VARS)
#LOCAL_MODULE:= libselinux
#LOCAL_C_INCLUDES := $(LIBSELINUX)
#LOCAL_SRC_FILES := stubs/selinux_stub.c
#include $(BUILD_SHARED_LIBRARY)
# libxz.a # libxz.a
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE:= libxz LOCAL_MODULE:= libxz
LOCAL_C_INCLUDES := $(EXT_PATH)/include LOCAL_C_INCLUDES := $(LIBXZ)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
xz-embedded/xz_crc32.c \ xz-embedded/xz_crc32.c \
xz-embedded/xz_dec_lzma2.c \ xz-embedded/xz_dec_lzma2.c \
...@@ -83,7 +65,7 @@ include $(BUILD_STATIC_LIBRARY) ...@@ -83,7 +65,7 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := liblzma LOCAL_MODULE := liblzma
LOCAL_C_INCLUDES += \ LOCAL_C_INCLUDES += \
$(EXT_PATH)/include/xz_config \ $(EXT_PATH)/xz_config \
$(EXT_PATH)/xz/src/common \ $(EXT_PATH)/xz/src/common \
$(EXT_PATH)/xz/src/liblzma/api \ $(EXT_PATH)/xz/src/liblzma/api \
$(EXT_PATH)/xz/src/liblzma/check \ $(EXT_PATH)/xz/src/liblzma/check \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once #pragma once
#include <sqlite3.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <map> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <functional> #include <functional>
#define db_err(e) db_err_cmd(e, )
#define db_err_cmd(e, cmd) if (e) { \
LOGE("sqlite3_exec: %s\n", e); \
sqlite3_free(e); \
cmd;\
}
template <class T, size_t num> template <class T, size_t num>
class db_data_base { class db_data_base {
public: public:
...@@ -160,4 +152,6 @@ bool validate_manager(std::string &pkg, int userid, struct stat *st); ...@@ -160,4 +152,6 @@ bool validate_manager(std::string &pkg, int userid, struct stat *st);
void exec_sql(int client); void exec_sql(int client);
char *db_exec(const char *sql); char *db_exec(const char *sql);
char *db_exec(const char *sql, const db_row_cb &fn); char *db_exec(const char *sql, const db_row_cb &fn);
bool db_err(char *e);
#define db_err_cmd(e, cmd) if (db_err(e)) { cmd; }
...@@ -19,12 +19,8 @@ ...@@ -19,12 +19,8 @@
#define MODULEUPGRADE SECURE_DIR "/modules_update" #define MODULEUPGRADE SECURE_DIR "/modules_update"
#define DATABIN SECURE_DIR "/magisk" #define DATABIN SECURE_DIR "/magisk"
#define MAGISKDB SECURE_DIR "/magisk.db" #define MAGISKDB SECURE_DIR "/magisk.db"
#define BOOTCOUNT SECURE_DIR "/.boot_count"
#define MANAGERAPK DATABIN "/magisk.apk" #define MANAGERAPK DATABIN "/magisk.apk"
// Legacy crap
#define LEGACYCORE MODULEROOT "/.core"
constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr }; constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr };
// Multi-call entrypoints // Multi-call entrypoints
......
...@@ -138,7 +138,7 @@ protected: ...@@ -138,7 +138,7 @@ protected:
void early_mount() override; void early_mount() override;
public: public:
RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) { RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {
persist_dir = "/dev/.magisk/mirror/persist/magisk"; persist_dir = "/dev/mnt/persist/magisk";
} }
void start() override { void start() override {
......
...@@ -94,7 +94,7 @@ static bool read_dt_fstab(cmdline *cmd, const char *name) { ...@@ -94,7 +94,7 @@ static bool read_dt_fstab(cmdline *cmd, const char *name) {
char path[128]; char path[128];
int fd; int fd;
sprintf(path, "%s/fstab/%s/dev", cmd->dt_dir, name); sprintf(path, "%s/fstab/%s/dev", cmd->dt_dir, name);
if ((fd = xopen(path, O_RDONLY | O_CLOEXEC)) >= 0) { if ((fd = open(path, O_RDONLY | O_CLOEXEC)) >= 0) {
read(fd, path, sizeof(path)); read(fd, path, sizeof(path));
close(fd); close(fd);
// Some custom treble use different names, so use what we read // Some custom treble use different names, so use what we read
...@@ -119,26 +119,6 @@ if (!is_lnk("/" #name) && read_dt_fstab(cmd, #name)) { \ ...@@ -119,26 +119,6 @@ if (!is_lnk("/" #name) && read_dt_fstab(cmd, #name)) { \
mount_list.emplace_back("/" #name); \ mount_list.emplace_back("/" #name); \
} }
void RootFSInit::early_mount() {
full_read("/init", self.buf, self.sz);
LOGD("Reverting /init\n");
root = xopen("/", O_RDONLY | O_CLOEXEC);
rename("/.backup/init", "/init");
// Mount sbin overlay for persist, but move it and add to cleanup list
mount_sbin();
xmount("/sbin", "/dev", nullptr, MS_MOVE, nullptr);
mount_list.emplace_back("/dev");
mount_list.emplace_back("/dev/.magisk/mirror/persist");
mount_list.emplace_back("/dev/.magisk/mirror/cache");
mount_root(system);
mount_root(vendor);
mount_root(product);
mount_root(odm);
}
static void switch_root(const string &path) { static void switch_root(const string &path) {
LOGD("Switch root to %s\n", path.data()); LOGD("Switch root to %s\n", path.data());
vector<string> mounts; vector<string> mounts;
...@@ -164,6 +144,45 @@ static void switch_root(const string &path) { ...@@ -164,6 +144,45 @@ static void switch_root(const string &path) {
chroot("."); chroot(".");
} }
static void mount_persist(const char *dev_base, const char *mnt_base) {
string mnt_point = mnt_base + "/persist"s;
strcpy(partname, "persist");
sprintf(block_dev, "%s/persist", dev_base);
if (setup_block(false) < 0) {
// Fallback to cache
strcpy(partname, "cache");
sprintf(block_dev, "%s/cache", dev_base);
if (setup_block(false) < 0) {
// Try NVIDIA's BS
strcpy(partname, "CAC");
if (setup_block(false) < 0)
return;
}
xsymlink("./cache", mnt_point.data());
mnt_point = mnt_base + "/cache"s;
}
xmkdir(mnt_point.data(), 0755);
xmount(block_dev, mnt_point.data(), "ext4", 0, nullptr);
}
void RootFSInit::early_mount() {
full_read("/init", self.buf, self.sz);
LOGD("Reverting /init\n");
root = xopen("/", O_RDONLY | O_CLOEXEC);
rename("/.backup/init", "/init");
mount_root(system);
mount_root(vendor);
mount_root(product);
mount_root(odm);
xmkdir("/dev/mnt", 0755);
mount_persist("/dev/block", "/dev/mnt");
mount_list.emplace_back("/dev/mnt/persist");
mount_list.emplace_back("/dev/mnt/cache");
}
void SARBase::backup_files() { void SARBase::backup_files() {
if (access("/overlay.d", F_OK) == 0) if (access("/overlay.d", F_OK) == 0)
cp_afc("/overlay.d", "/dev/overlay.d"); cp_afc("/overlay.d", "/dev/overlay.d");
...@@ -250,23 +269,5 @@ void mount_sbin() { ...@@ -250,23 +269,5 @@ void mount_sbin() {
xmkdir(MIRRDIR, 0); xmkdir(MIRRDIR, 0);
xmkdir(BLOCKDIR, 0); xmkdir(BLOCKDIR, 0);
// Mount persist partition mount_persist(BLOCKDIR, MIRRDIR);
strcpy(partname, "persist");
strcpy(block_dev, BLOCKDIR "/persist");
const char *mnt_point = MIRRDIR "/persist";
if (setup_block(false) < 0) {
// Fallback to cache
strcpy(partname, "cache");
strcpy(block_dev, BLOCKDIR "/cache");
if (setup_block(false) < 0) {
// Try NVIDIA's BS
strcpy(partname, "CAC");
if (setup_block(false) < 0)
return;
}
mnt_point = MIRRDIR "/cache";
xsymlink("./cache", MIRRDIR "/persist");
}
xmkdir(mnt_point, 0755);
xmount(block_dev, mnt_point, "ext4", 0, nullptr);
} }
...@@ -182,12 +182,6 @@ bool MagiskInit::patch_sepolicy(const char *file) { ...@@ -182,12 +182,6 @@ bool MagiskInit::patch_sepolicy(const char *file) {
return patch_init; return patch_init;
} }
constexpr const char wrapper[] =
"#!/system/bin/sh\n"
"export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH:/apex/com.android.runtime/" LIBNAME "\"\n"
"exec /sbin/magisk.bin \"$0\" \"$@\"\n"
;
static void sbin_overlay(const raw_data &self, const raw_data &config) { static void sbin_overlay(const raw_data &self, const raw_data &config) {
mount_sbin(); mount_sbin();
...@@ -199,17 +193,8 @@ static void sbin_overlay(const raw_data &self, const raw_data &config) { ...@@ -199,17 +193,8 @@ static void sbin_overlay(const raw_data &self, const raw_data &config) {
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755); fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
xwrite(fd, self.buf, self.sz); xwrite(fd, self.buf, self.sz);
close(fd); close(fd);
if (access("/system/apex", F_OK) == 0) { dump_magisk("/sbin/magisk", 0755);
LOGD("APEX detected, use wrapper\n"); patch_socket_name("/sbin/magisk");
dump_magisk("/sbin/magisk.bin", 0755);
patch_socket_name("/sbin/magisk.bin");
fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
xwrite(fd, wrapper, sizeof(wrapper) - 1);
close(fd);
} else {
dump_magisk("/sbin/magisk", 0755);
patch_socket_name("/sbin/magisk");
}
// Create applet symlinks // Create applet symlinks
char path[64]; char path[64];
...@@ -221,46 +206,35 @@ static void sbin_overlay(const raw_data &self, const raw_data &config) { ...@@ -221,46 +206,35 @@ static void sbin_overlay(const raw_data &self, const raw_data &config) {
xsymlink("./magiskinit", "/sbin/supolicy"); xsymlink("./magiskinit", "/sbin/supolicy");
} }
static void recreate_sbin(const char *mirror) { static void recreate_sbin(const char *mirror, bool use_bind_mount) {
int src = xopen(mirror, O_RDONLY | O_CLOEXEC); auto dp = xopen_dir(mirror);
int dest = xopen("/sbin", O_RDONLY | O_CLOEXEC); int src = dirfd(dp.get());
DIR *fp = fdopendir(src); char buf[4096];
char buf[256]; for (dirent *entry; (entry = xreaddir(dp.get()));) {
bool use_bind_mount = true;
for (dirent *entry; (entry = xreaddir(fp));) {
if (entry->d_name == "."sv || entry->d_name == ".."sv) if (entry->d_name == "."sv || entry->d_name == ".."sv)
continue; continue;
string sbin_path = "/sbin/"s + entry->d_name;
struct stat st; struct stat st;
fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW); fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW);
if (S_ISLNK(st.st_mode)) { if (S_ISLNK(st.st_mode)) {
xreadlinkat(src, entry->d_name, buf, sizeof(buf)); xreadlinkat(src, entry->d_name, buf, sizeof(buf));
xsymlinkat(buf, dest, entry->d_name); xsymlink(buf, sbin_path.data());
} else { } else {
char sbin_path[256];
sprintf(buf, "%s/%s", mirror, entry->d_name); sprintf(buf, "%s/%s", mirror, entry->d_name);
sprintf(sbin_path, "/sbin/%s", entry->d_name);
if (use_bind_mount) { if (use_bind_mount) {
auto mode = st.st_mode & 0777;
// Create dummy // Create dummy
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
xmkdir(sbin_path, st.st_mode & 0777); xmkdir(sbin_path.data(), mode);
else else
close(xopen(sbin_path, O_CREAT | O_WRONLY | O_CLOEXEC, st.st_mode & 0777)); close(xopen(sbin_path.data(), O_CREAT | O_WRONLY | O_CLOEXEC, mode));
if (xmount(buf, sbin_path, nullptr, MS_BIND, nullptr)) {
// Bind mount failed, fallback to symlink
remove(sbin_path);
use_bind_mount = false;
} else {
continue;
}
}
xsymlink(buf, sbin_path); xmount(buf, sbin_path.data(), nullptr, MS_BIND, nullptr);
} else {
xsymlink(buf, sbin_path.data());
}
} }
} }
close(src);
close(dest);
} }
#define ROOTMIR MIRRDIR "/system_root" #define ROOTMIR MIRRDIR "/system_root"
...@@ -304,7 +278,7 @@ void SARBase::patch_rootdir() { ...@@ -304,7 +278,7 @@ void SARBase::patch_rootdir() {
xmount(ROOTBLK, ROOTMIR, "erofs", MS_RDONLY, nullptr); xmount(ROOTBLK, ROOTMIR, "erofs", MS_RDONLY, nullptr);
// Recreate original sbin structure // Recreate original sbin structure
recreate_sbin(ROOTMIR "/sbin"); recreate_sbin(ROOTMIR "/sbin", true);
// Patch init // Patch init
raw_data init; raw_data init;
...@@ -491,7 +465,7 @@ int magisk_proxy_main(int argc, char *argv[]) { ...@@ -491,7 +465,7 @@ int magisk_proxy_main(int argc, char *argv[]) {
sbin_overlay(self, config); sbin_overlay(self, config);
// Create symlinks pointing back to /root // Create symlinks pointing back to /root
recreate_sbin("/root"); recreate_sbin("/root", false);
setenv("REMOUNT_ROOT", "1", 1); setenv("REMOUNT_ROOT", "1", 1);
execv("/sbin/magisk", argv); execv("/sbin/magisk", argv);
......
...@@ -73,6 +73,7 @@ private: ...@@ -73,6 +73,7 @@ private:
uint8_t outbuf[CHUNK]; uint8_t outbuf[CHUNK];
int write(const void *buf, size_t len, int flush) { int write(const void *buf, size_t len, int flush) {
int ret = 0;
strm.next_in = (Bytef *) buf; strm.next_in = (Bytef *) buf;
strm.avail_in = len; strm.avail_in = len;
do { do {
...@@ -91,9 +92,9 @@ private: ...@@ -91,9 +92,9 @@ private:
LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code); LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code);
return -1; return -1;
} }
bwrite(outbuf, sizeof(outbuf) - strm.avail_out); ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
} while (strm.avail_out == 0); } while (strm.avail_out == 0);
return len; return ret;
} }
}; };
...@@ -147,6 +148,7 @@ private: ...@@ -147,6 +148,7 @@ private:
char outbuf[CHUNK]; char outbuf[CHUNK];
int write(const void *buf, size_t len, int flush) { int write(const void *buf, size_t len, int flush) {
int ret = 0;
strm.next_in = (char *) buf; strm.next_in = (char *) buf;
strm.avail_in = len; strm.avail_in = len;
do { do {
...@@ -165,9 +167,9 @@ private: ...@@ -165,9 +167,9 @@ private:
LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code); LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code);
return -1; return -1;
} }
bwrite(outbuf, sizeof(outbuf) - strm.avail_out); ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
} while (strm.avail_out == 0); } while (strm.avail_out == 0);
return len; return ret;
} }
}; };
...@@ -229,6 +231,7 @@ private: ...@@ -229,6 +231,7 @@ private:
uint8_t outbuf[CHUNK]; uint8_t outbuf[CHUNK];
int write(const void *buf, size_t len, lzma_action flush) { int write(const void *buf, size_t len, lzma_action flush) {
int ret = 0;
strm.next_in = (uint8_t *) buf; strm.next_in = (uint8_t *) buf;
strm.avail_in = len; strm.avail_in = len;
do { do {
...@@ -239,9 +242,9 @@ private: ...@@ -239,9 +242,9 @@ private:
LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code); LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code);
return -1; return -1;
} }
bwrite(outbuf, sizeof(outbuf) - strm.avail_out); ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
} while (strm.avail_out == 0); } while (strm.avail_out == 0);
return len; return ret;
} }
}; };
...@@ -272,7 +275,7 @@ public: ...@@ -272,7 +275,7 @@ public:
} }
int write(const void *buf, size_t len) override { int write(const void *buf, size_t len) override {
auto ret = len; int ret = 0;
auto inbuf = reinterpret_cast<const uint8_t *>(buf); auto inbuf = reinterpret_cast<const uint8_t *>(buf);
if (!outbuf) if (!outbuf)
read_header(inbuf, len); read_header(inbuf, len);
...@@ -288,7 +291,7 @@ public: ...@@ -288,7 +291,7 @@ public:
} }
len -= read; len -= read;
inbuf += read; inbuf += read;
bwrite(outbuf, write); ret += bwrite(outbuf, write);
} while (len != 0 || write != 0); } while (len != 0 || write != 0);
return ret; return ret;
} }
...@@ -323,9 +326,9 @@ public: ...@@ -323,9 +326,9 @@ public:
} }
int write(const void *buf, size_t len) override { int write(const void *buf, size_t len) override {
auto ret = len; int ret = 0;
if (!outbuf) if (!outbuf)
write_header(); ret += write_header();
if (len == 0) if (len == 0)
return 0; return 0;
auto inbuf = reinterpret_cast<const uint8_t *>(buf); auto inbuf = reinterpret_cast<const uint8_t *>(buf);
...@@ -339,7 +342,7 @@ public: ...@@ -339,7 +342,7 @@ public:
} }
len -= read; len -= read;
inbuf += read; inbuf += read;
bwrite(outbuf, write); ret += bwrite(outbuf, write);
} while (len != 0); } while (len != 0);
return ret; return ret;
} }
...@@ -358,7 +361,7 @@ private: ...@@ -358,7 +361,7 @@ private:
static constexpr size_t BLOCK_SZ = 1 << 22; static constexpr size_t BLOCK_SZ = 1 << 22;
void write_header() { int write_header() {
LZ4F_preferences_t prefs { LZ4F_preferences_t prefs {
.autoFlush = 1, .autoFlush = 1,
.compressionLevel = 9, .compressionLevel = 9,
...@@ -372,7 +375,7 @@ private: ...@@ -372,7 +375,7 @@ private:
outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs); outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs);
outbuf = new uint8_t[outCapacity]; outbuf = new uint8_t[outCapacity];
size_t write = LZ4F_compressBegin(ctx, outbuf, outCapacity, &prefs); size_t write = LZ4F_compressBegin(ctx, outbuf, outCapacity, &prefs);
bwrite(outbuf, write); return bwrite(outbuf, write);
} }
}; };
...@@ -380,15 +383,15 @@ class LZ4_decoder : public cpr_stream { ...@@ -380,15 +383,15 @@ class LZ4_decoder : public cpr_stream {
public: public:
explicit LZ4_decoder(stream_ptr &&base) explicit LZ4_decoder(stream_ptr &&base)
: cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]), : cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]),
buffer(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {} buf(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {}
~LZ4_decoder() override { ~LZ4_decoder() override {
delete[] out_buf; delete[] out_buf;
delete[] buffer; delete[] buf;
} }
int write(const void *in, size_t size) override { int write(const void *in, size_t size) override {
auto ret = size; int ret = 0;
auto inbuf = static_cast<const char *>(in); auto inbuf = static_cast<const char *>(in);
if (!init) { if (!init) {
// Skip magic // Skip magic
...@@ -396,42 +399,48 @@ public: ...@@ -396,42 +399,48 @@ public:
size -= 4; size -= 4;
init = true; init = true;
} }
int write; for (int consumed; size != 0;) {
size_t consumed;
do {
if (block_sz == 0) { if (block_sz == 0) {
block_sz = *((unsigned *) inbuf); if (buf_off + size >= sizeof(block_sz)) {
inbuf += sizeof(unsigned); consumed = sizeof(block_sz) - buf_off;
size -= sizeof(unsigned); memcpy(buf + buf_off, inbuf, consumed);
memcpy(&block_sz, buf, sizeof(block_sz));
buf_off = 0;
} else {
consumed = size;
memcpy(buf + buf_off, inbuf, size);
}
inbuf += consumed;
size -= consumed;
} else if (buf_off + size >= block_sz) { } else if (buf_off + size >= block_sz) {
consumed = block_sz - buf_off; consumed = block_sz - buf_off;
memcpy(buffer + buf_off, inbuf, consumed); memcpy(buf + buf_off, inbuf, consumed);
inbuf += consumed; inbuf += consumed;
size -= consumed; size -= consumed;
write = LZ4_decompress_safe(buffer, out_buf, block_sz, LZ4_UNCOMPRESSED); int write = LZ4_decompress_safe(buf, out_buf, block_sz, LZ4_UNCOMPRESSED);
if (write < 0) { if (write < 0) {
LOGW("LZ4HC decompression failure (%d)\n", write); LOGW("LZ4HC decompression failure (%d)\n", write);
return -1; return -1;
} }
bwrite(out_buf, write); ret += bwrite(out_buf, write);
// Reset // Reset
buf_off = 0; buf_off = 0;
block_sz = 0; block_sz = 0;
} else { } else {
// Copy to internal buffer // Copy to internal buffer
memcpy(buffer + buf_off, inbuf, size); memcpy(buf + buf_off, inbuf, size);
buf_off += size; buf_off += size;
size = 0; break;
} }
} while (size != 0); }
return ret; return ret;
} }
private: private:
char *out_buf; char *out_buf;
char *buffer; char *buf;
bool init; bool init;
unsigned block_sz; unsigned block_sz;
int buf_off; int buf_off;
...@@ -440,12 +449,13 @@ private: ...@@ -440,12 +449,13 @@ private:
class LZ4_encoder : public cpr_stream { class LZ4_encoder : public cpr_stream {
public: public:
explicit LZ4_encoder(stream_ptr &&base) explicit LZ4_encoder(stream_ptr &&base)
: cpr_stream(std::move(base)), outbuf(new char[LZ4_COMPRESSED]), buf(new char[LZ4_UNCOMPRESSED]), : cpr_stream(std::move(base)), outbuf(new char[LZ4_COMPRESSED]),
init(false), buf_off(0), in_total(0) {} buf(new char[LZ4_UNCOMPRESSED]), init(false), buf_off(0), in_total(0) {}
int write(const void *in, size_t size) override { int write(const void *in, size_t size) override {
int ret = 0;
if (!init) { if (!init) {
bwrite("\x02\x21\x4c\x18", 4); ret += bwrite("\x02\x21\x4c\x18", 4);
init = true; init = true;
} }
if (size == 0) if (size == 0)
...@@ -453,21 +463,18 @@ public: ...@@ -453,21 +463,18 @@ public:
in_total += size; in_total += size;
const char *inbuf = (const char *) in; const char *inbuf = (const char *) in;
size_t consumed; size_t consumed;
int write;
do { do {
if (buf_off + size >= LZ4_UNCOMPRESSED) { if (buf_off + size >= LZ4_UNCOMPRESSED) {
consumed = LZ4_UNCOMPRESSED - buf_off; consumed = LZ4_UNCOMPRESSED - buf_off;
memcpy(buf + buf_off, inbuf, consumed); memcpy(buf + buf_off, inbuf, consumed);
inbuf += consumed; inbuf += consumed;
size -= consumed; size -= consumed;
buf_off = LZ4_UNCOMPRESSED;
write = LZ4_compress_HC(buf, outbuf, LZ4_UNCOMPRESSED, LZ4_COMPRESSED, 9); if (int written = write_block(); written < 0)
if (write == 0) { return -1;
LOGW("LZ4HC compression failure\n"); else
return false; ret += written;
}
bwrite(&write, sizeof(write));
bwrite(outbuf, write);
// Reset buffer // Reset buffer
buf_off = 0; buf_off = 0;
...@@ -478,15 +485,12 @@ public: ...@@ -478,15 +485,12 @@ public:
size = 0; size = 0;
} }
} while (size != 0); } while (size != 0);
return true; return ret;
} }
~LZ4_encoder() override { ~LZ4_encoder() override {
if (buf_off) { if (buf_off)
int write = LZ4_compress_HC(buf, outbuf, buf_off, LZ4_COMPRESSED, 9); write_block();
bwrite(&write, sizeof(write));
bwrite(outbuf, write);
}
bwrite(&in_total, sizeof(in_total)); bwrite(&in_total, sizeof(in_total));
delete[] outbuf; delete[] outbuf;
delete[] buf; delete[] buf;
...@@ -498,6 +502,17 @@ private: ...@@ -498,6 +502,17 @@ private:
bool init; bool init;
int buf_off; int buf_off;
unsigned in_total; unsigned in_total;
int write_block() {
int written = LZ4_compress_HC(buf, outbuf, buf_off, LZ4_COMPRESSED, 9);
if (written == 0) {
LOGW("LZ4HC compression failure\n");
return -1;
}
bwrite(&written, sizeof(written));
bwrite(outbuf, written);
return written + sizeof(written);
}
}; };
stream_ptr get_encoder(format_t type, stream_ptr &&base) { stream_ptr get_encoder(format_t type, stream_ptr &&base) {
......
...@@ -96,17 +96,7 @@ else ...@@ -96,17 +96,7 @@ else
fi fi
# Magisk stuffs # Magisk stuffs
if [ -e /apex ]; then ./magiskinit -x magisk /sbin/magisk
./magiskinit -x magisk /sbin/magisk.bin
[ -e /system/lib64 ] && LIB=lib64 || LIB=lib
cat <<EOF > /sbin/magisk
#!/system/bin/sh
export LD_LIBRARY_PATH="\$LD_LIBRARY_PATH:/apex/com.android.runtime/$LIB"
exec /sbin/magisk.bin "\$0" "\$@"
EOF
else
./magiskinit -x magisk /sbin/magisk
fi
chmod 755 /sbin/magisk chmod 755 /sbin/magisk
ln -s ./magisk /sbin/su ln -s ./magisk /sbin/su
ln -s ./magisk /sbin/resetprop ln -s ./magisk /sbin/resetprop
......
...@@ -11,8 +11,6 @@ import static android.os.Build.VERSION.SDK_INT; ...@@ -11,8 +11,6 @@ import static android.os.Build.VERSION.SDK_INT;
public class DynAPK { public class DynAPK {
private static final int STUB_VERSION = 6;
// Indices of the object array // Indices of the object array
private static final int STUB_VERSION_ENTRY = 0; private static final int STUB_VERSION_ENTRY = 0;
private static final int CLASS_COMPONENT_MAP = 1; private static final int CLASS_COMPONENT_MAP = 1;
...@@ -64,7 +62,7 @@ public class DynAPK { ...@@ -64,7 +62,7 @@ public class DynAPK {
} }
public static class Data { public static class Data {
public int version = STUB_VERSION; public int version;
public Map<String, String> classToComponent; public Map<String, String> classToComponent;
} }
} }
...@@ -6,6 +6,8 @@ import java.util.Map; ...@@ -6,6 +6,8 @@ import java.util.Map;
import static com.topjohnwu.magisk.DynAPK.Data; import static com.topjohnwu.magisk.DynAPK.Data;
public class Mapping { public class Mapping {
private static final int STUB_VERSION = 7;
private static Map<String, String> map = new HashMap<>(); private static Map<String, String> map = new HashMap<>();
private static Map<String, String> inverseMap; private static Map<String, String> inverseMap;
...@@ -29,6 +31,7 @@ public class Mapping { ...@@ -29,6 +31,7 @@ public class Mapping {
public static Data data() { public static Data data() {
Data data = new Data(); Data data = new Data();
data.version = STUB_VERSION;
data.classToComponent = inverseMap; data.classToComponent = inverseMap;
return data; return data;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment