[WIP] init: initial implementation of "quirks" support

This commit is contained in:
Peter Cai 2021-10-15 18:38:57 -04:00
parent 3e3c06374d
commit 37f6b0069d
6 changed files with 168 additions and 6 deletions

View file

@ -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"],

View file

@ -4,6 +4,8 @@
#include <string>
#include <iostream>
#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;
}

View file

@ -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

77
init/quirks.cpp Normal file
View file

@ -0,0 +1,77 @@
#define LOG_TAG "init_gsi_quirks"
#include <utils/Log.h>
#include "quirks.h"
#include <vector>
#include <sys/mount.h>
// Default destructor for DeviceQuirk
DeviceQuirk::~DeviceQuirk() {
}
static std::vector<DeviceQuirk*>* quirks = nullptr;
void Quirks::Add(DeviceQuirk* quirk) {
if (quirks == nullptr) {
quirks = new std::vector<DeviceQuirk*>();
}
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());
}

32
init/quirks.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include <filesystem>
#include <string>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
template<typename... Args>
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);
}

View file

@ -0,0 +1,38 @@
#include "../../quirks.h"
#include <filesystem>
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();