#include #include #include #include #include #include // Tracking Evolution-X's PixelPropsUtils #define UPSTREAM_URL "https://raw.githubusercontent.com/Evolution-X/frameworks_base/tiramisu/core/java/com/android/internal/util/evolution/PixelPropsUtils.java" // Use Pixel 6 Pro's fingerprint #define DEVICE_CODENAME "raven" #define DEVICE_VENDOR "google" #define STD_STRING_CONTAINS(str, search) (str.find(search) != std::string::npos) typedef struct result { bool vaild = false; std::string data = ""; } result_t; struct build_data { std::string vendor; std::string codename; int android_version; std::string buildid; std::string vendordata; }; static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { static_cast(userp)->append(static_cast(contents), size * nmemb); return size * nmemb; } static std::vector splitNewLines (const std::string& buffer) { auto result = std::vector{}; auto ss = std::stringstream{buffer}; for (std::string line; std::getline(ss, line, '\n');) result.push_back(line); return result; } static result_t *checkIfVaild(const std::string& line) { auto res = new result_t; // Is it related to ? if (!STD_STRING_CONTAINS(line, DEVICE_CODENAME)) return res; // Remove non-fingerprint stuff. // It should be //.. format if (!STD_STRING_CONTAINS(line, DEVICE_VENDOR)) return res; res->vaild = true; res->data = line; return res; } static result_t *parseJavaFile(const std::string& buffer) { auto kLines = splitNewLines(buffer); for (const auto line : kLines) { const auto res = checkIfVaild(line); if (res->vaild) { std::string data = res->data; res->data = data.substr(data.find(DEVICE_VENDOR)); data = res->data; res->data = data.substr(0, data.find_last_of('"')); return res; } else delete res; } // We failed to find the line. return nothing. return new result_t; } static std::string dirname(const std::string& arg) { auto idx = arg.find_last_of("/\\"); return arg.substr(0, idx); } static std::string fromBuildDataToFP(struct build_data *data) { const char *fmt = "%s/%s/%s:%d/%s/%s:user/release-keys"; int size = std::snprintf(nullptr, 0, fmt, data->vendor.c_str(), data->codename.c_str(), data->codename.c_str(), data->android_version, data->buildid.c_str(), data->vendordata.c_str()); std::vector buf(size + 1); std::snprintf(&buf[0], buf.size(), fmt, data->vendor.c_str(), data->codename.c_str(), data->codename.c_str(), data->android_version, data->buildid.c_str(), data->vendordata.c_str()); return std::string(buf.begin(), buf.end()); } static std::string fromBuildDataToDesc(struct build_data *data) { const char *fmt = "%s-user %d %s %s release-keys"; int size = std::snprintf(nullptr, 0, fmt, data->codename.c_str(), data->android_version, data->buildid.c_str(), data->vendordata.c_str()); std::vector buf(size + 1); std::snprintf(&buf[0], buf.size(), fmt, data->codename.c_str(), data->android_version, data->buildid.c_str(), data->vendordata.c_str()); return std::string(buf.begin(), buf.end()); } static struct build_data *serialize(const std::string& fpdata) { auto split = std::vector{}; auto ss = std::stringstream{fpdata}; auto data = new struct build_data; for (std::string line; std::getline(ss, line, '/');) split.push_back(line); // Fingerprint: "//://:user/release-keys" data->vendor = split[0]; std::string mixed = split[2]; int idx = mixed.find(':'); data->codename = mixed.substr(0, idx); data->android_version = stoi(mixed.substr(idx + 1)); data->buildid = split[3]; mixed = split[4]; idx = mixed.find(':'); data->vendordata = mixed.substr(0, idx); return data; } static void apply(const std::string& path, struct build_data *data) { std::remove(path.c_str()); std::ofstream file(path); if (file.is_open()) { std::string str; file << "# Autogenerated by " << __FILE__ << std::endl; file << "PRODUCT_GMS_CLIENTID_BASE := android-google" << std::endl; file << std::endl; str = fromBuildDataToFP(data); str.resize(str.find('\0')); file << "BUILD_FINGERPRINT := \"" << str << "\"" << std::endl; file << std::endl; file << "PRODUCT_BUILD_PROP_OVERRIDES += \\" << std::endl; str = fromBuildDataToDesc(data); str.resize(str.find('\0')); file << "\tPRIVATE_BUILD_DESC=\"" << str << "\"" << std::endl; file.close(); } } int main(int argc, const char **argv) { CURL *curl; CURLcode res; std::string readBuffer = ""; std::string execDir = dirname(argv[0]); curl = curl_easy_init(); if (curl != nullptr) { curl_easy_setopt(curl, CURLOPT_URL, UPSTREAM_URL); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res) return res; } auto parseRes = parseJavaFile(readBuffer); if (!parseRes->vaild) return 1; auto build = serialize(parseRes->data); delete parseRes; apply(execDir + "/../fingerprint.mk", build); return 0; }