Stamp platform version code into app Apks
The versionCode of theframework resources that an app is built against
gets stamped inside an app's AndroidManifest.xml in the <manifest>
tag as "platformBuildVersionCode" and "platformBuildVersionName"
attributes.
Bug:17207635
Change-Id: Id573c3dffcbca38eec9c0eb3e89f4a547e3361d3
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 11568d2..c65efe4 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1557,7 +1557,7 @@
};
const char16_t* valueToString(const Res_value* value, size_t stringBlock,
char16_t tmpBuffer[TMP_BUFFER_SIZE],
- size_t* outLen);
+ size_t* outLen) const;
struct bag_entry {
ssize_t stringBlock;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3f014ef..90879dd 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3728,7 +3728,7 @@
const char16_t* ResTable::valueToString(
const Res_value* value, size_t stringBlock,
- char16_t /*tmpBuffer*/ [TMP_BUFFER_SIZE], size_t* outLen)
+ char16_t /*tmpBuffer*/ [TMP_BUFFER_SIZE], size_t* outLen) const
{
if (!value) {
return NULL;
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index b44e2d1..117fc24 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1594,6 +1594,11 @@
return mIncludedAssets.getResources(false);
}
+AssetManager& AaptAssets::getAssetManager()
+{
+ return mIncludedAssets;
+}
+
void AaptAssets::print(const String8& prefix) const
{
String8 innerPrefix(prefix);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 0c2576a..3fc9f81 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -561,6 +561,7 @@
status_t buildIncludedResources(Bundle* bundle);
status_t addIncludedResources(const sp<AaptFile>& file);
const ResTable& getIncludedResources() const;
+ AssetManager& getAssetManager();
void print(const String8& prefix) const;
diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp
new file mode 100644
index 0000000..708e405
--- /dev/null
+++ b/tools/aapt/AaptXml.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+
+#include "AaptXml.h"
+
+using namespace android;
+
+namespace AaptXml {
+
+static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
+ String8* outError) {
+ Res_value value;
+ if (tree.getAttributeValue(attrIndex, &value) < 0) {
+ if (outError != NULL) {
+ *outError = "could not find attribute at index";
+ }
+ return String8();
+ }
+
+ if (value.dataType != Res_value::TYPE_STRING) {
+ if (outError != NULL) {
+ *outError = "attribute is not a string value";
+ }
+ return String8();
+ }
+
+ size_t len;
+ const uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
+ return str ? String8(str, len) : String8();
+}
+
+static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
+ int32_t defValue, String8* outError) {
+ Res_value value;
+ if (tree.getAttributeValue(attrIndex, &value) < 0) {
+ if (outError != NULL) {
+ *outError = "could not find attribute at index";
+ }
+ return defValue;
+ }
+
+ if (value.dataType < Res_value::TYPE_FIRST_INT
+ || value.dataType > Res_value::TYPE_LAST_INT) {
+ if (outError != NULL) {
+ *outError = "attribute is not an integer value";
+ }
+ return defValue;
+ }
+ return value.data;
+}
+
+
+ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
+ size_t attrCount = tree.getAttributeCount();
+ for (size_t i = 0; i < attrCount; i++) {
+ if (tree.getAttributeNameResID(i) == attrRes) {
+ return (ssize_t)i;
+ }
+ }
+ return -1;
+}
+
+String8 getAttribute(const ResXMLTree& tree, const char* ns,
+ const char* attr, String8* outError) {
+ ssize_t idx = tree.indexOfAttribute(ns, attr);
+ if (idx < 0) {
+ return String8();
+ }
+ return getStringAttributeAtIndex(tree, idx, outError);
+}
+
+String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ return String8();
+ }
+ return getStringAttributeAtIndex(tree, idx, outError);
+}
+
+String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
+ uint32_t attrRes, String8* outError) {
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ return String8();
+ }
+ Res_value value;
+ if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
+ if (value.dataType == Res_value::TYPE_STRING) {
+ size_t len;
+ const uint16_t* str = tree.getAttributeStringValue(idx, &len);
+ return str ? String8(str, len) : String8();
+ }
+ resTable.resolveReference(&value, 0);
+ if (value.dataType != Res_value::TYPE_STRING) {
+ if (outError != NULL) {
+ *outError = "attribute is not a string value";
+ }
+ return String8();
+ }
+ }
+ size_t len;
+ const Res_value* value2 = &value;
+ const char16_t* str = resTable.valueToString(value2, 0, NULL, &len);
+ return str ? String8(str, len) : String8();
+}
+
+int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
+ const char* attr, int32_t defValue, String8* outError) {
+ ssize_t idx = tree.indexOfAttribute(ns, attr);
+ if (idx < 0) {
+ return defValue;
+ }
+ return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
+}
+
+int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
+ String8* outError) {
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ return defValue;
+ }
+ return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
+}
+
+int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
+ uint32_t attrRes, int32_t defValue, String8* outError) {
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ return defValue;
+ }
+ Res_value value;
+ if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
+ if (value.dataType == Res_value::TYPE_REFERENCE) {
+ resTable.resolveReference(&value, 0);
+ }
+ if (value.dataType < Res_value::TYPE_FIRST_INT
+ || value.dataType > Res_value::TYPE_LAST_INT) {
+ if (outError != NULL) {
+ *outError = "attribute is not an integer value";
+ }
+ return defValue;
+ }
+ }
+ return value.data;
+}
+
+void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
+ uint32_t attrRes, Res_value* outValue, String8* outError) {
+ ssize_t idx = indexOfAttribute(tree, attrRes);
+ if (idx < 0) {
+ if (outError != NULL) {
+ *outError = "attribute could not be found";
+ }
+ return;
+ }
+ if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
+ if (outValue->dataType == Res_value::TYPE_REFERENCE) {
+ resTable.resolveReference(outValue, 0);
+ }
+ // The attribute was found and was resolved if need be.
+ return;
+ }
+ if (outError != NULL) {
+ *outError = "error getting resolved resource attribute";
+ }
+}
+
+} // namespace AaptXml
diff --git a/tools/aapt/AaptXml.h b/tools/aapt/AaptXml.h
new file mode 100644
index 0000000..16977f3
--- /dev/null
+++ b/tools/aapt/AaptXml.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __AAPT_XML_H
+#define __AAPT_XML_H
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+
+/**
+ * Utility methods for dealing with ResXMLTree.
+ */
+namespace AaptXml {
+
+/**
+ * Returns the index of the attribute, or < 0 if it was not found.
+ */
+ssize_t indexOfAttribute(const android::ResXMLTree& tree, uint32_t attrRes);
+
+/**
+ * Returns the string value for the specified attribute.
+ * The string must be present in the ResXMLTree's string pool (inline in the XML).
+ */
+android::String8 getAttribute(const android::ResXMLTree& tree, const char* ns,
+ const char* attr, android::String8* outError = NULL);
+
+/**
+ * Returns the string value for the specified attribute, or an empty string
+ * if the attribute does not exist.
+ * The string must be present in the ResXMLTree's string pool (inline in the XML).
+ */
+android::String8 getAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+ android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+int32_t getIntegerAttribute(const android::ResXMLTree& tree, const char* ns,
+ const char* attr, int32_t defValue = -1, android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+inline int32_t getIntegerAttribute(const android::ResXMLTree& tree, const char* ns,
+ const char* attr, android::String8* outError) {
+ return getIntegerAttribute(tree, ns, attr, -1, outError);
+}
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+int32_t getIntegerAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+ int32_t defValue = -1, android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer must be declared inline in the XML.
+ */
+inline int32_t getIntegerAttribute(const android::ResXMLTree& tree, uint32_t attrRes,
+ android::String8* outError) {
+ return getIntegerAttribute(tree, attrRes, -1, outError);
+}
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer may be a resource in the supplied ResTable.
+ */
+int32_t getResolvedIntegerAttribute(const android::ResTable& resTable,
+ const android::ResXMLTree& tree, uint32_t attrRes, int32_t defValue = -1,
+ android::String8* outError = NULL);
+
+/**
+ * Returns the integer value for the specified attribute, or the default value
+ * if the attribute does not exist.
+ * The integer may be a resource in the supplied ResTable.
+ */
+inline int32_t getResolvedIntegerAttribute(const android::ResTable& resTable,
+ const android::ResXMLTree& tree, uint32_t attrRes,
+ android::String8* outError) {
+ return getResolvedIntegerAttribute(resTable, tree, attrRes, -1, outError);
+}
+
+/**
+ * Returns the string value for the specified attribute, or an empty string
+ * if the attribute does not exist.
+ * The string may be a resource in the supplied ResTable.
+ */
+android::String8 getResolvedAttribute(const android::ResTable& resTable,
+ const android::ResXMLTree& tree, uint32_t attrRes,
+ android::String8* outError = NULL);
+
+/**
+ * Returns the resource for the specified attribute in the outValue parameter.
+ * The resource may be a resource in the supplied ResTable.
+ */
+void getResolvedResourceAttribute(const android::ResTable& resTable,
+ const android::ResXMLTree& tree, uint32_t attrRes, android::Res_value* outValue,
+ android::String8* outError = NULL);
+
+} // namespace AaptXml
+
+#endif // __AAPT_XML_H
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 4ce5045..2cbabe1 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -28,6 +28,7 @@
AaptAssets.cpp \
AaptConfig.cpp \
AaptUtil.cpp \
+ AaptXml.cpp \
ApkBuilder.cpp \
Command.cpp \
CrunchCache.cpp \
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index af49461..9bed899 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -130,6 +130,10 @@
void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; }
bool getErrorOnMissingConfigEntry() { return mErrorOnMissingConfigEntry; }
void setErrorOnMissingConfigEntry(bool val) { mErrorOnMissingConfigEntry = val; }
+ const android::String8& getPlatformBuildVersionCode() { return mPlatformVersionCode; }
+ void setPlatformBuildVersionCode(const android::String8& code) { mPlatformVersionCode = code; }
+ const android::String8& getPlatformBuildVersionName() { return mPlatformVersionName; }
+ void setPlatformBuildVersionName(const android::String8& name) { mPlatformVersionName = name; }
bool getUTF16StringsOption() {
return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO);
@@ -323,6 +327,8 @@
const char* mSingleCrunchInputFile;
const char* mSingleCrunchOutputFile;
bool mBuildSharedLibrary;
+ android::String8 mPlatformVersionCode;
+ android::String8 mPlatformVersionName;
/* file specification */
int mArgc;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index a0f0a08..fd660bb 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -3,6 +3,7 @@
//
// Android Asset Packaging Tool main entry point.
//
+#include "AaptXml.h"
#include "ApkBuilder.h"
#include "Bundle.h"
#include "Images.h"
@@ -241,162 +242,17 @@
return result;
}
-static ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes)
-{
- size_t N = tree.getAttributeCount();
- for (size_t i=0; i<N; i++) {
- if (tree.getAttributeNameResID(i) == attrRes) {
- return (ssize_t)i;
- }
- }
- return -1;
-}
-
-String8 getAttribute(const ResXMLTree& tree, const char* ns,
- const char* attr, String8* outError)
-{
- ssize_t idx = tree.indexOfAttribute(ns, attr);
- if (idx < 0) {
- return String8();
- }
- Res_value value;
- if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType != Res_value::TYPE_STRING) {
- if (outError != NULL) {
- *outError = "attribute is not a string value";
- }
- return String8();
- }
- }
- size_t len;
- const uint16_t* str = tree.getAttributeStringValue(idx, &len);
- return str ? String8(str, len) : String8();
-}
-
-static String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError)
-{
- ssize_t idx = indexOfAttribute(tree, attrRes);
- if (idx < 0) {
- return String8();
- }
- Res_value value;
- if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType != Res_value::TYPE_STRING) {
- if (outError != NULL) {
- *outError = "attribute is not a string value";
- }
- return String8();
- }
- }
- size_t len;
- const uint16_t* str = tree.getAttributeStringValue(idx, &len);
- return str ? String8(str, len) : String8();
-}
-
-static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes,
- String8* outError, int32_t defValue = -1)
-{
- ssize_t idx = indexOfAttribute(tree, attrRes);
- if (idx < 0) {
- return defValue;
- }
- Res_value value;
- if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType < Res_value::TYPE_FIRST_INT
- || value.dataType > Res_value::TYPE_LAST_INT) {
- if (outError != NULL) {
- *outError = "attribute is not an integer value";
- }
- return defValue;
- }
- }
- return value.data;
-}
-
-static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
- uint32_t attrRes, String8* outError, int32_t defValue = -1)
-{
- ssize_t idx = indexOfAttribute(tree, attrRes);
- if (idx < 0) {
- return defValue;
- }
- Res_value value;
- if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType == Res_value::TYPE_REFERENCE) {
- resTable->resolveReference(&value, 0);
- }
- if (value.dataType < Res_value::TYPE_FIRST_INT
- || value.dataType > Res_value::TYPE_LAST_INT) {
- if (outError != NULL) {
- *outError = "attribute is not an integer value";
- }
- return defValue;
- }
- }
- return value.data;
-}
-
-static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
- uint32_t attrRes, String8* outError)
-{
- ssize_t idx = indexOfAttribute(tree, attrRes);
- if (idx < 0) {
- return String8();
- }
- Res_value value;
- if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
- if (value.dataType == Res_value::TYPE_STRING) {
- size_t len;
- const uint16_t* str = tree.getAttributeStringValue(idx, &len);
- return str ? String8(str, len) : String8();
- }
- resTable->resolveReference(&value, 0);
- if (value.dataType != Res_value::TYPE_STRING) {
- if (outError != NULL) {
- *outError = "attribute is not a string value";
- }
- return String8();
- }
- }
- size_t len;
- const Res_value* value2 = &value;
- const char16_t* str = const_cast<ResTable*>(resTable)->valueToString(value2, 0, NULL, &len);
- return str ? String8(str, len) : String8();
-}
-
-static void getResolvedResourceAttribute(Res_value* value, const ResTable* resTable,
- const ResXMLTree& tree, uint32_t attrRes, String8* outError)
-{
- ssize_t idx = indexOfAttribute(tree, attrRes);
- if (idx < 0) {
- if (outError != NULL) {
- *outError = "attribute could not be found";
- }
- return;
- }
- if (tree.getAttributeValue(idx, value) != NO_ERROR) {
- if (value->dataType == Res_value::TYPE_REFERENCE) {
- resTable->resolveReference(value, 0);
- }
- // The attribute was found and was resolved if need be.
- return;
- }
- if (outError != NULL) {
- *outError = "error getting resolved resource attribute";
- }
-}
-
-static void printResolvedResourceAttribute(const ResTable* resTable, const ResXMLTree& tree,
+static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
uint32_t attrRes, String8 attrLabel, String8* outError)
{
Res_value value;
- getResolvedResourceAttribute(&value, resTable, tree, attrRes, outError);
+ AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError);
if (*outError != "") {
*outError = "error print resolved resource attribute";
return;
}
if (value.dataType == Res_value::TYPE_STRING) {
- String8 result = getResolvedAttribute(resTable, tree, attrRes, outError);
+ String8 result = AaptXml::getResolvedAttribute(resTable, tree, attrRes, outError);
printf("%s='%s'", attrLabel.string(),
ResTable::normalizeForOutput(result.string()).string());
} else if (Res_value::TYPE_FIRST_INT <= value.dataType &&
@@ -488,10 +344,10 @@
}
String8 tag(ctag16);
if (tag == "screen") {
- int32_t screenSize = getIntegerAttribute(tree,
- SCREEN_SIZE_ATTR, NULL, -1);
- int32_t screenDensity = getIntegerAttribute(tree,
- SCREEN_DENSITY_ATTR, NULL, -1);
+ int32_t screenSize = AaptXml::getIntegerAttribute(tree,
+ SCREEN_SIZE_ATTR);
+ int32_t screenDensity = AaptXml::getIntegerAttribute(tree,
+ SCREEN_DENSITY_ATTR);
if (screenSize > 0 && screenDensity > 0) {
if (!first) {
printf(",");
@@ -577,7 +433,7 @@
}
} else if (depth == 2 && withinApduService) {
if (tag == "aid-group") {
- String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
+ String8 category = AaptXml::getAttribute(tree, CATEGORY_ATTR, &error);
if (error != "") {
if (outError != NULL) *outError = error;
return Vector<String8>();
@@ -876,11 +732,11 @@
fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
goto bail;
}
- String8 pkg = getAttribute(tree, NULL, "package", NULL);
+ String8 pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
printf("package: %s\n", ResTable::normalizeForOutput(pkg.string()).string());
} else if (depth == 2 && tag == "permission") {
String8 error;
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR: %s\n", error.string());
goto bail;
@@ -889,14 +745,14 @@
ResTable::normalizeForOutput(name.string()).string());
} else if (depth == 2 && tag == "uses-permission") {
String8 error;
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR: %s\n", error.string());
goto bail;
}
printUsesPermission(name,
- getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
- getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
+ AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
+ AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
}
}
} else if (strcmp("badging", option) == 0) {
@@ -1151,12 +1007,14 @@
fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
goto bail;
}
- pkg = getAttribute(tree, NULL, "package", NULL);
+ pkg = AaptXml::getAttribute(tree, NULL, "package", NULL);
printf("package: name='%s' ",
ResTable::normalizeForOutput(pkg.string()).string());
- int32_t versionCode = getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
+ int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR,
+ &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:versionCode' attribute: %s\n",
+ error.string());
goto bail;
}
if (versionCode > 0) {
@@ -1164,23 +1022,29 @@
} else {
printf("versionCode='' ");
}
- String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error);
+ String8 versionName = AaptXml::getResolvedAttribute(res, tree,
+ VERSION_NAME_ATTR, &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n",
+ error.string());
goto bail;
}
printf("versionName='%s'",
ResTable::normalizeForOutput(versionName.string()).string());
- String8 splitName = getAttribute(tree, NULL, "split", NULL);
+ String8 splitName = AaptXml::getAttribute(tree, NULL, "split");
if (!splitName.isEmpty()) {
printf(" split='%s'", ResTable::normalizeForOutput(
splitName.string()).string());
}
+
+ int32_t platformVersionCode = AaptXml::getIntegerAttribute(tree, NULL,
+ "platformBuildVersionCode");
+ printf(" platformBuildVersionCode='%d'", platformVersionCode);
printf("\n");
- int32_t installLocation = getResolvedIntegerAttribute(&res, tree,
- INSTALL_LOCATION_ATTR, &error, -1);
+ int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
+ INSTALL_LOCATION_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:installLocation' attribute: %s\n",
error.string());
@@ -1215,7 +1079,8 @@
for (size_t i=0; i<NL; i++) {
const char* localeStr = locales[i].string();
assets.setLocale(localeStr != NULL ? localeStr : "");
- String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+ String8 llabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
+ &error);
if (llabel != "") {
if (localeStr == NULL || strlen(localeStr) == 0) {
label = llabel;
@@ -1236,7 +1101,8 @@
for (size_t i=0; i<ND; i++) {
tmpConfig.density = densities[i];
assets.setConfiguration(tmpConfig);
- String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+ String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
+ &error);
if (icon != "") {
printf("application-icon-%d:'%s'\n", densities[i],
ResTable::normalizeForOutput(icon.string()).string());
@@ -1244,14 +1110,17 @@
}
assets.setConfiguration(config);
- String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+ String8 icon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR, &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
+ error.string());
goto bail;
}
- int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
+ int32_t testOnly = AaptXml::getIntegerAttribute(tree, TEST_ONLY_ATTR, 0,
+ &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n",
+ error.string());
goto bail;
}
printf("application: label='%s' ",
@@ -1261,9 +1130,11 @@
printf("testOnly='%d'\n", testOnly);
}
- int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0);
+ int32_t debuggable = AaptXml::getResolvedIntegerAttribute(res, tree,
+ DEBUGGABLE_ATTR, 0, &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n",
+ error.string());
goto bail;
}
if (debuggable != 0) {
@@ -1284,10 +1155,11 @@
}
}
} else if (tag == "uses-sdk") {
- int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
+ int32_t code = AaptXml::getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error);
if (error != "") {
error = "";
- String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error);
+ String8 name = AaptXml::getResolvedAttribute(res, tree,
+ MIN_SDK_VERSION_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n",
error.string());
@@ -1300,14 +1172,15 @@
targetSdk = code;
printf("sdkVersion:'%d'\n", code);
}
- code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1);
+ code = AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR);
if (code != -1) {
printf("maxSdkVersion:'%d'\n", code);
}
- code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
+ code = AaptXml::getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
if (error != "") {
error = "";
- String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error);
+ String8 name = AaptXml::getResolvedAttribute(res, tree,
+ TARGET_SDK_VERSION_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n",
error.string());
@@ -1323,16 +1196,16 @@
printf("targetSdkVersion:'%d'\n", code);
}
} else if (tag == "uses-configuration") {
- int32_t reqTouchScreen = getIntegerAttribute(tree,
- REQ_TOUCH_SCREEN_ATTR, NULL, 0);
- int32_t reqKeyboardType = getIntegerAttribute(tree,
- REQ_KEYBOARD_TYPE_ATTR, NULL, 0);
- int32_t reqHardKeyboard = getIntegerAttribute(tree,
- REQ_HARD_KEYBOARD_ATTR, NULL, 0);
- int32_t reqNavigation = getIntegerAttribute(tree,
- REQ_NAVIGATION_ATTR, NULL, 0);
- int32_t reqFiveWayNav = getIntegerAttribute(tree,
- REQ_FIVE_WAY_NAV_ATTR, NULL, 0);
+ int32_t reqTouchScreen = AaptXml::getIntegerAttribute(tree,
+ REQ_TOUCH_SCREEN_ATTR, 0);
+ int32_t reqKeyboardType = AaptXml::getIntegerAttribute(tree,
+ REQ_KEYBOARD_TYPE_ATTR, 0);
+ int32_t reqHardKeyboard = AaptXml::getIntegerAttribute(tree,
+ REQ_HARD_KEYBOARD_ATTR, 0);
+ int32_t reqNavigation = AaptXml::getIntegerAttribute(tree,
+ REQ_NAVIGATION_ATTR, 0);
+ int32_t reqFiveWayNav = AaptXml::getIntegerAttribute(tree,
+ REQ_FIVE_WAY_NAV_ATTR, 0);
printf("uses-configuration:");
if (reqTouchScreen != 0) {
printf(" reqTouchScreen='%d'", reqTouchScreen);
@@ -1353,26 +1226,26 @@
} else if (tag == "supports-input") {
withinSupportsInput = true;
} else if (tag == "supports-screens") {
- smallScreen = getIntegerAttribute(tree,
- SMALL_SCREEN_ATTR, NULL, 1);
- normalScreen = getIntegerAttribute(tree,
- NORMAL_SCREEN_ATTR, NULL, 1);
- largeScreen = getIntegerAttribute(tree,
- LARGE_SCREEN_ATTR, NULL, 1);
- xlargeScreen = getIntegerAttribute(tree,
- XLARGE_SCREEN_ATTR, NULL, 1);
- anyDensity = getIntegerAttribute(tree,
- ANY_DENSITY_ATTR, NULL, 1);
- requiresSmallestWidthDp = getIntegerAttribute(tree,
- REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
- compatibleWidthLimitDp = getIntegerAttribute(tree,
- COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
- largestWidthLimitDp = getIntegerAttribute(tree,
- LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
+ smallScreen = AaptXml::getIntegerAttribute(tree,
+ SMALL_SCREEN_ATTR, 1);
+ normalScreen = AaptXml::getIntegerAttribute(tree,
+ NORMAL_SCREEN_ATTR, 1);
+ largeScreen = AaptXml::getIntegerAttribute(tree,
+ LARGE_SCREEN_ATTR, 1);
+ xlargeScreen = AaptXml::getIntegerAttribute(tree,
+ XLARGE_SCREEN_ATTR, 1);
+ anyDensity = AaptXml::getIntegerAttribute(tree,
+ ANY_DENSITY_ATTR, 1);
+ requiresSmallestWidthDp = AaptXml::getIntegerAttribute(tree,
+ REQUIRES_SMALLEST_WIDTH_DP_ATTR, 0);
+ compatibleWidthLimitDp = AaptXml::getIntegerAttribute(tree,
+ COMPATIBLE_WIDTH_LIMIT_DP_ATTR, 0);
+ largestWidthLimitDp = AaptXml::getIntegerAttribute(tree,
+ LARGEST_WIDTH_LIMIT_DP_ATTR, 0);
} else if (tag == "feature-group") {
withinFeatureGroup = true;
FeatureGroup group;
- group.label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+ group.label = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:label' attribute:"
" %s\n", error.string());
@@ -1381,17 +1254,17 @@
featureGroups.add(group);
} else if (tag == "uses-feature") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
- int req = getIntegerAttribute(tree,
- REQUIRED_ATTR, NULL, 1);
+ int req = AaptXml::getIntegerAttribute(tree,
+ REQUIRED_ATTR, 1);
commonFeatures.features.add(name, req);
if (req) {
addParentFeatures(&commonFeatures, name);
}
} else {
- int vers = getIntegerAttribute(tree,
+ int vers = AaptXml::getIntegerAttribute(tree,
GL_ES_VERSION_ATTR, &error);
if (error == "") {
if (vers > commonFeatures.openGLESVersion) {
@@ -1400,7 +1273,7 @@
}
}
} else if (tag == "uses-permission") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
if (name == "android.permission.CAMERA") {
addImpliedFeature(&impliedFeatures, "android.hardware.camera",
@@ -1478,15 +1351,15 @@
}
printUsesPermission(name,
- getIntegerAttribute(tree, REQUIRED_ATTR, NULL, 1) == 0,
- getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1));
+ AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
+ AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
} else {
fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
error.string());
goto bail;
}
} else if (tag == "uses-package") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
printf("uses-package:'%s'\n",
ResTable::normalizeForOutput(name.string()).string());
@@ -1496,7 +1369,7 @@
goto bail;
}
} else if (tag == "original-package") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
printf("original-package:'%s'\n",
ResTable::normalizeForOutput(name.string()).string());
@@ -1506,7 +1379,7 @@
goto bail;
}
} else if (tag == "supports-gl-texture") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
printf("supports-gl-texture:'%s'\n",
ResTable::normalizeForOutput(name.string()).string());
@@ -1524,9 +1397,9 @@
}
depth--;
} else if (tag == "package-verifier") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
- String8 publicKey = getAttribute(tree, PUBLIC_KEY_ATTR, &error);
+ String8 publicKey = AaptXml::getAttribute(tree, PUBLIC_KEY_ATTR, &error);
if (publicKey != "" && error == "") {
printf("package-verifier: name='%s' publicKey='%s'\n",
ResTable::normalizeForOutput(name.string()).string(),
@@ -1553,35 +1426,38 @@
if (withinApplication) {
if(tag == "activity") {
withinActivity = true;
- activityName = getAttribute(tree, NAME_ATTR, &error);
+ activityName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
error.string());
goto bail;
}
- activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+ activityLabel = AaptXml::getResolvedAttribute(res, tree, LABEL_ATTR,
+ &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
error.string());
goto bail;
}
- activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+ activityIcon = AaptXml::getResolvedAttribute(res, tree, ICON_ATTR,
+ &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
error.string());
goto bail;
}
- activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
+ activityBanner = AaptXml::getResolvedAttribute(res, tree, BANNER_ATTR,
+ &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
error.string());
goto bail;
}
- int32_t orien = getResolvedIntegerAttribute(&res, tree,
+ int32_t orien = AaptXml::getResolvedIntegerAttribute(res, tree,
SCREEN_ORIENTATION_ATTR, &error);
if (error == "") {
if (orien == 0 || orien == 6 || orien == 8) {
@@ -1595,21 +1471,21 @@
}
}
} else if (tag == "uses-library") {
- String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
+ String8 libraryName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr,
"ERROR getting 'android:name' attribute for uses-library"
" %s\n", error.string());
goto bail;
}
- int req = getIntegerAttribute(tree,
- REQUIRED_ATTR, NULL, 1);
+ int req = AaptXml::getIntegerAttribute(tree,
+ REQUIRED_ATTR, 1);
printf("uses-library%s:'%s'\n",
req ? "" : "-not-required", ResTable::normalizeForOutput(
libraryName.string()).string());
} else if (tag == "receiver") {
withinReceiver = true;
- receiverName = getAttribute(tree, NAME_ATTR, &error);
+ receiverName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr,
@@ -1618,7 +1494,8 @@
goto bail;
}
- String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+ String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
+ &error);
if (error == "") {
if (permission == "android.permission.BIND_DEVICE_ADMIN") {
hasBindDeviceAdminPermission = true;
@@ -1629,7 +1506,7 @@
}
} else if (tag == "service") {
withinService = true;
- serviceName = getAttribute(tree, NAME_ATTR, &error);
+ serviceName = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:name' attribute for "
@@ -1637,7 +1514,8 @@
goto bail;
}
- String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+ String8 permission = AaptXml::getAttribute(tree, PERMISSION_ATTR,
+ &error);
if (error == "") {
if (permission == "android.permission.BIND_INPUT_METHOD") {
hasBindInputMethodPermission = true;
@@ -1659,22 +1537,24 @@
} else if (tag == "provider") {
withinProvider = true;
- bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error);
+ bool exported = AaptXml::getResolvedIntegerAttribute(res, tree,
+ EXPORTED_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
" %s\n", error.string());
goto bail;
}
- bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree,
- GRANT_URI_PERMISSIONS_ATTR, &error);
+ bool grantUriPermissions = AaptXml::getResolvedIntegerAttribute(
+ res, tree, GRANT_URI_PERMISSIONS_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
" %s\n", error.string());
goto bail;
}
- String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error);
+ String8 permission = AaptXml::getResolvedAttribute(res, tree,
+ PERMISSION_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
" %s\n", error.string());
@@ -1685,7 +1565,8 @@
permission == "android.permission.MANAGE_DOCUMENTS";
} else if (bundle->getIncludeMetaData() && tag == "meta-data") {
- String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
+ String8 metaDataName = AaptXml::getResolvedAttribute(res, tree,
+ NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:name' attribute for "
"meta-data:%s\n", error.string());
@@ -1693,12 +1574,12 @@
}
printf("meta-data: name='%s' ",
ResTable::normalizeForOutput(metaDataName.string()).string());
- printResolvedResourceAttribute(&res, tree, VALUE_ATTR, String8("value"),
+ printResolvedResourceAttribute(res, tree, VALUE_ATTR, String8("value"),
&error);
if (error != "") {
// Try looking for a RESOURCE_ATTR
error = "";
- printResolvedResourceAttribute(&res, tree, RESOURCE_ATTR,
+ printResolvedResourceAttribute(res, tree, RESOURCE_ATTR,
String8("resource"), &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:value' or "
@@ -1709,7 +1590,7 @@
}
printf("\n");
} else if (withinSupportsInput && tag == "input-type") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
supportedInput.add(name);
} else {
@@ -1721,12 +1602,13 @@
} else if (withinFeatureGroup && tag == "uses-feature") {
FeatureGroup& top = featureGroups.editTop();
- String8 name = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
if (name != "" && error == "") {
top.features.add(name, true);
addParentFeatures(&top, name);
} else {
- int vers = getIntegerAttribute(tree, GL_ES_VERSION_ATTR, &error);
+ int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
+ &error);
if (error == "") {
if (vers > top.openGLESVersion) {
top.openGLESVersion = vers;
@@ -1754,7 +1636,7 @@
actCameraSecure = false;
catLauncher = false;
} else if (withinService && tag == "meta-data") {
- String8 name = getAttribute(tree, NAME_ATTR, &error);
+ String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:name' attribute for"
" meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
@@ -1768,7 +1650,8 @@
offHost = false;
}
- String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
+ String8 xmlPath = AaptXml::getResolvedAttribute(res, tree,
+ RESOURCE_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:resource' attribute for"
" meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
@@ -1797,7 +1680,7 @@
} else if ((depth == 5) && withinIntentFilter) {
String8 action;
if (tag == "action") {
- action = getAttribute(tree, NAME_ATTR, &error);
+ action = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
error.string());
@@ -1849,7 +1732,7 @@
}
if (tag == "category") {
- String8 category = getAttribute(tree, NAME_ATTR, &error);
+ String8 category = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'name' attribute: %s\n",
error.string());
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index dd40b20..f24a023b 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -60,9 +60,6 @@
int dumpResources(Bundle* bundle);
-String8 getAttribute(const ResXMLTree& tree, const char* ns,
- const char* attr, String8* outError);
-
status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets,
FILE* fp, bool includeRaw);
#endif // __MAIN_H
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 7979a1d..5deeca2 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -4,6 +4,7 @@
// Build resource files from raw assets.
//
#include "AaptAssets.h"
+#include "AaptXml.h"
#include "CacheUpdater.h"
#include "CrunchCache.h"
#include "FileFinder.h"
@@ -805,6 +806,20 @@
}
}
+ if (bundle->getPlatformBuildVersionCode() != "") {
+ if (!addTagAttribute(root, "", "platformBuildVersionCode",
+ bundle->getPlatformBuildVersionCode(), errorOnFailedInsert, true)) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ if (bundle->getPlatformBuildVersionName() != "") {
+ if (!addTagAttribute(root, "", "platformBuildVersionName",
+ bundle->getPlatformBuildVersionName(), errorOnFailedInsert, true)) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
if (bundle->getDebugMode()) {
sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
if (application != NULL) {
@@ -881,6 +896,106 @@
return NO_ERROR;
}
+static int32_t getPlatformAssetCookie(const AssetManager& assets) {
+ // Find the system package (0x01). AAPT always generates attributes
+ // with the type 0x01, so we're looking for the first attribute
+ // resource in the system package.
+ const ResTable& table = assets.getResources(true);
+ Res_value val;
+ ssize_t idx = table.getResource(0x01010000, &val, true);
+ if (idx != NO_ERROR) {
+ // Try as a bag.
+ const ResTable::bag_entry* entry;
+ ssize_t cnt = table.lockBag(0x01010000, &entry);
+ if (cnt >= 0) {
+ idx = entry->stringBlock;
+ }
+ table.unlockBag(entry);
+ }
+
+ if (idx < 0) {
+ return 0;
+ }
+ return table.getTableCookie(idx);
+}
+
+enum {
+ VERSION_CODE_ATTR = 0x0101021b,
+ VERSION_NAME_ATTR = 0x0101021c,
+};
+
+static ssize_t extractPlatformBuildVersion(ResXMLTree& tree, Bundle* bundle) {
+ size_t len;
+ ResXMLTree::event_code_t code;
+ while ((code = tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code != ResXMLTree::START_TAG) {
+ continue;
+ }
+
+ const char16_t* ctag16 = tree.getElementName(&len);
+ if (ctag16 == NULL) {
+ fprintf(stderr, "ERROR: failed to get XML element name (bad string pool)\n");
+ return UNKNOWN_ERROR;
+ }
+
+ String8 tag(ctag16, len);
+ if (tag != "manifest") {
+ continue;
+ }
+
+ String8 error;
+ int32_t versionCode = AaptXml::getIntegerAttribute(tree, VERSION_CODE_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR: failed to get platform version code\n");
+ return UNKNOWN_ERROR;
+ }
+
+ if (versionCode >= 0 && bundle->getPlatformBuildVersionCode() == "") {
+ bundle->setPlatformBuildVersionCode(String8::format("%d", versionCode));
+ }
+
+ String8 versionName = AaptXml::getAttribute(tree, VERSION_NAME_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR: failed to get platform version name\n");
+ return UNKNOWN_ERROR;
+ }
+
+ if (versionName != "" && bundle->getPlatformBuildVersionName() == "") {
+ bundle->setPlatformBuildVersionName(versionName);
+ }
+ return NO_ERROR;
+ }
+
+ fprintf(stderr, "ERROR: no <manifest> tag found in platform AndroidManifest.xml\n");
+ return UNKNOWN_ERROR;
+}
+
+static ssize_t extractPlatformBuildVersion(AssetManager& assets, Bundle* bundle) {
+ int32_t cookie = getPlatformAssetCookie(assets);
+ if (cookie == 0) {
+ fprintf(stderr, "ERROR: Platform package not found\n");
+ return UNKNOWN_ERROR;
+ }
+
+ ResXMLTree tree;
+ Asset* asset = assets.openNonAsset(cookie, "AndroidManifest.xml", Asset::ACCESS_STREAMING);
+ if (asset == NULL) {
+ fprintf(stderr, "ERROR: Platform AndroidManifest.xml not found\n");
+ return UNKNOWN_ERROR;
+ }
+
+ ssize_t result = NO_ERROR;
+ if (tree.setTo(asset->getBuffer(true), asset->getLength()) != NO_ERROR) {
+ fprintf(stderr, "ERROR: Platform AndroidManifest.xml is corrupt\n");
+ result = UNKNOWN_ERROR;
+ } else {
+ result = extractPlatformBuildVersion(tree, bundle);
+ }
+
+ delete asset;
+ return result;
+}
+
#define ASSIGN_IT(n) \
do { \
ssize_t index = resources->indexOfKey(String8(#n)); \
@@ -1356,6 +1471,17 @@
return UNKNOWN_ERROR;
}
+ // If we're not overriding the platform build versions,
+ // extract them from the platform APK.
+ if (packageType != ResourceTable::System &&
+ (bundle->getPlatformBuildVersionCode() == "" ||
+ bundle->getPlatformBuildVersionName() == "")) {
+ err = extractPlatformBuildVersion(assets->getAssetManager(), bundle);
+ if (err != NO_ERROR) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
const sp<AaptFile> manifestFile(androidManifestFile->getFiles().valueAt(0));
String8 manifestPath(manifestFile->getPrintableSource());
@@ -2636,13 +2762,14 @@
fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
return -1;
}
- pkg = getAttribute(tree, NULL, "package", NULL);
+ pkg = AaptXml::getAttribute(tree, NULL, "package");
} else if (depth == 2) {
if (tag == "application") {
inApplication = true;
keepTag = true;
- String8 agent = getAttribute(tree, "http://schemas.android.com/apk/res/android",
+ String8 agent = AaptXml::getAttribute(tree,
+ "http://schemas.android.com/apk/res/android",
"backupAgent", &error);
if (agent.length() > 0) {
addProguardKeepRule(keep, agent, pkg.string(),
@@ -2658,8 +2785,8 @@
}
}
if (keepTag) {
- String8 name = getAttribute(tree, "http://schemas.android.com/apk/res/android",
- "name", &error);
+ String8 name = AaptXml::getAttribute(tree,
+ "http://schemas.android.com/apk/res/android", "name", &error);
if (error != "") {
fprintf(stderr, "ERROR: %s\n", error.string());
return -1;