use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class DynamicRefTable method lookupResourceValue.
//
int lookupResourceValue(Ref<Res_value> value) {
byte resolvedType = DataType.REFERENCE.code();
Res_value inValue = value.get();
switch(DataType.fromCode(inValue.dataType)) {
case ATTRIBUTE:
resolvedType = DataType.ATTRIBUTE.code();
// fallthrough
case REFERENCE:
if (!mAppAsLib) {
return NO_ERROR;
}
// also need to be fixed.
break;
case DYNAMIC_ATTRIBUTE:
resolvedType = DataType.ATTRIBUTE.code();
// fallthrough
case DYNAMIC_REFERENCE:
break;
default:
return NO_ERROR;
}
final Ref<Integer> resIdRef = new Ref<>(inValue.data);
int err = lookupResourceId(resIdRef);
value.set(inValue.withData(resIdRef.get()));
if (err != NO_ERROR) {
return err;
}
value.set(new Res_value(resolvedType, resIdRef.get()));
return NO_ERROR;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class ResTable method getResource.
public final int getResource(int resID, Ref<Res_value> outValue, boolean mayBeBag, int density, final Ref<Integer> outSpecFlags, Ref<ResTable_config> outConfig) {
if (mError != NO_ERROR) {
return mError;
}
final int p = getResourcePackageIndex(resID);
final int t = Res_GETTYPE(resID);
final int e = Res_GETENTRY(resID);
if (p < 0) {
if (Res_GETPACKAGE(resID) + 1 == 0) {
ALOGW("No package identifier when getting value for resource number 0x%08x", resID);
} else {
ALOGW("No known package when getting value for resource number 0x%08x", resID);
}
return BAD_INDEX;
}
if (t < 0) {
ALOGW("No type identifier when getting value for resource number 0x%08x", resID);
return BAD_INDEX;
}
final PackageGroup grp = mPackageGroups.get(p);
if (grp == NULL) {
ALOGW("Bad identifier when getting value for resource number 0x%08x", resID);
return BAD_INDEX;
}
// Allow overriding density
ResTable_config desiredConfig = mParams;
if (density > 0) {
desiredConfig.density = density;
}
Entry entry = new Entry();
int err = getEntry(grp, t, e, desiredConfig, entry);
if (err != NO_ERROR) {
// part of a tool. The caller will do its own logging.
return err;
}
if ((entry.entry.flags & ResTable_entry.FLAG_COMPLEX) != 0) {
if (!mayBeBag) {
ALOGW("Requesting resource 0x%08x failed because it is complex\n", resID);
}
return BAD_VALUE;
}
// const Res_value* value = reinterpret_cast<const Res_value*>(
// reinterpret_cast<const uint8_t*>(entry.entry) + entry.entry->size);
Res_value value = new Res_value(entry.entry.myBuf(), entry.entry.myOffset() + entry.entry.size);
// outValue.size = dtohs(value.size);
// outValue.res0 = value.res0;
// outValue.dataType = value.dataType;
// outValue.data = dtohl(value.data);
outValue.set(value);
// We need to fix the package ID based on a mapping.
if (grp.dynamicRefTable.lookupResourceValue(outValue) != NO_ERROR) {
ALOGW("Failed to resolve referenced package: 0x%08x", outValue.get().data);
return BAD_VALUE;
}
if (outSpecFlags != null) {
outSpecFlags.set(entry.specFlags);
}
if (outConfig != null) {
outConfig.set(entry.config);
}
return entry._package_.header.index;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class ResTable method getBagLocked.
public int getBagLocked(int resID, Ref<bag_entry[]> outBag, Ref<Integer> outTypeSpecFlags) {
if (mError != NO_ERROR) {
return mError;
}
final int p = getResourcePackageIndex(resID);
final int t = Res_GETTYPE(resID);
final int e = Res_GETENTRY(resID);
if (p < 0) {
ALOGW("Invalid package identifier when getting bag for resource number 0x%08x", resID);
return BAD_INDEX;
}
if (t < 0) {
ALOGW("No type identifier when getting bag for resource number 0x%08x", resID);
return BAD_INDEX;
}
// printf("Get bag: id=0x%08x, p=%d, t=%d\n", resID, p, t);
PackageGroup grp = mPackageGroups.get(p);
if (grp == NULL) {
ALOGW("Bad identifier when getting bag for resource number 0x%08x", resID);
return BAD_INDEX;
}
final List<Type> typeConfigs = getOrDefault(grp.types, t, Collections.emptyList());
if (typeConfigs.isEmpty()) {
ALOGW("Type identifier 0x%x does not exist.", t + 1);
return BAD_INDEX;
}
final int NENTRY = typeConfigs.get(0).entryCount;
if (e >= (int) NENTRY) {
ALOGW("Entry identifier 0x%x is larger than entry count 0x%x", e, (int) typeConfigs.get(0).entryCount);
return BAD_INDEX;
}
// First see if we've already computed this bag...
TypeCacheEntry cacheEntry = grp.typeCacheEntries.editItemAt(t);
bag_set[] typeSet = cacheEntry.cachedBags;
// Bag not found, we need to compute it!
if (!isTruthy(typeSet)) {
// (bag_set**)calloc(NENTRY, sizeof(bag_set*));
typeSet = new bag_set[NENTRY];
// cacheEntry.cachedBags = typeSet;
}
if (kDebugTableNoisy) {
ALOGI("Building bag: %x\n", resID);
}
// Now collect all bag attributes
Entry entry = new Entry();
int err = getEntry(grp, t, e, mParams, entry);
if (err != NO_ERROR) {
return err;
}
final short entrySize = dtohs(entry.entry.size);
// const uint32_t parent = entrySize >= sizeof(ResTable_map_entry)
// ? dtohl(((const ResTable_map_entry*)entry.entry)->parent.ident) : 0;
// const uint32_t count = entrySize >= sizeof(ResTable_map_entry)
// ? dtohl(((const ResTable_map_entry*)entry.entry)->count) : 0;
ResTable_map_entry mapEntry = entrySize >= ResTable_map_entry.BASE_SIZEOF ? new ResTable_map_entry(entry.entry.myBuf(), entry.entry.myOffset()) : null;
final int parent = mapEntry != null ? dtohl(mapEntry.parent.ident) : 0;
final int count = mapEntry != null ? dtohl(mapEntry.count) : 0;
int N = count;
if (kDebugTableNoisy) {
ALOGI("Found map: size=%x parent=%x count=%d\n", entrySize, parent, count);
// If this map inherits from another, we need to start
// with its parent's values. Otherwise start out empty.
ALOGI("Creating new bag, entrySize=0x%08x, parent=0x%08x\n", entrySize, parent);
}
// This is what we are building.
bag_set set;
if (isTruthy(parent)) {
final Ref<Integer> resolvedParent = new Ref<>(parent);
// Bags encode a parent reference without using the standard
// Res_value structure. That means we must always try to
// resolve a parent reference in case it is actually a
// TYPE_DYNAMIC_REFERENCE.
err = grp.dynamicRefTable.lookupResourceId(resolvedParent);
if (err != NO_ERROR) {
ALOGE("Failed resolving bag parent id 0x%08x", parent);
return UNKNOWN_ERROR;
}
final Ref<bag_entry[]> parentBag = new Ref<>(null);
final Ref<Integer> parentTypeSpecFlags = new Ref<>(0);
final int NP = getBagLocked(resolvedParent.get(), parentBag, parentTypeSpecFlags);
final int NT = ((NP >= 0) ? NP : 0) + N;
set = new bag_set(NT);
if (NP > 0) {
set.copyFrom(parentBag.get(), NP);
set.numAttrs = NP;
if (kDebugTableNoisy) {
ALOGI("Initialized new bag with %d inherited attributes.\n", NP);
}
} else {
if (kDebugTableNoisy) {
ALOGI("Initialized new bag with no inherited attributes.\n");
}
set.numAttrs = 0;
}
set.availAttrs = NT;
set.typeSpecFlags = parentTypeSpecFlags.get();
} else {
set = new bag_set(N);
set.numAttrs = 0;
set.availAttrs = N;
set.typeSpecFlags = 0;
}
set.typeSpecFlags |= entry.specFlags;
// Now merge in the new attributes...
// int curOff = (reinterpret_cast<uintptr_t>(entry.entry) - reinterpret_cast<uintptr_t>(entry.type))
// + dtohs(entry.entry.size);
int curOff = entry.entry.myOffset() - entry.type.myOffset() + entry.entry.size;
ResTable_map map;
// bag_entry* entries = (bag_entry*)(set+1);
bag_entry[] entries = set.bag_entries;
int curEntry = 0;
int pos = 0;
if (kDebugTableNoisy) {
ALOGI("Starting with set %s, entries=%s, avail=0x%x\n", set, entries, set.availAttrs);
}
while (pos < count) {
if (kDebugTableNoisy) {
// ALOGI("Now at %s\n", curOff);
ALOGI("Now at %s\n", curEntry);
}
if (curOff > (dtohl(entry.type.header.size) - ResTable_map.SIZEOF)) {
ALOGW("ResTable_map at %d is beyond type chunk data %d", (int) curOff, dtohl(entry.type.header.size));
return BAD_TYPE;
}
// map = (const ResTable_map*)(((const uint8_t*)entry.type) + curOff);
map = new ResTable_map(entry.type.myBuf(), entry.type.myOffset() + curOff);
N++;
final Ref<Integer> newName = new Ref<>(htodl(map.name.ident));
if (!Res_INTERNALID(newName.get())) {
// other data, which would be wrong to change via a lookup.
if (grp.dynamicRefTable.lookupResourceId(newName) != NO_ERROR) {
ALOGE("Failed resolving ResTable_map name at %d with ident 0x%08x", (int) curEntry, (int) newName.get());
return UNKNOWN_ERROR;
}
}
boolean isInside;
int oldName = 0;
while ((isInside = (curEntry < set.numAttrs)) && (oldName = entries[curEntry].map.name.ident) < newName.get()) {
if (kDebugTableNoisy) {
ALOGI("#0x%x: Keeping existing attribute: 0x%08x\n", curEntry, entries[curEntry].map.name.ident);
}
curEntry++;
}
if ((!isInside) || oldName != newName.get()) {
// This is a new attribute... figure out what to do with it.
if (set.numAttrs >= set.availAttrs) {
// Need to alloc more memory...
final int newAvail = set.availAttrs + N;
// set = (bag_set[])realloc(set,
// sizeof(bag_set)
// + sizeof(bag_entry)*newAvail);
set.resizeBagEntries(newAvail);
set.availAttrs = newAvail;
// entries = (bag_entry*)(set+1);
entries = set.bag_entries;
if (kDebugTableNoisy) {
ALOGI("Reallocated set %s, entries=%s, avail=0x%x\n", set, entries, set.availAttrs);
}
}
if (isInside) {
// Going in the middle, need to make space.
// memmove(entries+curEntry+1, entries+curEntry,
// sizeof(bag_entry)*(set.numAttrs-curEntry));
System.arraycopy(entries, curEntry, entries, curEntry + 1, set.numAttrs - curEntry);
entries[curEntry] = null;
set.numAttrs++;
}
if (kDebugTableNoisy) {
ALOGI("#0x%x: Inserting new attribute: 0x%08x\n", curEntry, newName.get());
}
} else {
if (kDebugTableNoisy) {
ALOGI("#0x%x: Replacing existing attribute: 0x%08x\n", curEntry, oldName);
}
}
bag_entry cur = entries[curEntry];
if (cur == null) {
cur = entries[curEntry] = new bag_entry();
}
cur.stringBlock = entry._package_.header.index;
cur.map.name.ident = newName.get();
// cur->map.value.copyFrom_dtoh(map->value);
cur.map.value = map.value;
final Ref<Res_value> valueRef = new Ref<>(cur.map.value);
err = grp.dynamicRefTable.lookupResourceValue(valueRef);
cur.map.value = map.value = valueRef.get();
if (err != NO_ERROR) {
ALOGE("Reference item(0x%08x) in bag could not be resolved.", cur.map.value.data);
return UNKNOWN_ERROR;
}
if (kDebugTableNoisy) {
ALOGI("Setting entry #0x%x %s: block=%d, name=0x%08d, type=%d, data=0x%08x\n", curEntry, cur, cur.stringBlock, cur.map.name.ident, cur.map.value.dataType, cur.map.value.data);
}
// On to the next!
curEntry++;
pos++;
final int size = dtohs(map.value.size);
// curOff += size + sizeof(*map)-sizeof(map->value);
curOff += size + ResTable_map.SIZEOF - Res_value.SIZEOF;
}
;
if (curEntry > set.numAttrs) {
set.numAttrs = curEntry;
}
// And this is it...
typeSet[e] = set;
if (isTruthy(set)) {
if (outTypeSpecFlags != NULL) {
outTypeSpecFlags.set(set.typeSpecFlags);
}
outBag.set(set.bag_entries);
if (kDebugTableNoisy) {
ALOGI("Returning 0x%x attrs\n", set.numAttrs);
}
return set.numAttrs;
}
return BAD_INDEX;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class ResTableTheme method applyStyle.
public int applyStyle(int resID, boolean force) {
AppliedStyle newAppliedStyle = new AppliedStyle(resID, force);
if (styleDebug) {
System.out.println("Apply " + newAppliedStyle + " to " + this);
}
styles.add(newAppliedStyle);
final Ref<bag_entry[]> bag = new Ref<>(null);
final Ref<Integer> bagTypeSpecFlags = new Ref<>(0);
mTable.lock();
final int N = mTable.getBagLocked(resID, bag, bagTypeSpecFlags);
if (kDebugTableNoisy) {
ALOGV("Applying style 0x%08x to theme %s, count=%d", resID, this, N);
}
if (N < 0) {
mTable.unlock();
return N;
}
mTypeSpecFlags.set(mTypeSpecFlags.get() | bagTypeSpecFlags.get());
int curPackage = 0xffffffff;
int curPackageIndex = 0;
package_info curPI = null;
int curType = 0xffffffff;
int numEntries = 0;
theme_entry[] curEntries = null;
final int end = N;
int bagIndex = 0;
while (bagIndex < end) {
bag_entry bag_entry = bag.get()[bagIndex];
final int attrRes = bag_entry.map.name.ident;
final int p = Res_GETPACKAGE(attrRes);
final int t = Res_GETTYPE(attrRes);
final int e = Res_GETENTRY(attrRes);
if (curPackage != p) {
final int pidx = mTable.getResourcePackageIndex(attrRes);
if (pidx < 0) {
ALOGE("Style contains key with bad package: 0x%08x\n", attrRes);
bagIndex++;
continue;
}
curPackage = p;
curPackageIndex = pidx;
curPI = mPackages[pidx];
if (curPI == null) {
curPI = new package_info();
mPackages[pidx] = curPI;
}
curType = 0xffffffff;
}
if (curType != t) {
if (t > Res_MAXTYPE) {
ALOGE("Style contains key with bad type: 0x%08x\n", attrRes);
bagIndex++;
continue;
}
curType = t;
curEntries = curPI.types[t] != null ? curPI.types[t].entries : null;
if (curEntries == null) {
final PackageGroup grp = mTable.mPackageGroups.get(curPackageIndex);
final List<Type> typeList = getOrDefault(grp.types, t, Collections.emptyList());
int cnt = typeList.isEmpty() ? 0 : typeList.get(0).entryCount;
curEntries = new theme_entry[cnt];
// memset(curEntries, Res_value::TYPE_NULL, buff_size);
curPI.types[t] = new type_info();
curPI.types[t].numEntries = cnt;
curPI.types[t].entries = curEntries;
}
numEntries = curPI.types[t].numEntries;
}
if (e >= numEntries) {
ALOGE("Style contains key with bad entry: 0x%08x\n", attrRes);
bagIndex++;
continue;
}
if (curEntries[e] == null) {
curEntries[e] = new theme_entry();
}
theme_entry curEntry = curEntries[e];
if (styleDebug) {
ResourceName outName = new ResourceName();
mTable.getResourceName(attrRes, true, outName);
System.out.println(" " + outName + "(" + attrRes + ")" + " := " + bag_entry.map.value);
}
if (kDebugTableNoisy) {
ALOGV("Attr 0x%08x: type=0x%x, data=0x%08x; curType=0x%x", attrRes, bag.get()[bagIndex].map.value.dataType, bag.get()[bagIndex].map.value.data, curEntry.value.dataType);
}
if (force || (curEntry.value.dataType == TYPE_NULL && curEntry.value.data != Res_value.DATA_NULL_EMPTY)) {
curEntry.stringBlock = bag_entry.stringBlock;
curEntry.typeSpecFlags |= bagTypeSpecFlags.get();
curEntry.value = new Res_value(bag_entry.map.value);
}
bagIndex++;
}
mTable.unlock();
if (kDebugTableTheme) {
ALOGI("Applying style 0x%08x (force=%s) theme %s...\n", resID, force, this);
dumpToLog();
}
return NO_ERROR;
}
use of org.robolectric.res.android.ResourceTypes.Res_value in project robolectric by robolectric.
the class LoadedArsc method VerifyResTableEntry.
static boolean VerifyResTableEntry(ResTable_type type, int entry_offset) {
// Check that the offset is aligned.
if (isTruthy(entry_offset & 0x03)) {
logError("Entry at offset " + entry_offset + " is not 4-byte aligned.");
return false;
}
// if (entry_offset > std.numeric_limits<int>.max() - dtohl(type.entriesStart)) {
if (entry_offset > Integer.MAX_VALUE - dtohl(type.entriesStart)) {
// Overflow in offset.
logError("Entry at offset " + entry_offset + " is too large.");
return false;
}
int chunk_size = dtohl(type.header.size);
entry_offset += dtohl(type.entriesStart);
if (entry_offset > chunk_size - ResTable_entry.SIZEOF) {
logError("Entry at offset " + entry_offset + " is too large. No room for ResTable_entry.");
return false;
}
// ResTable_entry* entry = reinterpret_cast<ResTable_entry*>(
// reinterpret_cast<uint8_t*>(type) + entry_offset);
ResTable_entry entry = new ResTable_entry(type.myBuf(), type.myOffset() + entry_offset);
int entry_size = dtohs(entry.size);
// if (entry_size < sizeof(*entry)) {
if (entry_size < ResTable_entry.SIZEOF) {
logError("ResTable_entry size " + entry_size + " at offset " + entry_offset + " is too small.");
return false;
}
if (entry_size > chunk_size || entry_offset > chunk_size - entry_size) {
logError("ResTable_entry size " + entry_size + " at offset " + entry_offset + " is too large.");
return false;
}
if (entry_size < ResTable_map_entry.BASE_SIZEOF) {
// There needs to be room for one Res_value struct.
if (entry_offset + entry_size > chunk_size - Res_value.SIZEOF) {
logError("No room for Res_value after ResTable_entry at offset " + entry_offset + " for type " + (int) type.id + ".");
return false;
}
// Res_value value =
// reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(entry) + entry_size);
Res_value value = new Res_value(entry.myBuf(), entry.myOffset() + ResTable_entry.SIZEOF);
int value_size = dtohs(value.size);
if (value_size < Res_value.SIZEOF) {
logError("Res_value at offset " + entry_offset + " is too small.");
return false;
}
if (value_size > chunk_size || entry_offset + entry_size > chunk_size - value_size) {
logError("Res_value size " + value_size + " at offset " + entry_offset + " is too large.");
return false;
}
} else {
ResTable_map_entry map = new ResTable_map_entry(entry.myBuf(), entry.myOffset());
int map_entry_count = dtohl(map.count);
int map_entries_start = entry_offset + entry_size;
if (isTruthy(map_entries_start & 0x03)) {
logError("Map entries at offset " + entry_offset + " start at unaligned offset.");
return false;
}
// Each entry is sizeof(ResTable_map) big.
if (map_entry_count > ((chunk_size - map_entries_start) / ResTable_map.SIZEOF)) {
logError("Too many map entries in ResTable_map_entry at offset " + entry_offset + ".");
return false;
}
}
return true;
}
Aggregations