resources/src/main/java/org/robolectric/res/android/CppAssetManager2.java
private ApkAssetsCookie FindEntry(int resid, short density_override,
      boolean stop_at_first_match,
      final Ref<FindEntryResult> out_entry) {
    ATRACE_CALL();

    // Might use this if density_override != 0.
    ResTable_config density_override_config;

    // Select our configuration or generate a density override configuration.
    ResTable_config desired_config = configuration_;
    if (density_override != 0 && density_override != configuration_.density) {
      density_override_config = configuration_;
      density_override_config.density = density_override;
      desired_config = density_override_config;
    }

    if (!is_valid_resid(resid)) {
      System.err.println(String.format("Invalid ID 0x%08x.", resid));
      return K_INVALID_COOKIE;
    }

    final int package_id = get_package_id(resid);
    final int type_idx = (byte) (get_type_id(resid) - 1);
    final int entry_idx = get_entry_id(resid);

    final byte package_idx = package_ids_[package_id];
    if (package_idx == (byte) 0xff) {
      System.err.println(String.format("No package ID %02x found for ID 0x%08x.", package_id, resid));
      return K_INVALID_COOKIE;
    }

    final PackageGroup package_group = package_groups_.get(package_idx);
    final int package_count = package_group.packages_.size();

    ApkAssetsCookie best_cookie = K_INVALID_COOKIE;
    LoadedPackage best_package = null;
    ResTable_type best_type = null;
    ResTable_config best_config = null;
    ResTable_config best_config_copy;
    int best_offset = 0;
    int type_flags = 0;

    // If desired_config is the same as the set configuration, then we can use our filtered list
    // and we don't need to match the configurations, since they already matched.
    boolean use_fast_path = desired_config == configuration_;

    for (int pi = 0; pi < package_count; pi++) {
      ConfiguredPackage loaded_package_impl = package_group.packages_.get(pi);
      LoadedPackage loaded_package = loaded_package_impl.loaded_package_;
      ApkAssetsCookie cookie = package_group.cookies_.get(pi);

      // If the type IDs are offset in this package, we need to take that into account when searching
      // for a type.
      TypeSpec type_spec = loaded_package.GetTypeSpecByTypeIndex(type_idx);
      if (Util.UNLIKELY(type_spec == null)) {
        continue;
      }

      int local_entry_idx = entry_idx;

      // If there is an IDMAP supplied with this package, translate the entry ID.
      if (type_spec.idmap_entries != null) {
        if (!LoadedIdmap
            .Lookup(type_spec.idmap_entries, local_entry_idx, new Ref<>(local_entry_idx))) {
          // There is no mapping, so the resource is not meant to be in this overlay package.
          continue;
        }
      }

      type_flags |= type_spec.GetFlagsForEntryIndex(local_entry_idx);

      // If the package is an overlay, then even configurations that are the same MUST be chosen.
      boolean package_is_overlay = loaded_package.IsOverlay();

      FilteredConfigGroup filtered_group = loaded_package_impl.filtered_configs_.get(type_idx);
      if (use_fast_path) {
        List<ResTable_config> candidate_configs = filtered_group.configurations;
        int type_count = candidate_configs.size();
        for (int i = 0; i < type_count; i++) {
          ResTable_config this_config = candidate_configs.get(i);

          // We can skip calling ResTable_config.match() because we know that all candidate
          // configurations that do NOT match have been filtered-out.
          if ((best_config == null || this_config.isBetterThan(best_config, desired_config)) ||
              (package_is_overlay && this_config.compare(best_config) == 0)) {
            // The configuration matches and is better than the previous selection.
            // Find the entry value if it exists for this configuration.
            ResTable_type type_chunk = filtered_group.types.get(i);
            int offset = LoadedPackage.GetEntryOffset(type_chunk, local_entry_idx);
            if (offset == ResTable_type.NO_ENTRY) {
              continue;
            }

            best_cookie = cookie;
            best_package = loaded_package;
            best_type = type_chunk;
            best_config = this_config;
            best_offset = offset;
          }
        }
      } else {
        // This is the slower path, which doesn't use the filtered list of configurations.
        // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
        // and fill in any new fields that did not exist when the APK was compiled.
        // Furthermore when selecting configurations we can't just record the pointer to the
        // ResTable_config, we must copy it.
        // auto iter_end = type_spec.types + type_spec.type_count;
        //   for (auto iter = type_spec.types; iter != iter_end; ++iter) {
        for (ResTable_type type : type_spec.types) {
          ResTable_config this_config = ResTable_config.fromDtoH(type.config);

          if (this_config.match(desired_config)) {
            if ((best_config == null || this_config.isBetterThan(best_config, desired_config)) ||
                (package_is_overlay && this_config.compare(best_config) == 0)) {
              // The configuration matches and is better than the previous selection.
              // Find the entry value if it exists for this configuration.
              int offset = LoadedPackage.GetEntryOffset(type, local_entry_idx);
              if (offset == ResTable_type.NO_ENTRY) {
                continue;
              }

              best_cookie = cookie;
              best_package = loaded_package;
              best_type = type;
              best_config_copy = this_config;
              best_config = best_config_copy;
              best_offset = offset;
            }
          }
        }
      }
    }

    if (Util.UNLIKELY(best_cookie.intValue() == kInvalidCookie)) {
      return K_INVALID_COOKIE;
    }

    ResTable_entry best_entry = LoadedPackage.GetEntryFromOffset(best_type, best_offset);
    if (Util.UNLIKELY(best_entry == null)) {
      return K_INVALID_COOKIE;
    }

    FindEntryResult out_entry_ = new FindEntryResult();
    out_entry_.entry = best_entry;
    out_entry_.config = best_config;
    out_entry_.type_flags = type_flags;
    out_entry_.type_string_ref = new StringPoolRef(best_package.GetTypeStringPool(), best_type.id - 1);
    out_entry_.entry_string_ref =
        new StringPoolRef(best_package.GetKeyStringPool(), best_entry.key.index);
    out_entry_.dynamic_ref_table = package_group.dynamic_ref_table;
    out_entry.set(out_entry_);
    return best_cookie;
  }
