summaryrefslogtreecommitdiffstats
path: root/tools/aapt
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-01-14 20:47:47 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-01-14 20:47:47 +0000
commit5c61dfc25fed75a436dc32b0fb18854bde0c4cea (patch)
tree0eae0de74a065094073690f7060d7a0ebf137b8b /tools/aapt
parent4d5e761a34c73a700757ade349e9a05b3335f617 (diff)
parente488ce8668538b45c586eba21f5bca288d749686 (diff)
downloadframeworks_base-5c61dfc25fed75a436dc32b0fb18854bde0c4cea.zip
frameworks_base-5c61dfc25fed75a436dc32b0fb18854bde0c4cea.tar.gz
frameworks_base-5c61dfc25fed75a436dc32b0fb18854bde0c4cea.tar.bz2
am e488ce86: am 94e30215: Merge "AAPT: Handle all old unversioned attribute usage" into lmp-mr1-dev
* commit 'e488ce8668538b45c586eba21f5bca288d749686': AAPT: Handle all old unversioned attribute usage
Diffstat (limited to 'tools/aapt')
-rw-r--r--tools/aapt/ResourceTable.cpp172
-rw-r--r--tools/aapt/ResourceTable.h2
-rw-r--r--tools/aapt/SdkConstants.h1
3 files changed, 127 insertions, 48 deletions
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 5d15ffc..6fbc17c 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4363,38 +4363,80 @@ bool ResourceTable::getItemValue(
}
/**
- * Returns true if the given attribute ID comes from
- * a platform version from or after L.
+ * Returns the SDK version at which the attribute was
+ * made public, or -1 if the resource ID is not an attribute
+ * or is not public.
*/
-bool ResourceTable::isAttributeFromL(uint32_t attrId) {
- const uint32_t baseAttrId = 0x010103f7;
- if ((attrId & 0xffff0000) != (baseAttrId & 0xffff0000)) {
- return false;
+int ResourceTable::getPublicAttributeSdkLevel(uint32_t attrId) const {
+ if (Res_GETPACKAGE(attrId) + 1 != 0x01 || Res_GETTYPE(attrId) + 1 != 0x01) {
+ return -1;
}
uint32_t specFlags;
if (!mAssets->getIncludedResources().getResourceFlags(attrId, &specFlags)) {
- return false;
+ return -1;
+ }
+
+ if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) {
+ return -1;
+ }
+
+ const size_t entryId = Res_GETENTRY(attrId);
+ if (entryId <= 0x021c) {
+ return 1;
+ } else if (entryId <= 0x021d) {
+ return 2;
+ } else if (entryId <= 0x0269) {
+ return SDK_CUPCAKE;
+ } else if (entryId <= 0x028d) {
+ return SDK_DONUT;
+ } else if (entryId <= 0x02ad) {
+ return SDK_ECLAIR;
+ } else if (entryId <= 0x02b3) {
+ return SDK_ECLAIR_0_1;
+ } else if (entryId <= 0x02b5) {
+ return SDK_ECLAIR_MR1;
+ } else if (entryId <= 0x02bd) {
+ return SDK_FROYO;
+ } else if (entryId <= 0x02cb) {
+ return SDK_GINGERBREAD;
+ } else if (entryId <= 0x0361) {
+ return SDK_HONEYCOMB;
+ } else if (entryId <= 0x0366) {
+ return SDK_HONEYCOMB_MR1;
+ } else if (entryId <= 0x03a6) {
+ return SDK_HONEYCOMB_MR2;
+ } else if (entryId <= 0x03ae) {
+ return SDK_JELLY_BEAN;
+ } else if (entryId <= 0x03cc) {
+ return SDK_JELLY_BEAN_MR1;
+ } else if (entryId <= 0x03da) {
+ return SDK_JELLY_BEAN_MR2;
+ } else if (entryId <= 0x03f1) {
+ return SDK_KITKAT;
+ } else if (entryId <= 0x03f6) {
+ return SDK_KITKAT_WATCH;
+ } else if (entryId <= 0x04ce) {
+ return SDK_LOLLIPOP;
+ } else {
+ // Anything else is marked as defined in
+ // SDK_LOLLIPOP_MR1 since after this
+ // version no attribute compat work
+ // needs to be done.
+ return SDK_LOLLIPOP_MR1;
}
-
- return (specFlags & ResTable_typeSpec::SPEC_PUBLIC) != 0 &&
- (attrId & 0x0000ffff) >= (baseAttrId & 0x0000ffff);
}
-static bool isMinSdkVersionLOrAbove(const Bundle* bundle) {
- if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) {
- const char firstChar = bundle->getMinSdkVersion()[0];
- if (firstChar >= 'L' && firstChar <= 'Z') {
- // L is the code-name for the v21 release.
- return true;
- }
-
- const int minSdk = atoi(bundle->getMinSdkVersion());
- if (minSdk >= SDK_LOLLIPOP) {
- return true;
- }
+/**
+ * First check the Manifest, then check the command line flag.
+ */
+static int getMinSdkVersion(const Bundle* bundle) {
+ if (bundle->getManifestMinSdkVersion() != NULL && strlen(bundle->getManifestMinSdkVersion()) > 0) {
+ return atoi(bundle->getManifestMinSdkVersion());
+ } else if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) {
+ return atoi(bundle->getMinSdkVersion());
}
- return false;
+ return 0;
}
/**
@@ -4440,9 +4482,10 @@ static bool isMinSdkVersionLOrAbove(const Bundle* bundle) {
* attribute will be respected.
*/
status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
- if (isMinSdkVersionLOrAbove(bundle)) {
- // If this app will only ever run on L+ devices,
- // we don't need to do any compatibility work.
+ const int minSdk = getMinSdkVersion(bundle);
+ if (minSdk >= SDK_LOLLIPOP_MR1) {
+ // Lollipop MR1 and up handles public attributes differently, no
+ // need to do any compat modifications.
return NO_ERROR;
}
@@ -4481,20 +4524,19 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
}
const ConfigDescription& config = entries.keyAt(ei);
- if (config.sdkVersion >= SDK_LOLLIPOP) {
- // We don't need to do anything if the resource is
- // already qualified for version 21 or higher.
+ if (config.sdkVersion >= SDK_LOLLIPOP_MR1) {
continue;
}
- Vector<String16> attributesToRemove;
+ KeyedVector<int, Vector<String16> > attributesToRemove;
const KeyedVector<String16, Item>& bag = e->getBag();
const size_t bagCount = bag.size();
for (size_t bi = 0; bi < bagCount; bi++) {
const Item& item = bag.valueAt(bi);
const uint32_t attrId = getResId(bag.keyAt(bi), &attr16);
- if (isAttributeFromL(attrId)) {
- attributesToRemove.add(bag.keyAt(bi));
+ const int sdkLevel = getPublicAttributeSdkLevel(attrId);
+ if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) {
+ AaptUtil::appendValue(attributesToRemove, sdkLevel, bag.keyAt(bi));
}
}
@@ -4502,16 +4544,41 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
continue;
}
- // Duplicate the entry under the same configuration
- // but with sdkVersion == SDK_LOLLIPOP.
- ConfigDescription newConfig(config);
- newConfig.sdkVersion = SDK_LOLLIPOP;
- entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >(
- newConfig, new Entry(*e)));
+ const size_t sdkCount = attributesToRemove.size();
+ for (size_t i = 0; i < sdkCount; i++) {
+ const int sdkLevel = attributesToRemove.keyAt(i);
+
+ // Duplicate the entry under the same configuration
+ // but with sdkVersion == sdkLevel.
+ ConfigDescription newConfig(config);
+ newConfig.sdkVersion = sdkLevel;
+
+ sp<Entry> newEntry = new Entry(*e);
+
+ // Remove all items that have a higher SDK level than
+ // the one we are synthesizing.
+ for (size_t j = 0; j < sdkCount; j++) {
+ if (j == i) {
+ continue;
+ }
+
+ if (attributesToRemove.keyAt(j) > sdkLevel) {
+ const size_t attrCount = attributesToRemove[j].size();
+ for (size_t k = 0; k < attrCount; k++) {
+ newEntry->removeFromBag(attributesToRemove[j][k]);
+ }
+ }
+ }
+
+ entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >(
+ newConfig, newEntry));
+ }
// Remove the attribute from the original.
for (size_t i = 0; i < attributesToRemove.size(); i++) {
- e->removeFromBag(attributesToRemove[i]);
+ for (size_t j = 0; j < attributesToRemove[i].size(); j++) {
+ e->removeFromBag(attributesToRemove[i][j]);
+ }
}
}
@@ -4528,7 +4595,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
if (bundle->getVerbose()) {
entriesToAdd[i].value->getPos()
.printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
- SDK_LOLLIPOP,
+ entriesToAdd[i].key.sdkVersion,
String8(p->getName()).string(),
String8(t->getName()).string(),
String8(entriesToAdd[i].value->getName()).string(),
@@ -4551,17 +4618,23 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
const String16& resourceName,
const sp<AaptFile>& target,
const sp<XMLNode>& root) {
- if (isMinSdkVersionLOrAbove(bundle)) {
+ const int minSdk = getMinSdkVersion(bundle);
+ if (minSdk >= SDK_LOLLIPOP_MR1) {
+ // Lollipop MR1 and up handles public attributes differently, no
+ // need to do any compat modifications.
return NO_ERROR;
}
- if (target->getResourceType() == "" || target->getGroupEntry().toParams().sdkVersion >= SDK_LOLLIPOP) {
+ const ConfigDescription config(target->getGroupEntry().toParams());
+ if (target->getResourceType() == "" || config.sdkVersion >= SDK_LOLLIPOP_MR1) {
// Skip resources that have no type (AndroidManifest.xml) or are already version qualified with v21
// or higher.
return NO_ERROR;
}
sp<XMLNode> newRoot = NULL;
+ ConfigDescription newConfig(target->getGroupEntry().toParams());
+ newConfig.sdkVersion = SDK_LOLLIPOP_MR1;
Vector<sp<XMLNode> > nodesToVisit;
nodesToVisit.push(root);
@@ -4572,11 +4645,19 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes();
for (size_t i = 0; i < attrs.size(); i++) {
const XMLNode::attribute_entry& attr = attrs[i];
- if (isAttributeFromL(attr.nameResId)) {
+ const int sdkLevel = getPublicAttributeSdkLevel(attr.nameResId);
+ if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) {
if (newRoot == NULL) {
newRoot = root->clone();
}
+ // Find the smallest sdk version that we need to synthesize for
+ // and do that one. Subsequent versions will be processed on
+ // the next pass.
+ if (sdkLevel < newConfig.sdkVersion) {
+ newConfig.sdkVersion = sdkLevel;
+ }
+
if (bundle->getVerbose()) {
SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
"removing attribute %s%s%s from <%s>",
@@ -4602,9 +4683,6 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
return NO_ERROR;
}
- ConfigDescription newConfig(target->getGroupEntry().toParams());
- newConfig.sdkVersion = SDK_LOLLIPOP;
-
// Look to see if we already have an overriding v21 configuration.
sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()),
String16(target->getResourceType()), resourceName);
@@ -4621,7 +4699,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,
if (bundle->getVerbose()) {
SourcePos(target->getSourceFile(), -1).printf(
"using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
- SDK_LOLLIPOP,
+ newConfig.sdkVersion,
mAssets->getPackage().string(),
newFile->getResourceType().string(),
String8(resourceName).string(),
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 81590bc..eef0ae1 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -575,7 +575,7 @@ private:
const Item* getItem(uint32_t resID, uint32_t attrID) const;
bool getItemValue(uint32_t resID, uint32_t attrID,
Res_value* outValue);
- bool isAttributeFromL(uint32_t attrId);
+ int getPublicAttributeSdkLevel(uint32_t attrId) const;
String16 mAssetsPackage;
diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h
index 7fd1030..4e0fe10 100644
--- a/tools/aapt/SdkConstants.h
+++ b/tools/aapt/SdkConstants.h
@@ -37,6 +37,7 @@ enum {
SDK_KITKAT = 19,
SDK_KITKAT_WATCH = 20,
SDK_LOLLIPOP = 21,
+ SDK_LOLLIPOP_MR1 = 22,
};
#endif // H_AAPT_SDK_CONSTANTS