in source/model-generator/ContentProviderGenerator.cpp [61:115]
std::vector<Model> ContentProviderGenerator::emit_method_models(
const Methods& methods) {
std::unordered_set<std::string> manifest_providers = {};
try {
auto android_resources = create_resource_reader(options_.apk_directory());
const auto manifest_class_info =
android_resources->get_manifest_class_info();
for (const auto& tag_info : manifest_class_info.component_tags) {
if (tag_info.tag == ComponentTag::Provider) {
auto* dex_class = redex::get_class(tag_info.classname);
if (dex_class) {
std::unordered_set<std::string> parent_classes =
generator::get_custom_parents_from_class(dex_class);
for (const auto& parent_class : parent_classes) {
manifest_providers.emplace(
generator::get_outer_class(parent_class));
}
}
manifest_providers.emplace(
generator::get_outer_class(tag_info.classname));
}
}
} catch (const std::exception& e) {
// Redex may assert, or throw `std::runtime_error` if the file is missing.
ERROR(2, "Manifest could not be parsed: {}", e.what());
return {};
}
std::vector<std::unique_ptr<re2::RE2>> provider_regexes;
for (const auto& regex_string : provider_regex_strings) {
provider_regexes.push_back(std::make_unique<re2::RE2>(regex_string));
}
std::mutex mutex;
std::vector<Model> models;
auto queue = sparta::work_queue<const Method*>([&](const Method* method) {
const auto& signature = method->signature();
const auto outer_class = generator::get_outer_class(signature);
if (manifest_providers.count(outer_class)) {
for (const auto& regex : provider_regexes) {
if (re2::RE2::FullMatch(signature, *regex)) {
std::lock_guard<std::mutex> lock(mutex);
models.push_back(create_model(method, context_));
break;
}
}
}
});
for (const auto* method : methods) {
queue.add_item(method);
}
queue.run_all();
return models;
}