private ApkAssetsCookie FindEntry(int resid, short density_override,
      boolean stop_at_first_match,
      final Ref<FindEntryResult> out_entry) {
    ATRACE_CALL();

    // Might use this if density_override != 0.
    ResTable_config density_override_config;

    // Select our configuration or generate a density override configuration.
    ResTable_config desired_config = configuration_;
    if (density_override != 0 && density_override != configuration_.density) {
      density_override_config = configuration_;
      density_override_config.density = density_override;
      desired_config = density_override_config;
    }

    if (!is_valid_resid(resid)) {
      System.err.println(String.format("Invalid ID 0x%08x.", resid));
      return K_INVALID_COOKIE;
    }

    final int package_id = get_package_id(resid);
    final int type_idx = (byte) (get_type_id(resid) - 1);
    final int entry_idx = get_entry_id(resid);

    final byte package_idx = package_ids_[package_id];
    if (package_idx == (byte) 0xff) {
      System.err.println(String.format("No package ID %02x found for ID 0x%08x.", package_id, resid));
      return K_INVALID_COOKIE;
    }

    final PackageGroup package_group = package_groups_.get(package_idx);
    final int package_count = package_group.packages_.size();

    ApkAssetsCookie best_cookie = K_INVALID_COOKIE;
    LoadedPackage best_package = null;
    ResTable_type best_type = null;
    ResTable_config best_config = null;
    ResTable_config best_config_copy;
    int best_offset = 0;
    int type_flags = 0;

    // If desired_config is the same as the set configuration, then we can use our filtered list
    // and we don't need to match the configurations, since they already matched.
    boolean use_fast_path = desired_config == configuration_;

    for (int pi = 0; pi < package_count; pi++) {
      ConfiguredPackage loaded_package_impl = package_group.packages_.get(pi);
      LoadedPackage loaded_package = loaded_package_impl.loaded_package_;
      ApkAssetsCookie cookie = package_group.cookies_.get(pi);

      // If the type IDs are offset in this package, we need to take that into account when searching
      // for a type.
      TypeSpec type_spec = loaded_package.GetTypeSpecByTypeIndex(type_idx);
      if (Util.UNLIKELY(type_spec == null)) {
        continue;
      }

      int local_entry_idx = entry_idx;

      // If there is an IDMAP supplied with this package, translate the entry ID.
      if (type_spec.idmap_entries != null) {
        if (!LoadedIdmap
            .Lookup(type_spec.idmap_entries, local_entry_idx, new Ref<>(local_entry_idx))) {
          // There is no mapping, so the resource is not meant to be in this overlay package.
          continue;
        }
      }

      type_flags |= type_spec.GetFlagsForEntryIndex(local_entry_idx);

      // If the package is an overlay, then even configurations that are the same MUST be chosen.
      boolean package_is_overlay = loaded_package.IsOverlay();

      FilteredConfigGroup filtered_group = loaded_package_impl.filtered_configs_.get(type_idx);
      if (use_fast_path) {
        List<ResTable_config> candidate_configs = filtered_group.configurations;
        int type_count = candidate_configs.size();
        for (int i = 0; i < type_count; i++) {
          ResTable_config this_config = candidate_configs.get(i);

          // We can skip calling ResTable_config.match() because we know that all candidate
          // configurations that do NOT match have been filtered-out.
          if ((best_config == null || this_config.isBetterThan(best_config, desired_config)) ||
              (package_is_overlay && this_config.compare(best_config) == 0)) {
            // The configuration matches and is better than the previous selection.
            // Find the entry value if it exists for this configuration.
            ResTable_type type_chunk = filtered_group.types.get(i);
            int offset = LoadedPackage.GetEntryOffset(type_chunk, local_entry_idx);
            if (offset == ResTable_type.NO_ENTRY) {
              continue;
            }

            best_cookie = cookie;
            best_package = loaded_package;
            best_type = type_chunk;
            best_config = this_config;
            best_offset = offset;
          }
        }
      } else {
        // This is the slower path, which doesn't use the filtered list of configurations.
        // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
        // and fill in any new fields that did not exist when the APK was compiled.
        // Furthermore when selecting configurations we can't just record the pointer to the
        // ResTable_config, we must copy it.
        // auto iter_end = type_spec.types + type_spec.type_count;
        //   for (auto iter = type_spec.types; iter != iter_end; ++iter) {
        for (ResTable_type type : type_spec.types) {
          ResTable_config this_config = ResTable_config.fromDtoH(type.config);

          if (this_config.match(desired_config)) {
            if ((best_config == null || this_config.isBetterThan(best_config, desired_config)) ||
                (package_is_overlay && this_config.compare(best_config) == 0)) {
              // The configuration matches and is better than the previous selection.
              // Find the entry value if it exists for this configuration.
              int offset = LoadedPackage.GetEntryOffset(type, local_entry_idx);
              if (offset == ResTable_type.NO_ENTRY) {
                continue;
              }

              best_cookie = cookie;
              best_package = loaded_package;
              best_type = type;
              best_config_copy = this_config;
              best_config = best_config_copy;
              best_offset = offset;
            }
          }
        }
      }
    }

    if (Util.UNLIKELY(best_cookie.intValue() == kInvalidCookie)) {
      return K_INVALID_COOKIE;
    }

    ResTable_entry best_entry = LoadedPackage.GetEntryFromOffset(best_type, best_offset);
    if (Util.UNLIKELY(best_entry == null)) {
      return K_INVALID_COOKIE;
    }

    FindEntryResult out_entry_ = new FindEntryResult();
    out_entry_.entry = best_entry;
    out_entry_.config = best_config;
    out_entry_.type_flags = type_flags;
    out_entry_.type_string_ref = new StringPoolRef(best_package.GetTypeStringPool(), best_type.id - 1);
    out_entry_.entry_string_ref =
        new StringPoolRef(best_package.GetKeyStringPool(), best_entry.key.index);
    out_entry_.dynamic_ref_table = package_group.dynamic_ref_table;
    out_entry.set(out_entry_);
    return best_cookie;
  }
