std::vector ContentProviderGenerator::emit_method_models()

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;
}