public static boolean ResolveAttrs()

in resources/src/main/java/org/robolectric/res/android/AttributeResolution.java [64:224]


  public static boolean ResolveAttrs(ResTableTheme theme, int defStyleAttr,
                                     int defStyleRes, int[] srcValues,
                                     int srcValuesLength, int[] attrs,
                                     int attrsLength, int[] outValues, int[] outIndices) {
    if (kDebugStyles) {
      ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme,
          defStyleAttr, defStyleRes);
    }

    final ResTable res = theme.getResTable();
    ResTable_config config = new ResTable_config();
    Res_value value;

    int indicesIdx = 0;

    // Load default style from attribute, if specified...
    Ref<Integer> defStyleBagTypeSetFlags = new Ref<>(0);
    if (defStyleAttr != 0) {
      Ref<Res_value> valueRef = new Ref<>(null);
      if (theme.GetAttribute(defStyleAttr, valueRef, defStyleBagTypeSetFlags) >= 0) {
        value = valueRef.get();
        if (value.dataType == Res_value.TYPE_REFERENCE) {
          defStyleRes = value.data;
        }
      }
    }

    // Now lock down the resource object and start pulling stuff from it.
    res.lock();

    // Retrieve the default style bag, if requested.
    final Ref<ResTable.bag_entry[]> defStyleStart = new Ref<>(null);
    Ref<Integer> defStyleTypeSetFlags = new Ref<>(0);
    int bagOff = defStyleRes != 0
        ? res.getBagLocked(defStyleRes, defStyleStart, defStyleTypeSetFlags) : -1;
    defStyleTypeSetFlags.set(defStyleTypeSetFlags.get() | defStyleBagTypeSetFlags.get());
//    const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
    final int defStyleEnd = (bagOff >= 0 ? bagOff : 0);
    BagAttributeFinder defStyleAttrFinder = new BagAttributeFinder(defStyleStart.get(), defStyleEnd);

    // 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<attrsLength; ii++) {
      final int curIdent = attrs[ii];

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

      int block = -1;
      int typeSetFlags = 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 (srcValuesLength > 0 && srcValues[ii] != 0) {
        value = new Res_value((byte) Res_value.TYPE_ATTRIBUTE, srcValues[ii]);
        if (kDebugStyles) {
          ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      } else {
        final ResTable.bag_entry defStyleEntry = defStyleAttrFinder.find(curIdent);
        if (defStyleEntry != null) {
          block = defStyleEntry.stringBlock;
          typeSetFlags = defStyleTypeSetFlags.get();
          value = defStyleEntry.map.value;
          if (kDebugStyles) {
            ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
        }
      }

      int resid = 0;
      Ref<Res_value> valueRef = new Ref<>(value);
      Ref<Integer> residRef = new Ref<>(resid);
      Ref<Integer> typeSetFlagsRef = new Ref<>(typeSetFlags);
      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.
        int newBlock = theme.resolveAttributeReference(valueRef, block,
            residRef, typeSetFlagsRef, configRef);
        value = valueRef.get();
        resid = residRef.get();
        typeSetFlags = typeSetFlagsRef.get();
        config = configRef.get();
        if (newBlock >= 0) block = newBlock;
        if (kDebugStyles) {
          ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
        }
      } else {
        // If we still don't have a value for this attribute, try to find
        // it in the theme!
        int newBlock = theme.GetAttribute(curIdent, valueRef, typeSetFlagsRef);
        value = valueRef.get();
        typeSetFlags = typeSetFlagsRef.get();

        if (newBlock >= 0) {
          if (kDebugStyles) {
            ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
          newBlock = res.resolveReference(valueRef, newBlock, residRef, typeSetFlagsRef, configRef);
          value = valueRef.get();
          resid = residRef.get();
          typeSetFlags = typeSetFlagsRef.get();
          config = configRef.get();
          if (kThrowOnBadId) {
            if (newBlock == BAD_INDEX) {
              throw new IllegalStateException("Bad resource!");
            }
          }
          if (newBlock >= 0) block = newBlock;
          if (kDebugStyles) {
            ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
          }
        }
      }

      // 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;
        block = -1;
      }

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

      // Write the final value back to Java.
      outValues[destOffset + STYLE_TYPE] = value.dataType;
      outValues[destOffset + STYLE_DATA] = value.data;
      outValues[destOffset + STYLE_ASSET_COOKIE] =
          block != -1 ? res.getTableCookie(block) : -1;
      outValues[destOffset + STYLE_RESOURCE_ID] = resid;
      outValues[destOffset + STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
      outValues[destOffset + STYLE_DENSITY] = config.density;

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

      destOffset += STYLE_NUM_ENTRIES;
    }

    res.unlock();

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