public static void ApplyStyle()

in resources/src/main/java/org/robolectric/res/android/AttributeResolution9.java [237:442]


  public static void ApplyStyle(Theme theme, ResXMLParser xml_parser, int def_style_attr,
                                int def_style_resid, int[] attrs, int attrs_length,
                                int[] out_values, int[] out_indices) {
    if (kDebugStyles) {
      ALOGI("APPLY STYLE: theme=%s defStyleAttr=0x%x defStyleRes=0x%x xml=%s",
          theme, def_style_attr, def_style_resid, xml_parser);
    }

    CppAssetManager2 assetmanager = theme.GetAssetManager();
    final Ref<ResTable_config> config = new Ref<>(new ResTable_config());
    final Ref<Res_value> value = new Ref<>(new Res_value());

    int indices_idx = 0;

    // Load default style from attribute, if specified...
    final Ref<Integer> def_style_flags = new Ref<>(0);
    if (def_style_attr != 0) {
      if (theme.GetAttribute(def_style_attr, value, def_style_flags).intValue() != kInvalidCookie) {
        if (value.get().dataType == DataType.REFERENCE.code()) {
          def_style_resid = value.get().data;
        }
      }
    }

    // Retrieve the style resource ID associated with the current XML tag's style attribute.
    int style_resid = 0;
    final Ref<Integer> style_flags = new Ref<>(0);
    if (xml_parser != null) {
      int idx = xml_parser.indexOfStyle();
      if (idx >= 0 && xml_parser.getAttributeValue(idx, value) >= 0) {
        if (value.get().dataType == DataType.ATTRIBUTE.code()) {
          // Resolve the attribute with out theme.
          if (theme.GetAttribute(value.get().data, value, style_flags).intValue() == kInvalidCookie) {
            value.set(value.get().withType(DataType.NULL.code()));
          }
        }

        if (value.get().dataType == DataType.REFERENCE.code()) {
          style_resid = value.get().data;
        }
      }
    }

    // Retrieve the default style bag, if requested.
    ResolvedBag default_style_bag = null;
    if (def_style_resid != 0) {
      default_style_bag = assetmanager.GetBag(def_style_resid);
      if (default_style_bag != null) {
        def_style_flags.set(def_style_flags.get() | default_style_bag.type_spec_flags);
      }
    }

    BagAttributeFinder def_style_attr_finder = new BagAttributeFinder(default_style_bag);

    // Retrieve the style class bag, if requested.
    ResolvedBag xml_style_bag = null;
    if (style_resid != 0) {
      xml_style_bag = assetmanager.GetBag(style_resid);
      if (xml_style_bag != null) {
        style_flags.set(style_flags.get() | xml_style_bag.type_spec_flags);
      }
    }

    BagAttributeFinder xml_style_attr_finder = new BagAttributeFinder(xml_style_bag);

    // Retrieve the XML attributes, if requested.
    XmlAttributeFinder xml_attr_finder = new XmlAttributeFinder(xml_parser);

    // Now iterate through all of the attributes that the client has requested,
    // filling in each with whatever data we can find.
    for (int ii = 0; ii < attrs_length; ii++) {
      final int cur_ident = attrs[ii];

      if (kDebugStyles) {
        ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident);
      }

      ApkAssetsCookie cookie = K_INVALID_COOKIE;
      final Ref<Integer> type_set_flags = new Ref<>(0);

      value.set(Res_value.NULL_VALUE);
      config.get().density = 0;

      // Try to find a value for this attribute...  we prioritize values
      // coming from, first XML attributes, then XML style, then default
      // style, and finally the theme.

      // Walk through the xml attributes looking for the requested attribute.
      int xml_attr_idx = xml_attr_finder.Find(cur_ident);
      if (xml_attr_idx != -1) {
        // We found the attribute we were looking for.
        xml_parser.getAttributeValue(xml_attr_idx, value);
        type_set_flags.set(style_flags.get());
        if (kDebugStyles) {
          ALOGI("-> From XML: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
        }
      }

      if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
        // Walk through the style class values looking for the requested attribute.
        Entry entry = xml_style_attr_finder.Find(cur_ident);
        if (entry != null) {
          // We found the attribute we were looking for.
          cookie = entry.cookie;
          type_set_flags.set(style_flags.get());
          value.set(entry.value);
          if (kDebugStyles) {
            ALOGI("-> From style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
          }
        }
      }

      if (value.get().dataType == DataType.NULL.code() && value.get().data != Res_value.DATA_NULL_EMPTY) {
        // Walk through the default style values looking for the requested attribute.
        Entry entry = def_style_attr_finder.Find(cur_ident);
        if (entry != null) {
          // We found the attribute we were looking for.
          cookie = entry.cookie;
          type_set_flags.set(def_style_flags.get());
          
          value.set(entry.value);
          if (kDebugStyles) {
            ALOGI("-> From def style: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
          }
        }
      }

      final Ref<Integer> resid = new Ref<>(0);
      if (value.get().dataType != DataType.NULL.code()) {
        // Take care of resolving the found resource to its final value.
        ApkAssetsCookie new_cookie =
            theme.ResolveAttributeReference(cookie, value, config, type_set_flags, resid);
        if (new_cookie.intValue() != kInvalidCookie) {
          cookie = new_cookie;
        }

        if (kDebugStyles) {
          ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
        }
      } else if (value.get().data != Res_value.DATA_NULL_EMPTY) {
        // If we still don't have a value for this attribute, try to find it in the theme!
        ApkAssetsCookie new_cookie = theme.GetAttribute(cur_ident, value, type_set_flags);
        if (new_cookie.intValue() != kInvalidCookie) {
          if (kDebugStyles) {
            ALOGI("-> From theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
          }
          new_cookie =
              assetmanager.ResolveReference(new_cookie, value, config, type_set_flags, resid);
          if (new_cookie.intValue() != kInvalidCookie) {
            cookie = new_cookie;
          }

          if (kDebugStyles) {
            ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.get().dataType, value.get().data);
          }
        }
      }

      // Deal with the special @null value -- it turns back to TYPE_NULL.
      if (value.get().dataType == DataType.REFERENCE.code() && value.get().data == 0) {
        if (kDebugStyles) {
          ALOGI(". Setting to @null!");
        }
        value.set(Res_value.NULL_VALUE);
        cookie = K_INVALID_COOKIE;
      }

      if (kDebugStyles) {
        ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.get().dataType, value.get().data);
      }

      // Write the final value back to Java.
      int destIndex = ii * STYLE_NUM_ENTRIES;
      Res_value res_value = value.get();
      out_values[destIndex + STYLE_TYPE] = res_value.dataType;
      out_values[destIndex + STYLE_DATA] = res_value.data;
      out_values[destIndex + STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
      out_values[destIndex + STYLE_RESOURCE_ID] = resid.get();
      out_values[destIndex + STYLE_CHANGING_CONFIGURATIONS] = type_set_flags.get();
      out_values[destIndex + STYLE_DENSITY] = config.get().density;

      if (res_value.dataType != DataType.NULL.code() || res_value.data == Res_value.DATA_NULL_EMPTY) {
        indices_idx++;

        // out_indices must NOT be nullptr.
        out_indices[indices_idx] = ii;
      }

      // Robolectric-custom:
      // if (false && res_value.dataType == DataType.ATTRIBUTE.code()) {
      //   final Ref<ResourceName> attrName = new Ref<>(null);
      //   final Ref<ResourceName> attrRefName = new Ref<>(null);
      //   boolean gotName = assetmanager.GetResourceName(cur_ident, attrName);
      //   boolean gotRefName = assetmanager.GetResourceName(res_value.data, attrRefName);
      //   Logger.warn(
      //       "Failed to resolve attribute lookup: %s=\"?%s\"; theme: %s",
      //       gotName ? attrName.get() : "unknown", gotRefName ? attrRefName.get() : "unknown",
      //       theme);
      // }

//      out_values += STYLE_NUM_ENTRIES;
    }

    // out_indices must NOT be nullptr.
    out_indices[0] = indices_idx;
  }