entity_annotator_native_library.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/optimization_guide/core/entity_annotator_native_library.h"
  5. #include "base/base_paths.h"
  6. #include "base/compiler_specific.h"
  7. #include "base/logging.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/metrics/histogram_functions.h"
  10. #include "base/path_service.h"
  11. #include "build/build_config.h"
  12. #include "components/optimization_guide/core/model_util.h"
  13. #include "components/optimization_guide/core/optimization_guide_util.h"
  14. #include "components/optimization_guide/proto/page_entities_model_metadata.pb.h"
  15. #if BUILDFLAG(IS_MAC)
  16. #include "base/mac/bundle_locations.h"
  17. #include "base/mac/foundation_util.h"
  18. #endif
  19. // IMPORTANT: All functions in this file that call dlsym()'ed
  20. // functions should be annotated with DISABLE_CFI_DLSYM.
  21. namespace optimization_guide {
  22. namespace {
  23. const char kModelMetadataBaseName[] = "model_metadata.pb";
  24. const char kWordEmbeddingsBaseName[] = "word_embeddings";
  25. const char kNameTableBaseName[] = "entities_names";
  26. const char kMetadataTableBaseName[] = "entities_metadata";
  27. const char kNameFilterBaseName[] = "entities_names_filter";
  28. const char kPrefixFilterBaseName[] = "entities_prefixes_filter";
  29. // Sets |field_to_set| with the full file path of |base_name|'s entry in
  30. // |base_to_full_file_path|. Returns whether |base_name| is in
  31. // |base_to_full_file_path|.
  32. absl::optional<std::string> GetFilePathFromMap(
  33. const std::string& base_name,
  34. const base::flat_map<std::string, base::FilePath>& base_to_full_file_path) {
  35. auto it = base_to_full_file_path.find(base_name);
  36. return it == base_to_full_file_path.end()
  37. ? absl::nullopt
  38. : absl::make_optional(FilePathToString(it->second));
  39. }
  40. // Returns the expected base name for |slice|. Will be of the form
  41. // |slice|-|base_name|.
  42. std::string GetSliceBaseName(const std::string& slice,
  43. const std::string& base_name) {
  44. return slice + "-" + base_name;
  45. }
  46. class ScopedEntityAnnotatorCreationStatusRecorder {
  47. public:
  48. ScopedEntityAnnotatorCreationStatusRecorder() = default;
  49. ~ScopedEntityAnnotatorCreationStatusRecorder() {
  50. DCHECK_NE(status_, EntityAnnotatorCreationStatus::kUnknown);
  51. base::UmaHistogramEnumeration(
  52. "OptimizationGuide.PageEntitiesModelExecutor.CreationStatus", status_);
  53. }
  54. void set_status(EntityAnnotatorCreationStatus status) { status_ = status; }
  55. private:
  56. EntityAnnotatorCreationStatus status_ =
  57. EntityAnnotatorCreationStatus::kUnknown;
  58. };
  59. } // namespace
  60. EntityAnnotatorNativeLibrary::EntityAnnotatorNativeLibrary(
  61. base::NativeLibrary native_library,
  62. bool should_provide_filter_path)
  63. : native_library_(std::move(native_library)),
  64. should_provide_filter_path_(should_provide_filter_path) {
  65. LoadFunctions();
  66. }
  67. EntityAnnotatorNativeLibrary::~EntityAnnotatorNativeLibrary() = default;
  68. // static
  69. std::unique_ptr<EntityAnnotatorNativeLibrary>
  70. EntityAnnotatorNativeLibrary::Create(bool should_provide_filter_path) {
  71. base::FilePath base_dir;
  72. #if !BUILDFLAG(IS_ANDROID)
  73. #if BUILDFLAG(IS_MAC)
  74. if (base::mac::AmIBundled()) {
  75. base_dir = base::mac::FrameworkBundlePath().Append("Libraries");
  76. } else {
  77. #endif // BUILDFLAG(IS_MAC)
  78. if (!base::PathService::Get(base::DIR_MODULE, &base_dir)) {
  79. LOG(ERROR) << "Error getting app dir";
  80. return nullptr;
  81. }
  82. #if BUILDFLAG(IS_MAC)
  83. }
  84. #endif // BUILDFLAG(IS_MAC)
  85. #endif // !BUILDFLAG(IS_ANDROID)
  86. base::NativeLibraryLoadError error;
  87. base::NativeLibrary native_library = base::LoadNativeLibrary(
  88. base_dir.AppendASCII(
  89. base::GetNativeLibraryName("optimization_guide_internal")),
  90. &error);
  91. base::UmaHistogramBoolean(
  92. "OptimizationGuide.EntityAnnotatorNativeLibrary.InitiatedSuccessfully",
  93. (native_library != nullptr));
  94. if (!native_library) {
  95. LOG(ERROR) << "Failed to initialize optimization guide internal: "
  96. << error.ToString();
  97. return nullptr;
  98. }
  99. std::unique_ptr<EntityAnnotatorNativeLibrary>
  100. entity_annotator_native_library =
  101. base::WrapUnique<EntityAnnotatorNativeLibrary>(
  102. new EntityAnnotatorNativeLibrary(std::move(native_library),
  103. should_provide_filter_path));
  104. if (entity_annotator_native_library->IsValid()) {
  105. return entity_annotator_native_library;
  106. }
  107. LOG(ERROR) << "Could not find all required functions for optimization guide "
  108. "internal library";
  109. return nullptr;
  110. }
  111. DISABLE_CFI_DLSYM
  112. void EntityAnnotatorNativeLibrary::LoadFunctions() {
  113. get_max_supported_feature_flag_func_ =
  114. reinterpret_cast<GetMaxSupportedFeatureFlagFunc>(
  115. base::GetFunctionPointerFromNativeLibrary(
  116. native_library_,
  117. "OptimizationGuideEntityAnnotatorGetMaxSupportedFeatureFlag"));
  118. create_from_options_func_ = reinterpret_cast<CreateFromOptionsFunc>(
  119. base::GetFunctionPointerFromNativeLibrary(
  120. native_library_,
  121. "OptimizationGuideEntityAnnotatorCreateFromOptions"));
  122. get_creation_error_func_ = reinterpret_cast<GetCreationErrorFunc>(
  123. base::GetFunctionPointerFromNativeLibrary(
  124. native_library_, "OptimizationGuideEntityAnnotatorGetCreationError"));
  125. delete_func_ =
  126. reinterpret_cast<DeleteFunc>(base::GetFunctionPointerFromNativeLibrary(
  127. native_library_, "OptimizationGuideEntityAnnotatorDelete"));
  128. annotate_job_create_func_ = reinterpret_cast<AnnotateJobCreateFunc>(
  129. base::GetFunctionPointerFromNativeLibrary(
  130. native_library_,
  131. "OptimizationGuideEntityAnnotatorAnnotateJobCreate"));
  132. annotate_job_delete_func_ = reinterpret_cast<AnnotateJobDeleteFunc>(
  133. base::GetFunctionPointerFromNativeLibrary(
  134. native_library_,
  135. "OptimizationGuideEntityAnnotatorAnnotateJobDelete"));
  136. run_annotate_job_func_ = reinterpret_cast<RunAnnotateJobFunc>(
  137. base::GetFunctionPointerFromNativeLibrary(
  138. native_library_, "OptimizationGuideEntityAnnotatorRunAnnotateJob"));
  139. annotate_get_output_metadata_at_index_func_ = reinterpret_cast<
  140. AnnotateGetOutputMetadataAtIndexFunc>(
  141. base::GetFunctionPointerFromNativeLibrary(
  142. native_library_,
  143. "OptimizationGuideEntityAnnotatorAnnotateGetOutputMetadataAtIndex"));
  144. annotate_get_output_metadata_score_at_index_func_ =
  145. reinterpret_cast<AnnotateGetOutputMetadataScoreAtIndexFunc>(
  146. base::GetFunctionPointerFromNativeLibrary(
  147. native_library_,
  148. "OptimizationGuideEntityAnnotatorAnnotateGetOutputMetadataScoreAt"
  149. "Index"));
  150. entity_metadata_job_create_func_ =
  151. reinterpret_cast<EntityMetadataJobCreateFunc>(
  152. base::GetFunctionPointerFromNativeLibrary(
  153. native_library_,
  154. "OptimizationGuideEntityAnnotatorEntityMetadataJobCreate"));
  155. entity_metadata_job_delete_func_ =
  156. reinterpret_cast<EntityMetadataJobDeleteFunc>(
  157. base::GetFunctionPointerFromNativeLibrary(
  158. native_library_,
  159. "OptimizationGuideEntityAnnotatorEntityMetadataJobDelete"));
  160. run_entity_metadata_job_func_ = reinterpret_cast<RunEntityMetadataJobFunc>(
  161. base::GetFunctionPointerFromNativeLibrary(
  162. native_library_,
  163. "OptimizationGuideEntityAnnotatorRunEntityMetadataJob"));
  164. options_create_func_ = reinterpret_cast<OptionsCreateFunc>(
  165. base::GetFunctionPointerFromNativeLibrary(
  166. native_library_, "OptimizationGuideEntityAnnotatorOptionsCreate"));
  167. options_set_model_file_path_func_ =
  168. reinterpret_cast<OptionsSetModelFilePathFunc>(
  169. base::GetFunctionPointerFromNativeLibrary(
  170. native_library_,
  171. "OptimizationGuideEntityAnnotatorOptionsSetModelFilePath"));
  172. options_set_model_metadata_file_path_func_ = reinterpret_cast<
  173. OptionsSetModelMetadataFilePathFunc>(
  174. base::GetFunctionPointerFromNativeLibrary(
  175. native_library_,
  176. "OptimizationGuideEntityAnnotatorOptionsSetModelMetadataFilePath"));
  177. options_set_word_embeddings_file_path_func_ = reinterpret_cast<
  178. OptionsSetWordEmbeddingsFilePathFunc>(
  179. base::GetFunctionPointerFromNativeLibrary(
  180. native_library_,
  181. "OptimizationGuideEntityAnnotatorOptionsSetWordEmbeddingsFilePath"));
  182. options_add_model_slice_func_ = reinterpret_cast<OptionsAddModelSliceFunc>(
  183. base::GetFunctionPointerFromNativeLibrary(
  184. native_library_,
  185. "OptimizationGuideEntityAnnotatorOptionsAddModelSlice"));
  186. options_delete_func_ = reinterpret_cast<OptionsDeleteFunc>(
  187. base::GetFunctionPointerFromNativeLibrary(
  188. native_library_, "OptimizationGuideEntityAnnotatorOptionsDelete"));
  189. entity_metadata_get_entity_id_func_ =
  190. reinterpret_cast<EntityMetadataGetEntityIdFunc>(
  191. base::GetFunctionPointerFromNativeLibrary(
  192. native_library_, "OptimizationGuideEntityMetadataGetEntityID"));
  193. entity_metadata_get_human_readable_name_func_ =
  194. reinterpret_cast<EntityMetadataGetHumanReadableNameFunc>(
  195. base::GetFunctionPointerFromNativeLibrary(
  196. native_library_,
  197. "OptimizationGuideEntityMetadataGetHumanReadableName"));
  198. entity_metadata_get_human_readable_categories_count_func_ = reinterpret_cast<
  199. EntityMetadataGetHumanReadableCategoriesCountFunc>(
  200. base::GetFunctionPointerFromNativeLibrary(
  201. native_library_,
  202. "OptimizationGuideEntityMetadataGetHumanReadableCategoriesCount"));
  203. entity_metadata_get_human_readable_category_name_at_index_func_ =
  204. reinterpret_cast<EntityMetadataGetHumanReadableCategoryNameAtIndexFunc>(
  205. base::GetFunctionPointerFromNativeLibrary(
  206. native_library_,
  207. "OptimizationGuideEntityMetadataGetHumanReadableCategoryNameAtInd"
  208. "ex"));
  209. entity_metadata_get_human_readable_category_score_at_index_func_ =
  210. reinterpret_cast<EntityMetadataGetHumanReadableCategoryScoreAtIndexFunc>(
  211. base::GetFunctionPointerFromNativeLibrary(
  212. native_library_,
  213. "OptimizationGuideEntityMetadataGetHumanReadableCategoryScoreAtIn"
  214. "dex"));
  215. entity_metadata_get_human_readable_aliases_count_func_ =
  216. reinterpret_cast<EntityMetadataGetHumanReadableAliasesCountFunc>(
  217. base::GetFunctionPointerFromNativeLibrary(
  218. native_library_,
  219. "OptimizationGuideEntityMetadataGetHumanReadableAliasesCount"));
  220. entity_metadata_get_human_readable_alias_at_index_func_ =
  221. reinterpret_cast<EntityMetadataGetHumanReadableAliasAtIndexFunc>(
  222. base::GetFunctionPointerFromNativeLibrary(
  223. native_library_,
  224. "OptimizationGuideEntityMetadataGetHumanReadableAliasAtIndex"));
  225. entity_metadata_get_collections_count_func_ =
  226. reinterpret_cast<EntityMetadataGetCollectionsCountFunc>(
  227. base::GetFunctionPointerFromNativeLibrary(
  228. native_library_,
  229. "OptimizationGuideEntityMetadataGetCollectionsCount"));
  230. entity_metadata_get_collection_at_index_func_ =
  231. reinterpret_cast<EntityMetadataGetCollectionAtIndexFunc>(
  232. base::GetFunctionPointerFromNativeLibrary(
  233. native_library_,
  234. "OptimizationGuideEntityMetadataGetCollectionAtIndex"));
  235. }
  236. DISABLE_CFI_DLSYM
  237. bool EntityAnnotatorNativeLibrary::IsValid() const {
  238. return get_max_supported_feature_flag_func_ && create_from_options_func_ &&
  239. get_creation_error_func_ && delete_func_ &&
  240. annotate_job_create_func_ && annotate_job_delete_func_ &&
  241. run_annotate_job_func_ &&
  242. annotate_get_output_metadata_at_index_func_ &&
  243. annotate_get_output_metadata_score_at_index_func_ &&
  244. entity_metadata_job_create_func_ && entity_metadata_job_delete_func_ &&
  245. run_entity_metadata_job_func_ && options_create_func_ &&
  246. options_set_model_file_path_func_ &&
  247. options_set_model_metadata_file_path_func_ &&
  248. options_set_word_embeddings_file_path_func_ &&
  249. options_add_model_slice_func_ && options_delete_func_ &&
  250. entity_metadata_get_entity_id_func_ &&
  251. entity_metadata_get_human_readable_name_func_ &&
  252. entity_metadata_get_human_readable_categories_count_func_ &&
  253. entity_metadata_get_human_readable_category_name_at_index_func_ &&
  254. entity_metadata_get_human_readable_category_score_at_index_func_ &&
  255. entity_metadata_get_human_readable_aliases_count_func_ &&
  256. entity_metadata_get_human_readable_alias_at_index_func_ &&
  257. entity_metadata_get_collections_count_func_ &&
  258. entity_metadata_get_collection_at_index_func_;
  259. }
  260. DISABLE_CFI_DLSYM
  261. int32_t EntityAnnotatorNativeLibrary::GetMaxSupportedFeatureFlag() {
  262. DCHECK(IsValid());
  263. if (!IsValid()) {
  264. return -1;
  265. }
  266. return get_max_supported_feature_flag_func_();
  267. }
  268. DISABLE_CFI_DLSYM
  269. void* EntityAnnotatorNativeLibrary::CreateEntityAnnotator(
  270. const ModelInfo& model_info) {
  271. ScopedEntityAnnotatorCreationStatusRecorder recorder;
  272. DCHECK(IsValid());
  273. if (!IsValid()) {
  274. recorder.set_status(EntityAnnotatorCreationStatus::kLibraryInvalid);
  275. return nullptr;
  276. }
  277. void* options = options_create_func_();
  278. EntityAnnotatorCreationStatus status;
  279. if (!PopulateEntityAnnotatorOptionsFromModelInfo(options, model_info,
  280. &status)) {
  281. options_delete_func_(options);
  282. recorder.set_status(status);
  283. return nullptr;
  284. }
  285. void* entity_annotator = create_from_options_func_(options);
  286. const char* creation_error = get_creation_error_func_(entity_annotator);
  287. if (creation_error) {
  288. LOG(ERROR) << "Failed to create entity annotator: " << creation_error;
  289. recorder.set_status(EntityAnnotatorCreationStatus::kInitializationFailure);
  290. DeleteEntityAnnotator(entity_annotator);
  291. entity_annotator = nullptr;
  292. } else {
  293. recorder.set_status(EntityAnnotatorCreationStatus::kSuccess);
  294. }
  295. options_delete_func_(options);
  296. return entity_annotator;
  297. }
  298. DISABLE_CFI_DLSYM
  299. bool EntityAnnotatorNativeLibrary::PopulateEntityAnnotatorOptionsFromModelInfo(
  300. void* options,
  301. const ModelInfo& model_info,
  302. EntityAnnotatorCreationStatus* status) {
  303. // We don't know which files are intended for use if we don't have model
  304. // metadata, so return early.
  305. if (!model_info.GetModelMetadata()) {
  306. *status = EntityAnnotatorCreationStatus::kMissingModelMetadata;
  307. return false;
  308. }
  309. // // Validate the model metadata.
  310. absl::optional<proto::PageEntitiesModelMetadata> entities_model_metadata =
  311. ParsedAnyMetadata<proto::PageEntitiesModelMetadata>(
  312. model_info.GetModelMetadata().value());
  313. if (!entities_model_metadata) {
  314. *status = EntityAnnotatorCreationStatus::kMissingEntitiesModelMetadata;
  315. return false;
  316. }
  317. if (entities_model_metadata->slice_size() == 0) {
  318. *status = EntityAnnotatorCreationStatus::
  319. kMissingEntitiesModelMetadataSliceSpecification;
  320. return false;
  321. }
  322. // Build the entity annotator options.
  323. options_set_model_file_path_func_(
  324. options, FilePathToString(model_info.GetModelFilePath()).c_str());
  325. // Attach the additional files required by the model.
  326. base::flat_map<std::string, base::FilePath> base_to_full_file_path;
  327. for (const auto& model_file : model_info.GetAdditionalFiles()) {
  328. base_to_full_file_path.insert(
  329. {FilePathToString(model_file.BaseName()), model_file});
  330. }
  331. absl::optional<std::string> model_metadata_file_path =
  332. GetFilePathFromMap(kModelMetadataBaseName, base_to_full_file_path);
  333. if (!model_metadata_file_path) {
  334. *status = EntityAnnotatorCreationStatus::
  335. kMissingAdditionalEntitiesModelMetadataPath;
  336. return false;
  337. }
  338. options_set_model_metadata_file_path_func_(options,
  339. model_metadata_file_path->c_str());
  340. absl::optional<std::string> word_embeddings_file_path =
  341. GetFilePathFromMap(kWordEmbeddingsBaseName, base_to_full_file_path);
  342. if (!word_embeddings_file_path) {
  343. *status =
  344. EntityAnnotatorCreationStatus::kMissingAdditionalWordEmbeddingsPath;
  345. return false;
  346. }
  347. options_set_word_embeddings_file_path_func_(
  348. options, word_embeddings_file_path->c_str());
  349. base::flat_set<std::string> slices(entities_model_metadata->slice().begin(),
  350. entities_model_metadata->slice().end());
  351. for (const auto& slice_id : slices) {
  352. absl::optional<std::string> name_filter_path;
  353. if (should_provide_filter_path_) {
  354. name_filter_path =
  355. GetFilePathFromMap(GetSliceBaseName(slice_id, kNameFilterBaseName),
  356. base_to_full_file_path);
  357. if (!name_filter_path) {
  358. *status =
  359. EntityAnnotatorCreationStatus::kMissingAdditionalNameFilterPath;
  360. return false;
  361. }
  362. }
  363. absl::optional<std::string> name_table_path = GetFilePathFromMap(
  364. GetSliceBaseName(slice_id, kNameTableBaseName), base_to_full_file_path);
  365. if (!name_table_path) {
  366. *status = EntityAnnotatorCreationStatus::kMissingAdditionalNameTablePath;
  367. return false;
  368. }
  369. absl::optional<std::string> prefix_filter_path;
  370. if (should_provide_filter_path_) {
  371. prefix_filter_path =
  372. GetFilePathFromMap(GetSliceBaseName(slice_id, kPrefixFilterBaseName),
  373. base_to_full_file_path);
  374. if (!prefix_filter_path) {
  375. *status =
  376. EntityAnnotatorCreationStatus::kMissingAdditionalPrefixFilterPath;
  377. return false;
  378. }
  379. }
  380. absl::optional<std::string> metadata_table_path =
  381. GetFilePathFromMap(GetSliceBaseName(slice_id, kMetadataTableBaseName),
  382. base_to_full_file_path);
  383. if (!metadata_table_path) {
  384. *status =
  385. EntityAnnotatorCreationStatus::kMissingAdditionalMetadataTablePath;
  386. return false;
  387. }
  388. options_add_model_slice_func_(
  389. options, slice_id.c_str(), name_filter_path.value_or("").c_str(),
  390. name_table_path->c_str(), prefix_filter_path.value_or("").c_str(),
  391. metadata_table_path->c_str());
  392. }
  393. return true;
  394. }
  395. DISABLE_CFI_DLSYM
  396. void EntityAnnotatorNativeLibrary::DeleteEntityAnnotator(
  397. void* entity_annotator) {
  398. DCHECK(IsValid());
  399. if (!IsValid()) {
  400. return;
  401. }
  402. delete_func_(reinterpret_cast<void*>(entity_annotator));
  403. }
  404. DISABLE_CFI_DLSYM
  405. absl::optional<std::vector<ScoredEntityMetadata>>
  406. EntityAnnotatorNativeLibrary::AnnotateText(void* annotator,
  407. const std::string& text) {
  408. DCHECK(IsValid());
  409. if (!IsValid()) {
  410. return absl::nullopt;
  411. }
  412. if (!annotator) {
  413. return absl::nullopt;
  414. }
  415. void* job = annotate_job_create_func_(reinterpret_cast<void*>(annotator));
  416. int32_t output_metadata_count = run_annotate_job_func_(job, text.c_str());
  417. if (output_metadata_count <= 0) {
  418. return absl::nullopt;
  419. }
  420. std::vector<ScoredEntityMetadata> scored_md;
  421. scored_md.reserve(output_metadata_count);
  422. for (int32_t i = 0; i < output_metadata_count; i++) {
  423. ScoredEntityMetadata md;
  424. md.score = annotate_get_output_metadata_score_at_index_func_(job, i);
  425. md.metadata = GetEntityMetadataFromOptimizationGuideEntityMetadata(
  426. annotate_get_output_metadata_at_index_func_(job, i));
  427. scored_md.emplace_back(md);
  428. }
  429. annotate_job_delete_func_(job);
  430. return scored_md;
  431. }
  432. DISABLE_CFI_DLSYM
  433. absl::optional<EntityMetadata>
  434. EntityAnnotatorNativeLibrary::GetEntityMetadataForEntityId(
  435. void* annotator,
  436. const std::string& entity_id) {
  437. DCHECK(IsValid());
  438. if (!IsValid()) {
  439. return absl::nullopt;
  440. }
  441. if (!annotator) {
  442. return absl::nullopt;
  443. }
  444. void* job =
  445. entity_metadata_job_create_func_(reinterpret_cast<void*>(annotator));
  446. const void* entity_metadata =
  447. run_entity_metadata_job_func_(job, entity_id.c_str());
  448. if (!entity_metadata) {
  449. return absl::nullopt;
  450. }
  451. EntityMetadata md =
  452. GetEntityMetadataFromOptimizationGuideEntityMetadata(entity_metadata);
  453. entity_metadata_job_delete_func_(job);
  454. return md;
  455. }
  456. DISABLE_CFI_DLSYM
  457. EntityMetadata EntityAnnotatorNativeLibrary::
  458. GetEntityMetadataFromOptimizationGuideEntityMetadata(
  459. const void* og_entity_metadata) {
  460. EntityMetadata entity_metadata;
  461. entity_metadata.entity_id =
  462. entity_metadata_get_entity_id_func_(og_entity_metadata);
  463. entity_metadata.human_readable_name =
  464. entity_metadata_get_human_readable_name_func_(og_entity_metadata);
  465. int32_t human_readable_categories_count =
  466. entity_metadata_get_human_readable_categories_count_func_(
  467. og_entity_metadata);
  468. for (int32_t i = 0; i < human_readable_categories_count; i++) {
  469. std::string category_name =
  470. entity_metadata_get_human_readable_category_name_at_index_func_(
  471. og_entity_metadata, i);
  472. float category_score =
  473. entity_metadata_get_human_readable_category_score_at_index_func_(
  474. og_entity_metadata, i);
  475. entity_metadata.human_readable_categories[category_name] = category_score;
  476. }
  477. int32_t human_readable_aliases_count =
  478. entity_metadata_get_human_readable_aliases_count_func_(
  479. og_entity_metadata);
  480. for (int32_t i = 0; i < human_readable_aliases_count; i++) {
  481. entity_metadata.human_readable_aliases.push_back(
  482. entity_metadata_get_human_readable_alias_at_index_func_(
  483. og_entity_metadata, i));
  484. }
  485. int32_t collections_count =
  486. entity_metadata_get_collections_count_func_(og_entity_metadata);
  487. for (int32_t i = 0; i < collections_count; i++) {
  488. std::string collection =
  489. entity_metadata_get_collection_at_index_func_(og_entity_metadata, i);
  490. entity_metadata.collections.push_back(collection);
  491. }
  492. return entity_metadata;
  493. }
  494. } // namespace optimization_guide