summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/androidfw/ResourceTypes.h3
-rw-r--r--libs/androidfw/ResourceTypes.cpp103
-rw-r--r--tools/aapt/ResourceTable.cpp168
-rw-r--r--tools/aapt/ResourceTable.h15
4 files changed, 221 insertions, 68 deletions
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 6b84494..5a28be5 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1828,6 +1828,9 @@ private:
const ResTable_config* config,
Entry* outEntry) const;
+ uint32_t findEntry(const PackageGroup* group, ssize_t typeIndex, const char16_t* name,
+ size_t nameLen, uint32_t* outTypeSpecFlags) const;
+
status_t parsePackage(
const ResTable_package* const pkg, const Header* const header);
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 6dfb4dc..d7b9765 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -4173,6 +4173,9 @@ nope:
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];
@@ -4185,64 +4188,72 @@ nope:
const size_t packageCount = group->packages.size();
for (size_t pi = 0; pi < packageCount; pi++) {
- ssize_t ti = group->packages[pi]->typeStrings.indexOfString(type, typeLen);
- if (ti < 0) {
- continue;
- }
+ const char16_t* targetType = type;
+ size_t targetTypeLen = typeLen;
- ti += group->packages[pi]->typeIdOffset;
+ do {
+ ssize_t ti = group->packages[pi]->typeStrings.indexOfString(
+ targetType, targetTypeLen);
+ if (ti < 0) {
+ continue;
+ }
- const TypeList& typeList = group->types[ti];
- if (typeList.isEmpty()) {
- TABLE_NOISY(printf("Expected type structure not found in package %s for index %d\n",
- String8(group->name).string(), ti));
- continue;
- }
+ ti += group->packages[pi]->typeIdOffset;
- const size_t typeCount = typeList.size();
- for (size_t i = 0; i < typeCount; i++) {
- const Type* t = typeList[i];
- const ssize_t ei = t->package->keyStrings.indexOfString(name, nameLen);
- if (ei < 0) {
- continue;
+ 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;
+}
- const size_t configCount = t->configs.size();
- for (size_t j = 0; j < configCount; j++) {
- const TypeVariant tv(t->configs[j]);
- for (TypeVariant::iterator iter = tv.beginEntries();
- iter != tv.endEntries();
- iter++) {
- const ResTable_entry* entry = *iter;
- if (entry == NULL) {
- continue;
- }
+uint32_t ResTable::findEntry(const PackageGroup* group, ssize_t typeIndex, const char16_t* name,
+ size_t nameLen, uint32_t* outTypeSpecFlags) const {
+ const TypeList& typeList = group->types[typeIndex];
+ const size_t typeCount = typeList.size();
+ for (size_t i = 0; i < typeCount; i++) {
+ const Type* t = typeList[i];
+ const ssize_t ei = t->package->keyStrings.indexOfString(name, nameLen);
+ if (ei < 0) {
+ continue;
+ }
- if (dtohl(entry->key.index) == (size_t) ei) {
- uint32_t resId = Res_MAKEID(group->id - 1, ti, iter.index());
- if (outTypeSpecFlags) {
- Entry result;
- if (getEntry(group, ti, iter.index(), NULL, &result) != NO_ERROR) {
- ALOGW("Failed to find spec flags for %s:%s/%s (0x%08x)",
- String8(group->name).string(),
- String8(String16(type, typeLen)).string(),
- String8(String16(name, nameLen)).string(),
- resId);
- return 0;
- }
- *outTypeSpecFlags = result.specFlags;
+ const size_t configCount = t->configs.size();
+ for (size_t j = 0; j < configCount; j++) {
+ const TypeVariant tv(t->configs[j]);
+ for (TypeVariant::iterator iter = tv.beginEntries();
+ iter != tv.endEntries();
+ iter++) {
+ const ResTable_entry* entry = *iter;
+ if (entry == NULL) {
+ continue;
+ }
- if (fakePublic) {
- *outTypeSpecFlags |= ResTable_typeSpec::SPEC_PUBLIC;
- }
- }
- return resId;
+ if (dtohl(entry->key.index) == (size_t) ei) {
+ uint32_t resId = Res_MAKEID(group->id - 1, typeIndex, iter.index());
+ if (outTypeSpecFlags) {
+ Entry result;
+ if (getEntry(group, typeIndex, iter.index(), NULL, &result) != NO_ERROR) {
+ ALOGW("Failed to find spec flags for 0x%08x", resId);
+ return 0;
}
+ *outTypeSpecFlags = result.specFlags;
}
+ return resId;
}
}
}
- break;
}
return 0;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index bdc6586..6d03311 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -12,6 +12,7 @@
#include "ResourceIdCache.h"
#include "SdkConstants.h"
+#include <algorithm>
#include <androidfw/ResourceTypes.h>
#include <utils/ByteOrder.h>
#include <utils/TypeHelpers.h>
@@ -19,6 +20,8 @@
#define NOISY(x) //x
+static const char* kAttrPrivateType = "^attr-private";
+
status_t compileXmlFile(const Bundle* bundle,
const sp<AaptAssets>& assets,
const String16& resourceName,
@@ -2131,8 +2134,16 @@ uint32_t ResourceTable::getResId(const String16& package,
if (p == NULL) return 0;
sp<Type> t = p->getTypes().valueFor(type);
if (t == NULL) return 0;
- sp<ConfigList> c = t->getConfigs().valueFor(name);
- if (c == NULL) return 0;
+ sp<ConfigList> c = t->getConfigs().valueFor(name);
+ if (c == NULL) {
+ if (type != String16("attr")) {
+ return 0;
+ }
+ t = p->getTypes().valueFor(String16(kAttrPrivateType));
+ if (t == NULL) return 0;
+ c = t->getConfigs().valueFor(name);
+ if (c == NULL) return 0;
+ }
int32_t ei = c->getEntryIndex();
if (ei < 0) return 0;
@@ -2266,7 +2277,15 @@ uint32_t ResourceTable::getCustomResource(
sp<Type> t = p->getTypes().valueFor(type);
if (t == NULL) return 0;
sp<ConfigList> c = t->getConfigs().valueFor(name);
- if (c == NULL) return 0;
+ if (c == NULL) {
+ if (type != String16("attr")) {
+ return 0;
+ }
+ t = p->getTypes().valueFor(String16(kAttrPrivateType));
+ if (t == NULL) return 0;
+ c = t->getConfigs().valueFor(name);
+ if (c == NULL) return 0;
+ }
int32_t ei = c->getEntryIndex();
if (ei < 0) return 0;
return getResId(p, t, ei);
@@ -2470,6 +2489,10 @@ status_t ResourceTable::assignResourceIds()
continue;
}
+ if (mPackageType == System) {
+ p->movePrivateAttrs();
+ }
+
// This has no sense for packages being built as AppFeature (aka with a non-zero offset).
status_t err = p->applyPublicTypeOrder();
if (err != NO_ERROR && firstError == NO_ERROR) {
@@ -2540,15 +2563,20 @@ status_t ResourceTable::assignResourceIds()
}
}
+
// Assign resource IDs to keys in bags...
for (size_t ti = 0; ti < typeCount; ti++) {
sp<Type> t = p->getOrderedTypes().itemAt(ti);
if (t == NULL) {
continue;
}
+
const size_t N = t->getOrderedConfigs().size();
for (size_t ci=0; ci<N; ci++) {
sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
+ if (c == NULL) {
+ continue;
+ }
//printf("Ordered config #%d: %p\n", ci, c.get());
const size_t N = c->getEntries().size();
for (size_t ei=0; ei<N; ei++) {
@@ -2586,9 +2614,15 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
if (t == NULL) {
continue;
}
+
const size_t N = t->getOrderedConfigs().size();
- sp<AaptSymbols> typeSymbols =
- outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ sp<AaptSymbols> typeSymbols;
+ if (t->getName() == String16(kAttrPrivateType)) {
+ typeSymbols = outSymbols->addNestedSymbol(String8("attr"), t->getPos());
+ } else {
+ typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ }
+
if (typeSymbols == NULL) {
return UNKNOWN_ERROR;
}
@@ -2954,6 +2988,10 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
for (size_t ei=0; ei<N; ei++) {
sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
+ if (cl == NULL) {
+ continue;
+ }
+
if (cl->getPublic()) {
typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC);
}
@@ -2984,12 +3022,13 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
// We need to write one type chunk for each configuration for
// which we have entries in this type.
- const size_t NC = t->getUniqueConfigs().size();
+ const SortedVector<ConfigDescription> uniqueConfigs(t->getUniqueConfigs());
+ const size_t NC = uniqueConfigs.size();
const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N;
for (size_t ci=0; ci<NC; ci++) {
- ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
+ const ConfigDescription& config = uniqueConfigs[ci];
NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
"orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d "
@@ -3061,7 +3100,10 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
// Build the entries inside of this type.
for (size_t ei=0; ei<N; ei++) {
sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei);
- sp<Entry> e = cl->getEntries().valueFor(config);
+ sp<Entry> e = NULL;
+ if (cl != NULL) {
+ e = cl->getEntries().valueFor(config);
+ }
// Set the offset for this entry in its type.
uint32_t* index = (uint32_t*)
@@ -3096,9 +3138,11 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>&
for (size_t i = 0; i < N; ++i) {
if (!validResources[i]) {
sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
- fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
- String8(typeName).string(), String8(c->getName()).string(),
- Res_MAKEID(p->getAssignedId() - 1, ti, i));
+ if (c != NULL) {
+ fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
+ String8(typeName).string(), String8(c->getName()).string(),
+ Res_MAKEID(p->getAssignedId() - 1, ti, i));
+ }
missing_entry = true;
}
}
@@ -3807,11 +3851,45 @@ sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
*/
}
- mUniqueConfigs.add(cdesc);
-
return e;
}
+sp<ResourceTable::ConfigList> ResourceTable::Type::removeEntry(const String16& entry) {
+ ssize_t idx = mConfigs.indexOfKey(entry);
+ if (idx < 0) {
+ return NULL;
+ }
+
+ sp<ConfigList> removed = mConfigs.valueAt(idx);
+ mConfigs.removeItemsAt(idx);
+
+ Vector<sp<ConfigList> >::iterator iter = std::find(
+ mOrderedConfigs.begin(), mOrderedConfigs.end(), removed);
+ if (iter != mOrderedConfigs.end()) {
+ mOrderedConfigs.erase(iter);
+ }
+
+ mPublic.removeItem(entry);
+ return removed;
+}
+
+SortedVector<ConfigDescription> ResourceTable::Type::getUniqueConfigs() const {
+ SortedVector<ConfigDescription> unique;
+ const size_t entryCount = mOrderedConfigs.size();
+ for (size_t i = 0; i < entryCount; i++) {
+ if (mOrderedConfigs[i] == NULL) {
+ continue;
+ }
+ const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configs =
+ mOrderedConfigs[i]->getEntries();
+ const size_t configCount = configs.size();
+ for (size_t j = 0; j < configCount; j++) {
+ unique.add(configs.keyAt(j));
+ }
+ }
+ return unique;
+}
+
status_t ResourceTable::Type::applyPublicEntryOrder()
{
size_t N = mOrderedConfigs.size();
@@ -3838,11 +3916,10 @@ status_t ResourceTable::Type::applyPublicEntryOrder()
//printf("#%d: \"%s\"\n", i, String8(e->getName()).string());
if (e->getName() == name) {
if (idx >= (int32_t)mOrderedConfigs.size()) {
- p.sourcePos.error("Public entry identifier 0x%x entry index "
- "is larger than available symbols (index %d, total symbols %d).\n",
- p.ident, idx, mOrderedConfigs.size());
- hasError = true;
- } else if (mOrderedConfigs.itemAt(idx) == NULL) {
+ mOrderedConfigs.resize(idx + 1);
+ }
+
+ if (mOrderedConfigs.itemAt(idx) == NULL) {
e->setPublic(true);
e->setPublicSourcePos(p.sourcePos);
mOrderedConfigs.replaceAt(e, idx);
@@ -4018,6 +4095,61 @@ status_t ResourceTable::Package::applyPublicTypeOrder()
return NO_ERROR;
}
+void ResourceTable::Package::movePrivateAttrs() {
+ sp<Type> attr = mTypes.valueFor(String16("attr"));
+ if (attr == NULL) {
+ // Nothing to do.
+ return;
+ }
+
+ Vector<sp<ConfigList> > privateAttrs;
+
+ bool hasPublic = false;
+ const Vector<sp<ConfigList> >& configs = attr->getOrderedConfigs();
+ const size_t configCount = configs.size();
+ for (size_t i = 0; i < configCount; i++) {
+ if (configs[i] == NULL) {
+ continue;
+ }
+
+ if (attr->isPublic(configs[i]->getName())) {
+ hasPublic = true;
+ } else {
+ privateAttrs.add(configs[i]);
+ }
+ }
+
+ // Only if we have public attributes do we create a separate type for
+ // private attributes.
+ if (!hasPublic) {
+ return;
+ }
+
+ // Create a new type for private attributes.
+ sp<Type> privateAttrType = getType(String16(kAttrPrivateType), SourcePos());
+
+ const size_t privateAttrCount = privateAttrs.size();
+ for (size_t i = 0; i < privateAttrCount; i++) {
+ const sp<ConfigList>& cl = privateAttrs[i];
+
+ // Remove the private attributes from their current type.
+ attr->removeEntry(cl->getName());
+
+ // Add it to the new type.
+ const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries = cl->getEntries();
+ const size_t entryCount = entries.size();
+ for (size_t j = 0; j < entryCount; j++) {
+ const sp<Entry>& oldEntry = entries[j];
+ sp<Entry> entry = privateAttrType->getEntry(
+ cl->getName(), oldEntry->getPos(), &entries.keyAt(j));
+ *entry = *oldEntry;
+ }
+
+ // Move the symbols to the new type.
+
+ }
+}
+
sp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
{
if (package != mAssetsPackage) {
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index db392c8..81590bc 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -470,6 +470,14 @@ public:
bool overlay = false,
bool autoAddOverlay = false);
+ bool isPublic(const String16& entry) const {
+ return mPublic.indexOfKey(entry) >= 0;
+ }
+
+ sp<ConfigList> removeEntry(const String16& entry);
+
+ SortedVector<ConfigDescription> getUniqueConfigs() const;
+
const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; }
int32_t getPublicIndex() const { return mPublicIndex; }
@@ -479,19 +487,16 @@ public:
status_t applyPublicEntryOrder();
- const SortedVector<ConfigDescription>& getUniqueConfigs() const { return mUniqueConfigs; }
-
const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
-
const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; }
const SourcePos& getPos() const { return mPos; }
+
private:
String16 mName;
SourcePos* mFirstPublicSourcePos;
DefaultKeyedVector<String16, Public> mPublic;
- SortedVector<ConfigDescription> mUniqueConfigs;
DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
Vector<sp<ConfigList> > mOrderedConfigs;
SortedVector<String16> mCanAddEntries;
@@ -527,6 +532,8 @@ public:
const DefaultKeyedVector<String16, sp<Type> >& getTypes() const { return mTypes; }
const Vector<sp<Type> >& getOrderedTypes() const { return mOrderedTypes; }
+ void movePrivateAttrs();
+
private:
status_t setStrings(const sp<AaptFile>& data,
ResStringPool* strings,