diff --git a/init/Android.bp b/init/Android.bp index 1675a01..ff4b21b 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -1,10 +1,19 @@ cc_binary { name: "init_gsi", system_ext_specific: true, - srcs: ["init_gsi.cpp"], - shared_libs: ["libbase", "libdl", "libutils"], - static_libs: ["libresetprop"], + srcs: [ + "init_gsi.cpp", + "quirks.cpp", + + // SoC-specific quirks + "quirks/soc/mtk_ril.cpp", + ], + shared_libs: ["libbase", "libdl", "liblog", "libutils"], + static_libs: ["libresetprop", "libc++fs"], init_rc: ["init_gsi.rc"], + cflags: [ + "-std=gnu++17", + ], target: { android: { ldflags: ["-Wl,--rpath,/system/${LIB}/bootstrap"], diff --git a/init/init_gsi.cpp b/init/init_gsi.cpp index 677975f..5c8ac91 100644 --- a/init/init_gsi.cpp +++ b/init/init_gsi.cpp @@ -4,6 +4,8 @@ #include #include +#include "quirks.h" + using namespace android; using namespace std; @@ -31,7 +33,7 @@ std::string RO_PROP_SOURCES[] = { "", "product", "odm", "vendor", "system_ext", "system", "bootimage", }; -int main() { +void handle_device_model_props() { string device = base::GetProperty("ro.product.vendor.device", ""); string model = base::GetProperty("ro.product.vendor.model", ""); string name = base::GetProperty("ro.product.vendor.name", ""); @@ -48,6 +50,10 @@ int main() { } override_ro_prop("ro", "", "build.stock_fingerprint", fingerprint); - +} + +int main() { + handle_device_model_props(); + Quirks::Run(); return 0; } diff --git a/init/init_gsi.rc b/init/init_gsi.rc index 9dcbb56..84829c8 100644 --- a/init/init_gsi.rc +++ b/init/init_gsi.rc @@ -1,2 +1,2 @@ on post-fs - exec -- /system_ext/bin/init_gsi + exec u:r:init_gsi:s0 root -- /system_ext/bin/init_gsi diff --git a/init/quirks.cpp b/init/quirks.cpp new file mode 100644 index 0000000..a243189 --- /dev/null +++ b/init/quirks.cpp @@ -0,0 +1,77 @@ +#define LOG_TAG "init_gsi_quirks" +#include + +#include "quirks.h" + +#include + +#include + +// Default destructor for DeviceQuirk +DeviceQuirk::~DeviceQuirk() { + +} + +static std::vector* quirks = nullptr; + +void Quirks::Add(DeviceQuirk* quirk) { + if (quirks == nullptr) { + quirks = new std::vector(); + } + quirks->push_back(quirk); +} + +void Quirks::Run() { + if (quirks == nullptr) return; + + for (DeviceQuirk* quirk : *quirks) { + if (quirk->ShouldRun()) { + quirk->Run(); + } + } +} + +// Utility functions for use with quirks +#define QUIRKS_TMP_BASE_PATH "/mnt/quirks" +#define QUIRKS_TMP_FILES_PATH QUIRKS_TMP_BASE_PATH "/files" + +void EnsureDirectory(filesystem::path p) { + if (!filesystem::is_directory(p)) { + filesystem::create_directories(p); + } +} + +void EnsureTmpMount() { + if (filesystem::is_directory(QUIRKS_TMP_BASE_PATH)) return; + + EnsureDirectory(QUIRKS_TMP_BASE_PATH); + int err = mount("tmpfs", QUIRKS_TMP_BASE_PATH, "tmpfs", 0, "mode=755,gid=0"); + + if (err < 0) { + ALOGE("mount tmpfs on %s err = %d\n", QUIRKS_TMP_BASE_PATH, errno); + } +} + +void Quirks::OverrideFileReplaceSubstr(filesystem::path p, string pattern, string replacement) { + if (!filesystem::is_regular_file(p)) return; + + EnsureTmpMount(); + EnsureDirectory(QUIRKS_TMP_FILES_PATH); + + filesystem::path tmp_path = QUIRKS_TMP_FILES_PATH + p.string(); + EnsureDirectory(tmp_path.parent_path()); + + // TODO: Actually implement pattern replacement + filesystem::copy_file(p, tmp_path); + + int err = mount(tmp_path.c_str(), p.c_str(), nullptr, MS_BIND, nullptr); + + if (err < 0) { + ALOGE("bind mount %s on %s err = %d\n", tmp_path.c_str(), p.c_str(), errno); + } + + // Call restorecon via execl, because for some reason + // libselinux functions will segfault in our case + // (probably related to other magic present in our process) + fork_execl("/system/bin/restorecon", "restorecon", p.c_str()); +} diff --git a/init/quirks.h b/init/quirks.h new file mode 100644 index 0000000..a9d87bd --- /dev/null +++ b/init/quirks.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include + +#include +#include + +using namespace std; + +template +void fork_execl(Args... args) { + int pid, status; + if ((pid = fork()) == 0) { + execl(args..., nullptr); + } else { + waitpid(pid, &status, 0); + } +} + +class DeviceQuirk { +public: + virtual bool ShouldRun(); + virtual void Run(); + virtual ~DeviceQuirk(); +}; + +namespace Quirks { + void Add(DeviceQuirk* quirk); + void Run(); + + void OverrideFileReplaceSubstr(filesystem::path p, string pattern, string replacement); +} diff --git a/init/quirks/soc/mtk_ril.cpp b/init/quirks/soc/mtk_ril.cpp new file mode 100644 index 0000000..912d176 --- /dev/null +++ b/init/quirks/soc/mtk_ril.cpp @@ -0,0 +1,38 @@ +#include "../../quirks.h" + +#include + +using namespace std; + +const string PATHS[] = { + "/vendor/lib/libmtk-ril.so", + "/vendor/lib/mtk-ril.so", + "/vendor/lib64/libmtk-ril.so", + "/vendor/lib64/mtk-ril.so" +}; + +class MtkRilQuirk : DeviceQuirk { +public: + MtkRilQuirk() { + Quirks::Add(this); + } + + bool ShouldRun() { + for (auto& p : PATHS) { + if (filesystem::exists(p)) { + return true; + } + } + return false; + } + + void Run() { + for (auto& p : PATHS) { + if (filesystem::exists(p)) { + Quirks::OverrideFileReplaceSubstr(p, "AT+EAIC=2", "AT+EAIC=3"); + } + } + } +}; + +static MtkRilQuirk* _ignored = new MtkRilQuirk();