Search in sources :

Example 1 with ResTable_sparseTypeEntry

use of org.robolectric.res.android.ResourceTypes.ResTable_sparseTypeEntry in project robolectric by robolectric.

the class ResTable method getEntry.

private int getEntry(final PackageGroup packageGroup, int typeIndex, int entryIndex, final ResTable_config config, Entry outEntry) {
    final List<Type> typeList = getOrDefault(packageGroup.types, typeIndex, Collections.emptyList());
    if (typeList.isEmpty()) {
        ALOGV("Skipping entry type index 0x%02x because type is NULL!\n", typeIndex);
        return BAD_TYPE;
    }
    ResTable_type bestType = null;
    int bestOffset = ResTable_type.NO_ENTRY;
    Package bestPackage = null;
    int specFlags = 0;
    byte actualTypeIndex = (byte) typeIndex;
    ResTable_config bestConfig = null;
    // memset(&bestConfig, 0, sizeof(bestConfig));
    // Iterate over the Types of each package.
    final int typeCount = typeList.size();
    for (int i = 0; i < typeCount; i++) {
        final Type typeSpec = typeList.get(i);
        int realEntryIndex = entryIndex;
        int realTypeIndex = typeIndex;
        boolean currentTypeIsOverlay = false;
        // ID to package resource ID.
        if (typeSpec.idmapEntries.hasEntries()) {
            final Ref<Short> overlayEntryIndex = new Ref<>((short) 0);
            if (typeSpec.idmapEntries.lookup(entryIndex, overlayEntryIndex) != NO_ERROR) {
                // No such mapping exists
                continue;
            }
            realEntryIndex = overlayEntryIndex.get();
            realTypeIndex = typeSpec.idmapEntries.overlayTypeId() - 1;
            currentTypeIsOverlay = true;
        }
        // entryCount do not need to match.
        if (((int) realEntryIndex) >= typeSpec.entryCount) {
            ALOGW("For resource 0x%08x, entry index(%d) is beyond type entryCount(%d)", Res_MAKEID(packageGroup.id - 1, typeIndex, entryIndex), entryIndex, ((int) typeSpec.entryCount));
            // resources in the 'android' package (old bug in AAPT).
            continue;
        }
        // Aggregate all the flags for each package that defines this entry.
        if (typeSpec.typeSpecFlags != null) {
            specFlags |= dtohl(typeSpec.typeSpecFlags[realEntryIndex]);
        } else {
            specFlags = -1;
        }
        List<ResTable_type> candidateConfigs = typeSpec.configs;
        // List<ResTable_type> filteredConfigs;
        // if (isTruthy(config) && Objects.equals(mParams, config)) {
        // // Grab the lock first so we can safely get the current filtered list.
        // synchronized (mFilteredConfigLock) {
        // // This configuration is equal to the one we have previously cached for,
        // // so use the filtered configs.
        // 
        // final TypeCacheEntry cacheEntry = packageGroup.typeCacheEntries.get(typeIndex);
        // if (i < cacheEntry.filteredConfigs.size()) {
        // if (isTruthy(cacheEntry.filteredConfigs.get(i))) {
        // // Grab a reference to the shared_ptr so it doesn't get destroyed while
        // // going through this list.
        // filteredConfigs = cacheEntry.filteredConfigs.get(i);
        // 
        // // Use this filtered list.
        // candidateConfigs = filteredConfigs;
        // }
        // }
        // }
        // }
        final int numConfigs = candidateConfigs.size();
        for (int c = 0; c < numConfigs; c++) {
            final ResTable_type thisType = candidateConfigs.get(c);
            if (thisType == NULL) {
                continue;
            }
            final ResTable_config thisConfig;
            // thisConfig.copyFromDtoH(thisType.config);
            thisConfig = ResTable_config.fromDtoH(thisType.config);
            // Check to make sure this one is valid for the current parameters.
            if (config != NULL && !thisConfig.match(config)) {
                continue;
            }
            // const uint32_t* const eindex = reinterpret_cast<const uint32_t*>(
            // reinterpret_cast<const uint8_t*>(thisType) + dtohs(thisType->header.headerSize));
            final int eindex = thisType.myOffset() + dtohs(thisType.header.headerSize);
            int thisOffset;
            // Check if there is the desired entry in this type.
            if (isTruthy(thisType.flags & ResTable_type.FLAG_SPARSE)) {
                // This is encoded as a sparse map, so perform a binary search.
                final ByteBuffer buf = thisType.myBuf();
                ResTable_sparseTypeEntry sparseIndices = new ResTable_sparseTypeEntry(buf, eindex);
                ResTable_sparseTypeEntry result = lower_bound(sparseIndices, new ResTable_sparseTypeEntry(buf, sparseIndices.myOffset() + dtohl(thisType.entryCount)), new ResTable_sparseTypeEntry(buf, realEntryIndex), (a, b) -> dtohs(a.idxOrOffset) < dtohs(b.idxOrOffset));
                // || dtohs(result.idx) != realEntryIndex) {
                if (result.myOffset() == sparseIndices.myOffset() + dtohl(thisType.entryCount) || dtohs(result.idxOrOffset) != realEntryIndex) {
                    // No entry found.
                    continue;
                }
                // Extract the offset from the entry. Each offset must be a multiple of 4
                // so we store it as the real offset divided by 4.
                // thisOffset = dtohs(result->offset) * 4u;
                thisOffset = dtohs(result.idxOrOffset) * 4;
            } else {
                if (realEntryIndex >= dtohl(thisType.entryCount)) {
                    // Entry does not exist.
                    continue;
                }
                // thisOffset = dtohl(eindex[realEntryIndex]);
                thisOffset = thisType.entryOffset(realEntryIndex);
            }
            if (thisOffset == ResTable_type.NO_ENTRY) {
                // There is no entry for this index and configuration.
                continue;
            }
            if (bestType != NULL) {
                // about to those we least care about.
                if (!thisConfig.isBetterThan(bestConfig, config)) {
                    if (!currentTypeIsOverlay || thisConfig.compare(bestConfig) != 0) {
                        continue;
                    }
                }
            }
            bestType = thisType;
            bestOffset = thisOffset;
            bestConfig = thisConfig;
            bestPackage = typeSpec._package_;
            actualTypeIndex = (byte) realTypeIndex;
            // If no config was specified, any type will do, so skip
            if (config == NULL) {
                break;
            }
        }
    }
    if (bestType == NULL) {
        return BAD_INDEX;
    }
    bestOffset += dtohl(bestType.entriesStart);
    // if (bestOffset > (dtohl(bestType->header.size)-sizeof(ResTable_entry))) {
    if (bestOffset > (dtohl(bestType.header.size) - ResTable_entry.SIZEOF)) {
        ALOGW("ResTable_entry at 0x%x is beyond type chunk data 0x%x", bestOffset, dtohl(bestType.header.size));
        return BAD_TYPE;
    }
    if ((bestOffset & 0x3) != 0) {
        ALOGW("ResTable_entry at 0x%x is not on an integer boundary", bestOffset);
        return BAD_TYPE;
    }
    // const ResTable_entry* const entry = reinterpret_cast<const ResTable_entry*>(
    // reinterpret_cast<const uint8_t*>(bestType) + bestOffset);
    final ResTable_entry entry = new ResTable_entry(bestType.myBuf(), bestType.myOffset() + bestOffset);
    if (dtohs(entry.size) < ResTable_entry.SIZEOF) {
        ALOGW("ResTable_entry size 0x%x is too small", dtohs(entry.size));
        return BAD_TYPE;
    }
    if (outEntry != null) {
        outEntry.entry = entry;
        outEntry.config = bestConfig;
        outEntry.type = bestType;
        outEntry.specFlags = specFlags;
        outEntry._package_ = bestPackage;
        outEntry.typeStr = new StringPoolRef(bestPackage.typeStrings, actualTypeIndex - bestPackage.typeIdOffset);
        outEntry.keyStr = new StringPoolRef(bestPackage.keyStrings, dtohl(entry.key.index));
    }
    return NO_ERROR;
}
Also used : ByteBuffer(java.nio.ByteBuffer) ResTable_entry(org.robolectric.res.android.ResourceTypes.ResTable_entry) ResTable_sparseTypeEntry(org.robolectric.res.android.ResourceTypes.ResTable_sparseTypeEntry) ResTable_type(org.robolectric.res.android.ResourceTypes.ResTable_type)

