in libresource/ResourceTypes.cpp [4253:4406]
uint32_t ResTable::identifierForName(const char16_t* name, size_t nameLen,
const char16_t* type, size_t typeLen,
const char16_t* package,
size_t packageLen,
uint32_t* outTypeSpecFlags) const
{
if (kDebugTableSuperNoisy) {
printf("Identifier for name: error=%d\n", mError);
}
// Check for internal resource identifier as the very first thing, so
// that we will always find them even when there are no resources.
if (name[0] == '^') {
const int N = (sizeof(ID_NAMES)/sizeof(ID_NAMES[0]));
size_t len;
for (int i=0; i<N; i++) {
const id_name_map* m = ID_NAMES + i;
len = m->len;
if (len != nameLen) {
continue;
}
for (size_t j=1; j<len; j++) {
if (m->name[j] != name[j]) {
goto nope;
}
}
if (outTypeSpecFlags) {
*outTypeSpecFlags = ResTable_typeSpec::SPEC_PUBLIC;
}
return m->id;
nope:
;
}
if (nameLen > 7) {
if (name[1] == 'i' && name[2] == 'n'
&& name[3] == 'd' && name[4] == 'e' && name[5] == 'x'
&& name[6] == '_') {
int index = atoi(String8(name + 7, nameLen - 7).string());
if (Res_CHECKID(index)) {
ALOGW("Array resource index: %d is too large.",
index);
return 0;
}
if (outTypeSpecFlags) {
*outTypeSpecFlags = ResTable_typeSpec::SPEC_PUBLIC;
}
return Res_MAKEARRAY(index);
}
}
return 0;
}
if (mError != NO_ERROR) {
return 0;
}
bool fakePublic = false;
// Figure out the package and type we are looking in...
const char16_t* packageEnd = NULL;
const char16_t* typeEnd = NULL;
const char16_t* const nameEnd = name+nameLen;
const char16_t* p = name;
while (p < nameEnd) {
if (*p == ':') packageEnd = p;
else if (*p == '/') typeEnd = p;
p++;
}
if (*name == '@') {
name++;
if (*name == '*') {
fakePublic = true;
name++;
}
}
if (name >= nameEnd) {
return 0;
}
if (packageEnd) {
package = name;
packageLen = packageEnd-name;
name = packageEnd+1;
} else if (!package) {
return 0;
}
if (typeEnd) {
type = name;
typeLen = typeEnd-name;
name = typeEnd+1;
} else if (!type) {
return 0;
}
if (name >= nameEnd) {
return 0;
}
nameLen = nameEnd-name;
if (kDebugTableNoisy) {
printf("Looking for identifier: type=%s, name=%s, package=%s\n",
String8(type, typeLen).string(),
String8(name, nameLen).string(),
String8(package, packageLen).string());
}
const String16 attr("attr");
const String16 attrPrivate("^attr-private");
const size_t NG = mPackageGroups.size();
for (size_t ig=0; ig<NG; ig++) {
const PackageGroup* group = mPackageGroups[ig];
if (strzcmp16(package, packageLen,
group->name.string(), group->name.size())) {
if (kDebugTableNoisy) {
printf("Skipping package group: %s\n", String8(group->name).string());
}
continue;
}
const size_t packageCount = group->packages.size();
for (size_t pi = 0; pi < packageCount; pi++) {
const char16_t* targetType = type;
size_t targetTypeLen = typeLen;
do {
ssize_t ti = group->packages[pi]->typeStrings.indexOfString(
targetType, targetTypeLen);
if (ti < 0) {
continue;
}
ti += group->packages[pi]->typeIdOffset;
const uint32_t identifier = findEntry(group, ti, name, nameLen,
outTypeSpecFlags);
if (identifier != 0) {
if (fakePublic && outTypeSpecFlags) {
*outTypeSpecFlags |= ResTable_typeSpec::SPEC_PUBLIC;
}
return identifier;
}
} while (strzcmp16(attr.string(), attr.size(), targetType, targetTypeLen) == 0
&& (targetType = attrPrivate.string())
&& (targetTypeLen = attrPrivate.size())
);
}
break;
}
return 0;
}