private ApkAssetsCookie FindEntry ( int resid , short density_override , boolean stop_at_first_match , final Ref < FindEntryResult > out_entry ) { ATRACE_CALL ( ) ; // Might use this if density_override != 0. ResTable_config density_override_config ; // Select our configuration or generate a density override configuration. ResTable_config desired_config = configuration_ ; if ( density_override != 0 && density_override != configuration_ . density ) { density_override_config = configuration_ ; density_override_config . density = density_override ; desired_config = density_override_config ; } if ( ! is_valid_resid ( resid ) ) { System . err . println ( String . format ( "Invalid ID 0x%08x." , resid ) ) ; return K_INVALID_COOKIE ; } final int package_id = get_package_id ( resid ) ; final int type_idx = ( byte ) ( get_type_id ( resid ) - 1 ) ; final int entry_idx = get_entry_id ( resid ) ; final byte package_idx = package_ids_ [ package_id ] ; if ( package_idx == ( byte ) 0xff ) { System . err . println ( String . format ( "No package ID %02x found for ID 0x%08x." , package_id , resid ) ) ; return K_INVALID_COOKIE ; } final PackageGroup package_group = package_groups_ . get ( package_idx ) ; final int package_count = package_group . packages_ . size ( ) ; ApkAssetsCookie best_cookie = K_INVALID_COOKIE ; LoadedPackage best_package = null ; ResTable_type best_type = null ; ResTable_config best_config = null ; ResTable_config best_config_copy ; int best_offset = 0 ; int type_flags = 0 ; // If desired_config is the same as the set configuration, then we can use our filtered list // and we don't need to match the configurations, since they already matched. boolean use_fast_path = desired_config == configuration_ ; for ( int pi = 0 ; pi < package_count ; pi ++ ) { ConfiguredPackage loaded_package_impl = package_group . packages_ . get ( pi ) ; LoadedPackage loaded_package = loaded_package_impl . loaded_package_ ; ApkAssetsCookie cookie = package_group . cookies_ . get ( pi ) ; // If the type IDs are offset in this package, we need to take that into account when searching // for a type. TypeSpec type_spec = loaded_package . GetTypeSpecByTypeIndex ( type_idx ) ; if ( Util . UNLIKELY ( type_spec == null ) ) { continue ; } int local_entry_idx = entry_idx ; // If there is an IDMAP supplied with this package, translate the entry ID. if ( type_spec . idmap_entries != null ) { if ( ! LoadedIdmap . Lookup ( type_spec . idmap_entries , local_entry_idx , new Ref <> ( local_entry_idx ) ) ) { // There is no mapping, so the resource is not meant to be in this overlay package. continue ; } } type_flags |= type_spec . GetFlagsForEntryIndex ( local_entry_idx ) ; // If the package is an overlay, then even configurations that are the same MUST be chosen. boolean package_is_overlay = loaded_package . IsOverlay ( ) ; FilteredConfigGroup filtered_group = loaded_package_impl . filtered_configs_ . get ( type_idx ) ; if ( use_fast_path ) { List < ResTable_config > candidate_configs = filtered_group . configurations ; int type_count = candidate_configs . size ( ) ; for ( int i = 0 ; i < type_count ; i ++ ) { ResTable_config this_config = candidate_configs . get ( i ) ; // We can skip calling ResTable_config.match() because we know that all candidate // configurations that do NOT match have been filtered-out. if ( ( best_config == null || this_config . isBetterThan ( best_config , desired_config ) ) || ( package_is_overlay && this_config . compare ( best_config ) == 0 ) ) { // The configuration matches and is better than the previous selection. // Find the entry value if it exists for this configuration. ResTable_type type_chunk = filtered_group . types . get ( i ) ; int offset = LoadedPackage . GetEntryOffset ( type_chunk , local_entry_idx ) ; if ( offset == ResTable_type . NO_ENTRY ) { continue ; } best_cookie = cookie ; best_package = loaded_package ; best_type = type_chunk ; best_config = this_config ; best_offset = offset ; } } } else { // This is the slower path, which doesn't use the filtered list of configurations. // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness // and fill in any new fields that did not exist when the APK was compiled. // Furthermore when selecting configurations we can't just record the pointer to the // ResTable_config, we must copy it. // auto iter_end = type_spec.types + type_spec.type_count; //   for (auto iter = type_spec.types; iter != iter_end; ++iter) { for ( ResTable_type type : type_spec . types ) { ResTable_config this_config = ResTable_config . fromDtoH ( type . config ) ; if ( this_config . match ( desired_config ) ) { if ( ( best_config == null || this_config . isBetterThan ( best_config , desired_config ) ) || ( package_is_overlay && this_config . compare ( best_config ) == 0 ) ) { // The configuration matches and is better than the previous selection. // Find the entry value if it exists for this configuration. int offset = LoadedPackage . GetEntryOffset ( type , local_entry_idx ) ; if ( offset == ResTable_type . NO_ENTRY ) { continue ; } best_cookie = cookie ; best_package = loaded_package ; best_type = type ; best_config_copy = this_config ; best_config = best_config_copy ; best_offset = offset ; } } } } } if ( Util . UNLIKELY ( best_cookie . intValue ( ) == kInvalidCookie ) ) { return K_INVALID_COOKIE ; } ResTable_entry best_entry = LoadedPackage . GetEntryFromOffset ( best_type , best_offset ) ; if ( Util . UNLIKELY ( best_entry == null ) ) { return K_INVALID_COOKIE ; } FindEntryResult out_entry_ = new FindEntryResult ( ) ; out_entry_ . entry = best_entry ; out_entry_ . config = best_config ; out_entry_ . type_flags = type_flags ; out_entry_ . type_string_ref = new StringPoolRef ( best_package . GetTypeStringPool ( ) , best_type . id - 1 ) ; out_entry_ . entry_string_ref = new StringPoolRef ( best_package . GetKeyStringPool ( ) , best_entry . key . index ) ; out_entry_ . dynamic_ref_table = package_group . dynamic_ref_table ; out_entry . set ( out_entry_ ) ; return best_cookie ; }
int* out_flags);
int * out_flags ) ;