Example 2 with ResTable_sparseTypeEntry

use of org.robolectric.res.android.ResourceTypes.ResTable_sparseTypeEntry in project robolectric by robolectric.

the class ResTable method lower_bound.

ResTable_sparseTypeEntry lower_bound(ResTable_sparseTypeEntry first, ResTable_sparseTypeEntry last, ResTable_sparseTypeEntry value, Compare comparator) {
    int count = (last.myOffset() - first.myOffset()) / ResTable_sparseTypeEntry.SIZEOF;
    int itOffset;
    int step;
    while (count > 0) {
        itOffset = first.myOffset();
        step = count / 2;
        itOffset += step * ResTable_sparseTypeEntry.SIZEOF;
        if (comparator.compare(new ResTable_sparseTypeEntry(first.myBuf(), itOffset), value)) {
            itOffset += ResTable_sparseTypeEntry.SIZEOF;
            first = new ResTable_sparseTypeEntry(first.myBuf(), itOffset);
        } else {
            count = step;
        }
    }
    return first;
}
Also used : ResTable_sparseTypeEntry(org.robolectric.res.android.ResourceTypes.ResTable_sparseTypeEntry)

Aggregations

ResTable_sparseTypeEntry (org.robolectric.res.android.ResourceTypes.ResTable_sparseTypeEntry)2 ByteBuffer (java.nio.ByteBuffer)1 ResTable_entry (org.robolectric.res.android.ResourceTypes.ResTable_entry)1 ResTable_type (org.robolectric.res.android.ResourceTypes.ResTable_type)1