public static boolean ResolveAttrs()

in resources/src/main/java/org/robolectric/res/android/AttributeResolution9.java [89:235]


  public static boolean ResolveAttrs(Theme theme, int def_style_attr,
                                     int def_style_res, int[] src_values,
                                     int src_values_length, int[] attrs,
                                     int attrs_length, int[] out_values, int[] out_indices) {
    if (kDebugStyles) {
      ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
          def_style_attr, def_style_res);
    }

    CppAssetManager2 assetmanager = theme.GetAssetManager();
    ResTable_config config = new ResTable_config();
    Res_value value;

    int indicesIdx = 0;

    // Load default style from attribute, if specified...
    final Ref<Integer> def_style_flags = new Ref<>(0);
    if (def_style_attr != 0) {
      final Ref<Res_value> valueRef = new Ref<>(null);
      if (theme.GetAttribute(def_style_attr, valueRef, def_style_flags).intValue() != kInvalidCookie) {
        value = valueRef.get();
        if (value.dataType == Res_value.TYPE_REFERENCE) {
          def_style_res = value.data;
        }
      }
    }

    // Retrieve the default style bag, if requested.
    ResolvedBag default_style_bag = null;
    if (def_style_res != 0) {
      default_style_bag = assetmanager.GetBag(def_style_res);
      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);

    // Now iterate through all of the attributes that the client has requested,
    // filling in each with whatever data we can find.
    int destOffset = 0;
    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;
      int type_set_flags = 0;

      value = Res_value.NULL_VALUE;
      config.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.

      // Retrieve the current input value if available.
      if (src_values_length > 0 && src_values[ii] != 0) {
        value = new Res_value((byte) Res_value.TYPE_ATTRIBUTE, src_values[ii]);
        if (kDebugStyles) {
          ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      } else {
        final Entry entry = def_style_attr_finder.Find(cur_ident);
        if (entry != null) {
          cookie = entry.cookie;
          type_set_flags = def_style_flags.get();
          value = entry.value;
          if (kDebugStyles) {
            ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
        }
      }

      int resid = 0;
      final Ref<Res_value> valueRef = new Ref<>(value);
      final Ref<Integer> residRef = new Ref<>(resid);
      final Ref<Integer> type_set_flagsRef = new Ref<>(type_set_flags);
      final Ref<ResTable_config> configRef = new Ref<>(config);
      if (value.dataType != Res_value.TYPE_NULL) {
        // Take care of resolving the found resource to its final value.
        ApkAssetsCookie new_cookie =
            theme.ResolveAttributeReference(cookie, valueRef, configRef, type_set_flagsRef, residRef);
        if (new_cookie.intValue() != kInvalidCookie) {
          cookie = new_cookie;
        }
        if (kDebugStyles) {
          ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      } else if (value.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, valueRef, type_set_flagsRef);
        if (new_cookie.intValue() != kInvalidCookie) {
          if (kDebugStyles) {
            ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
          new_cookie =
              assetmanager.ResolveReference(new_cookie, valueRef, configRef, type_set_flagsRef, residRef);
          if (new_cookie.intValue() != kInvalidCookie) {
            cookie = new_cookie;
          }
          if (kDebugStyles) {
            ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
        }
      }
      value = valueRef.get();
      resid = residRef.get();
      type_set_flags = type_set_flagsRef.get();
      config = configRef.get();

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

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

      // Write the final value back to Java.
      out_values[destOffset + STYLE_TYPE] = value.dataType;
      out_values[destOffset + STYLE_DATA] = value.data;
      out_values[destOffset + STYLE_ASSET_COOKIE] = ApkAssetsCookieToJavaCookie(cookie);
      out_values[destOffset + STYLE_RESOURCE_ID] = resid;
      out_values[destOffset + STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
      out_values[destOffset + STYLE_DENSITY] = config.density;

      if (out_indices != null && value.dataType != Res_value.TYPE_NULL) {
        indicesIdx++;
        out_indices[indicesIdx] = ii;
      }

      destOffset += STYLE_NUM_ENTRIES;
    }

    if (out_indices != null) {
      out_indices[0] = indicesIdx;
    }
    return true;
  }