diff options
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 168 | ||||
-rw-r--r-- | core/java/android/content/res/TypedArray.java | 36 | ||||
-rw-r--r-- | include/utils/ResourceTypes.h | 4 | ||||
-rw-r--r-- | libs/utils/ResourceTypes.cpp | 9 | ||||
-rw-r--r-- | tools/aapt/Command.cpp | 2 | ||||
-rw-r--r-- | tools/aapt/Resource.cpp | 267 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 14 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.h | 6 |
8 files changed, 321 insertions, 185 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 5da7fd119783..663d9e605084 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -755,14 +755,14 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifest); pkg.mVersionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode, 0); - pkg.mVersionName = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_versionName); + pkg.mVersionName = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifest_versionName, 0); if (pkg.mVersionName != null) { pkg.mVersionName = pkg.mVersionName.intern(); } - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifest_sharedUserId); - if (str != null) { + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); + if (str != null && str.length() > 0) { String nameError = validateName(str, true); if (nameError != null && !"android".equals(pkgName)) { outError[0] = "<manifest> specifies bad sharedUserId name \"" @@ -828,6 +828,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesPermission); + // Note: don't allow this value to be a reference to a resource + // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesPermission_name); @@ -871,6 +873,8 @@ public class PackageParser { FeatureInfo fi = new FeatureInfo(); sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesFeature); + // Note: don't allow this value to be a reference to a resource + // that may change. fi.name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesFeature_name); if (fi.name == null) { @@ -1002,6 +1006,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); + // Note: don't allow this value to be a reference to a resource + // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); @@ -1027,8 +1033,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage); - String orig =sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestOriginalPackage_name); + String orig =sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); if (!pkg.packageName.equals(orig)) { if (pkg.mOriginalPackages == null) { pkg.mOriginalPackages = new ArrayList<String>(); @@ -1045,8 +1051,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestOriginalPackage); - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestOriginalPackage_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); sa.recycle(); @@ -1271,6 +1277,8 @@ public class PackageParser { return null; } + // Note: don't allow this value to be a reference to a resource + // that may change. perm.info.group = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); if (perm.info.group != null) { @@ -1375,6 +1383,8 @@ public class PackageParser { } String str; + // Note: don't allow this value to be a reference to a resource + // that may change. str = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); a.info.targetPackage = str != null ? str.intern() : null; @@ -1415,8 +1425,8 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestApplication); - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_name, 0); if (name != null) { ai.className = buildClassName(pkgName, name, outError); if (ai.className == null) { @@ -1426,8 +1436,8 @@ public class PackageParser { } } - String manageSpaceActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity); + String manageSpaceActivity = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0); if (manageSpaceActivity != null) { ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, outError); @@ -1440,8 +1450,8 @@ public class PackageParser { // backupAgent, killAfterRestore, restoreNeedsApplication, and restoreAnyVersion // are only relevant if backup is possible for the given application. - String backupAgent = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_backupAgent); + String backupAgent = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0); if (backupAgent != null) { ai.backupAgentName = buildClassName(pkgName, backupAgent, outError); if (false) { @@ -1539,21 +1549,22 @@ public class PackageParser { } String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_permission, 0); ai.permission = (str != null && str.length() > 0) ? str.intern() : null; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity, 0); ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, str, outError); if (outError[0] == null) { - ai.processName = buildProcessName(ai.packageName, null, sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestApplication_process), + ai.processName = buildProcessName(ai.packageName, null, sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestApplication_process, 0), flags, mSeparateProcesses, outError); - ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); + ai.enabled = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); } sa.recycle(); @@ -1632,6 +1643,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestUsesLibrary); + // Note: don't allow this value to be a reference to a resource + // that may change. String lname = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); boolean req = sa.getBoolean( @@ -1681,7 +1694,7 @@ public class PackageParser { private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, int nameRes, int labelRes, int iconRes) { - String name = sa.getNonResourceString(nameRes); + String name = sa.getNonConfigurationString(nameRes, 0); if (name == null) { outError[0] = tag + " does not specify android:name"; return false; @@ -1747,16 +1760,16 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivity_permission, 0); if (str == null) { a.info.permission = owner.applicationInfo.permission; } else { a.info.permission = str.length() > 0 ? str.toString().intern() : null; } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity, 0); a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, owner.applicationInfo.taskAffinity, str, outError); @@ -1902,8 +1915,8 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestActivityAlias); - String targetActivity = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity); + String targetActivity = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity, 0); if (targetActivity == null) { outError[0] = "<activity-alias> does not specify android:targetActivity"; sa.recycle(); @@ -1980,8 +1993,8 @@ public class PackageParser { } String str; - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestActivityAlias_permission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0); if (str != null) { a.info.permission = str.length() > 0 ? str.toString().intern() : null; } @@ -2068,17 +2081,17 @@ public class PackageParser { p.info.exported = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestProvider_exported, true); - String cpname = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_authorities); + String cpname = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0); p.info.isSyncable = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestProvider_syncable, false); - String permission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_permission); - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_readPermission); + String permission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_permission, 0); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0); if (str == null) { str = permission; } @@ -2088,8 +2101,8 @@ public class PackageParser { p.info.readPermission = str.length() > 0 ? str.toString().intern() : null; } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestProvider_writePermission); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0); if (str == null) { str = permission; } @@ -2152,20 +2165,20 @@ public class PackageParser { PatternMatcher pa = null; - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0); if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } @@ -2203,15 +2216,15 @@ public class PackageParser { PathPermission pa = null; - String permission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_permission); - String readPermission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission); + String permission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0); + String readPermission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0); if (readPermission == null) { readPermission = permission; } - String writePermission = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission); + String writePermission = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0); if (writePermission == null) { writePermission = permission; } @@ -2238,22 +2251,22 @@ public class PackageParser { return false; } - String path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_path); + String path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); } - path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix); + path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); } - path = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern); + path = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0); if (path != null) { pa = new PathPermission(path, PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); @@ -2335,8 +2348,8 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestService_exported, false); } - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestService_permission); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestService_permission, 0); if (str == null) { s.info.permission = owner.applicationInfo.permission; } else { @@ -2433,8 +2446,8 @@ public class PackageParser { data = new Bundle(); } - String name = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestMetaData_name); + String name = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestMetaData_name, 0); if (name == null) { outError[0] = "<meta-data> requires an android:name attribute"; sa.recycle(); @@ -2552,8 +2565,8 @@ public class PackageParser { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestData); - String str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_mimeType); + String str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_mimeType, 0); if (str != null) { try { outInfo.addDataType(str); @@ -2564,34 +2577,34 @@ public class PackageParser { } } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_scheme); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_scheme, 0); if (str != null) { outInfo.addDataScheme(str); } - String host = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_host); - String port = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_port); + String host = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_host, 0); + String port = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_port, 0); if (host != null) { outInfo.addDataAuthority(host, port); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_path); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_path, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPrefix); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); } - str = sa.getNonResourceString( - com.android.internal.R.styleable.AndroidManifestData_pathPattern); + str = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0); if (str != null) { outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } @@ -2754,7 +2767,7 @@ public class PackageParser { public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { owner = args.owner; intents = new ArrayList<II>(0); - String name = args.sa.getNonResourceString(args.nameRes); + String name = args.sa.getNonConfigurationString(args.nameRes, 0); if (name == null) { className = null; args.outError[0] = args.tag + " does not specify android:name"; @@ -2793,7 +2806,8 @@ public class PackageParser { if (args.processRes != 0) { outInfo.processName = buildProcessName(owner.applicationInfo.packageName, - owner.applicationInfo.processName, args.sa.getNonResourceString(args.processRes), + owner.applicationInfo.processName, + args.sa.getNonConfigurationString(args.processRes, 0), args.flags, args.sepProcesses, args.outError); } diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index a7fb31de05f3..09fdf8d637d4 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -148,6 +148,42 @@ public class TypedArray { } /** + * @hide + * Retrieve the string value for the attribute at <var>index</var> that is + * not allowed to change with the given configurations. + * + * @param index Index of attribute to retrieve. + * @param allowedChangingConfigs Bit mask of configurations from + * ActivityInfo that are allowed to change. + * + * @return String holding string data. Any styling information is + * removed. Returns null if the attribute is not defined. + */ + public String getNonConfigurationString(int index, int allowedChangingConfigs) { + index *= AssetManager.STYLE_NUM_ENTRIES; + final int[] data = mData; + final int type = data[index+AssetManager.STYLE_TYPE]; + if ((data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]&~allowedChangingConfigs) != 0) { + return null; + } + if (type == TypedValue.TYPE_NULL) { + return null; + } else if (type == TypedValue.TYPE_STRING) { + return loadStringValueAt(index).toString(); + } + + TypedValue v = mValue; + if (getValueAt(index, v)) { + Log.w(Resources.TAG, "Converting to string: " + v); + CharSequence cs = v.coerceToString(); + return cs != null ? cs.toString() : null; + } + Log.w(Resources.TAG, "getString of bad type: 0x" + + Integer.toHexString(type)); + return null; + } + + /** * Retrieve the boolean value for the attribute at <var>index</var>. * * @param index Index of attribute to retrieve. diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 0e796dc561f1..b701ce74d627 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -631,6 +631,8 @@ public: void restart(); + const ResStringPool& getStrings() const; + event_code_t getEventType() const; // Note, unlike XmlPullParser, the first call to next() will return // START_TAG of the first element. @@ -716,8 +718,6 @@ public: void uninit(); - const ResStringPool& getStrings() const; - private: friend class ResXMLParser; diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 38d8412952fc..7e0f881af674 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -625,6 +625,10 @@ void ResXMLParser::restart() mCurNode = NULL; mEventCode = mTree.mError == NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT; } +const ResStringPool& ResXMLParser::getStrings() const +{ + return mTree.mStrings; +} ResXMLParser::event_code_t ResXMLParser::getEventType() const { @@ -1149,11 +1153,6 @@ void ResXMLTree::uninit() restart(); } -const ResStringPool& ResXMLTree::getStrings() const -{ - return mStrings; -} - status_t ResXMLTree::validateNode(const ResXMLTree_node* node) const { const uint16_t eventCode = dtohs(node->header.type); diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 537ae5e7716b..735a80da9f2e 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -603,7 +603,7 @@ int doDump(Bundle* bundle) } else { printf("versionCode='' "); } - String8 versionName = getAttribute(tree, VERSION_NAME_ATTR, &error); + String8 versionName = getResolvedAttribute(&res, tree, VERSION_NAME_ATTR, &error); if (error != "") { fprintf(stderr, "ERROR getting 'android:versionName' attribute: %s\n", error.string()); goto bail; diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index b7580b33c723..c0ebb5963328 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -379,14 +379,64 @@ enum { ATTR_LEADING_SPACES = -3, ATTR_TRAILING_SPACES = -4 }; -static int validateAttr(const String8& path, const ResXMLParser& parser, +static int validateAttr(const String8& path, const ResTable& table, + const ResXMLParser& parser, const char* ns, const char* attr, const char* validChars, bool required) { size_t len; ssize_t index = parser.indexOfAttribute(ns, attr); const uint16_t* str; - if (index >= 0 && (str=parser.getAttributeStringValue(index, &len)) != NULL) { + Res_value value; + if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) { + const ResStringPool* pool = &parser.getStrings(); + if (value.dataType == Res_value::TYPE_REFERENCE) { + uint32_t specFlags = 0; + int strIdx; + if ((strIdx=table.resolveReference(&value, 0x10000000, NULL, &specFlags)) < 0) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s references unknown resid 0x%08x.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + value.data); + return ATTR_NOT_FOUND; + } + + pool = table.getTableStringBlock(strIdx); + #if 0 + if (pool != NULL) { + str = pool->stringAt(value.data, &len); + } + printf("***** RES ATTR: %s specFlags=0x%x strIdx=%d: %s\n", attr, + specFlags, strIdx, str != NULL ? String8(str).string() : "???"); + #endif + if ((specFlags&~ResTable_typeSpec::SPEC_PUBLIC) != 0 && false) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s varies by configurations 0x%x.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + specFlags); + return ATTR_NOT_FOUND; + } + } + if (value.dataType == Res_value::TYPE_STRING) { + if (pool == NULL) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has no string block.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr); + return ATTR_NOT_FOUND; + } + if ((str=pool->stringAt(value.data, &len)) == NULL) { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has corrupt string value.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr); + return ATTR_NOT_FOUND; + } + } else { + fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid type %d.\n", + path.string(), parser.getLineNumber(), + String8(parser.getElementName(&len)).string(), attr, + value.dataType); + return ATTR_NOT_FOUND; + } if (validChars) { for (size_t i=0; i<len; i++) { uint16_t c = str[i]; @@ -959,21 +1009,102 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) err = NO_ERROR; } + if (table.validateLocalizations()) { + hasErrors = true; + } + + if (hasErrors) { + return UNKNOWN_ERROR; + } + const sp<AaptFile> manifestFile(androidManifestFile->getFiles().valueAt(0)); String8 manifestPath(manifestFile->getPrintableSource()); + // Generate final compiled manifest file. + manifestFile->clearData(); + sp<XMLNode> manifestTree = XMLNode::parse(manifestFile); + if (manifestTree == NULL) { + return UNKNOWN_ERROR; + } + err = massageManifest(bundle, manifestTree); + if (err < NO_ERROR) { + return err; + } + err = compileXmlFile(assets, manifestTree, manifestFile, &table); + if (err < NO_ERROR) { + return err; + } + + //block.restart(); + //printXMLBlock(&block); + + // -------------------------------------------------------------- + // Generate the final resource table. + // Re-flatten because we may have added new resource IDs + // -------------------------------------------------------------- + + ResTable finalResTable; + sp<AaptFile> resFile; + + if (table.hasResources()) { + sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); + err = table.addSymbols(symbols); + if (err < NO_ERROR) { + return err; + } + + resFile = getResourceFile(assets); + if (resFile == NULL) { + fprintf(stderr, "Error: unable to generate entry for resource data\n"); + return UNKNOWN_ERROR; + } + + err = table.flatten(bundle, resFile); + if (err < NO_ERROR) { + return err; + } + + if (bundle->getPublicOutputFile()) { + FILE* fp = fopen(bundle->getPublicOutputFile(), "w+"); + if (fp == NULL) { + fprintf(stderr, "ERROR: Unable to open public definitions output file %s: %s\n", + (const char*)bundle->getPublicOutputFile(), strerror(errno)); + return UNKNOWN_ERROR; + } + if (bundle->getVerbose()) { + printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); + } + table.writePublicDefinitions(String16(assets->getPackage()), fp); + fclose(fp); + } + + // Read resources back in, + finalResTable.add(resFile->getData(), resFile->getSize(), NULL); + +#if 0 + NOISY( + printf("Generated resources:\n"); + finalResTable.print(); + ) +#endif + } + // Perform a basic validation of the manifest file. This time we // parse it with the comments intact, so that we can use them to // generate java docs... so we are not going to write this one // back out to the final manifest data. - err = compileXmlFile(assets, manifestFile, &table, + sp<AaptFile> outManifestFile = new AaptFile(manifestFile->getSourceFile(), + manifestFile->getGroupEntry(), + manifestFile->getResourceType()); + err = compileXmlFile(assets, manifestFile, + outManifestFile, &table, XML_COMPILE_ASSIGN_ATTRIBUTE_IDS | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES); if (err < NO_ERROR) { return err; } ResXMLTree block; - block.setTo(manifestFile->getData(), manifestFile->getSize(), true); + block.setTo(outManifestFile->getData(), outManifestFile->getSize(), true); String16 manifest16("manifest"); String16 permission16("permission"); String16 permission_group16("permission-group"); @@ -1012,16 +1143,20 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) continue; } if (strcmp16(block.getElementName(&len), manifest16.string()) == 0) { - if (validateAttr(manifestPath, block, NULL, "package", + if (validateAttr(manifestPath, finalResTable, block, NULL, "package", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "sharedUserId", packageIdentChars, false) != ATTR_OKAY) { + hasErrors = true; + } } else if (strcmp16(block.getElementName(&len), permission16.string()) == 0 || strcmp16(block.getElementName(&len), permission_group16.string()) == 0) { const bool isGroup = strcmp16(block.getElementName(&len), permission_group16.string()) == 0; - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - isGroup ? packageIdentCharsWithTheStupid + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", isGroup ? packageIdentCharsWithTheStupid : packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } @@ -1099,56 +1234,56 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } syms->makeSymbolPublic(String8(e), srcPos); } else if (strcmp16(block.getElementName(&len), uses_permission16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - packageIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), instrumentation16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "targetPackage", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), application16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, false) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "taskAffinity", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), provider16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "authorities", authoritiesIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; @@ -1156,39 +1291,39 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } else if (strcmp16(block.getElementName(&len), service16.string()) == 0 || strcmp16(block.getElementName(&len), receiver16.string()) == 0 || strcmp16(block.getElementName(&len), activity16.string()) == 0) { - if (validateAttr(manifestPath, block, RESOURCES_ANDROID_NAMESPACE, "name", - classIdentChars, true) != ATTR_OKAY) { + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, + "name", classIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "permission", packageIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "process", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "taskAffinity", processIdentChars, false) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), action16.string()) == 0 || strcmp16(block.getElementName(&len), category16.string()) == 0) { - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "name", packageIdentChars, true) != ATTR_OKAY) { hasErrors = true; } } else if (strcmp16(block.getElementName(&len), data16.string()) == 0) { - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "mimeType", typeIdentChars, true) != ATTR_OKAY) { hasErrors = true; } - if (validateAttr(manifestPath, block, + if (validateAttr(manifestPath, finalResTable, block, RESOURCES_ANDROID_NAMESPACE, "scheme", schemeIdentChars, true) != ATTR_OKAY) { hasErrors = true; @@ -1197,76 +1332,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) } } - if (table.validateLocalizations()) { - hasErrors = true; - } - - if (hasErrors) { - return UNKNOWN_ERROR; - } - - // Generate final compiled manifest file. - manifestFile->clearData(); - sp<XMLNode> manifestTree = XMLNode::parse(manifestFile); - if (manifestTree == NULL) { - return UNKNOWN_ERROR; - } - err = massageManifest(bundle, manifestTree); - if (err < NO_ERROR) { - return err; - } - err = compileXmlFile(assets, manifestTree, manifestFile, &table); - if (err < NO_ERROR) { - return err; - } - - //block.restart(); - //printXMLBlock(&block); - - // -------------------------------------------------------------- - // Generate the final resource table. - // Re-flatten because we may have added new resource IDs - // -------------------------------------------------------------- - - if (table.hasResources()) { - sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); - err = table.addSymbols(symbols); - if (err < NO_ERROR) { - return err; - } - - sp<AaptFile> resFile(getResourceFile(assets)); - if (resFile == NULL) { - fprintf(stderr, "Error: unable to generate entry for resource data\n"); - return UNKNOWN_ERROR; - } - - err = table.flatten(bundle, resFile); - if (err < NO_ERROR) { - return err; - } - - if (bundle->getPublicOutputFile()) { - FILE* fp = fopen(bundle->getPublicOutputFile(), "w+"); - if (fp == NULL) { - fprintf(stderr, "ERROR: Unable to open public definitions output file %s: %s\n", - (const char*)bundle->getPublicOutputFile(), strerror(errno)); - return UNKNOWN_ERROR; - } - if (bundle->getVerbose()) { - printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); - } - table.writePublicDefinitions(String16(assets->getPackage()), fp); - fclose(fp); - } -#if 0 - NOISY( - ResTable rt; - rt.add(resFile->getData(), resFile->getSize(), NULL); - printf("Generated resources:\n"); - rt.print(); - ) -#endif + if (resFile != NULL) { // These resources are now considered to be a part of the included // resources, for others to reference. err = assets->addIncludedResources(resFile); @@ -1275,6 +1341,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) return err; } } + return err; } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 1f9d15285785..ab5e9376f328 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -28,6 +28,20 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, } status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<AaptFile>& target, + const sp<AaptFile>& outTarget, + ResourceTable* table, + int options) +{ + sp<XMLNode> root = XMLNode::parse(target); + if (root == NULL) { + return UNKNOWN_ERROR; + } + + return compileXmlFile(assets, root, outTarget, table, options); +} + +status_t compileXmlFile(const sp<AaptAssets>& assets, const sp<XMLNode>& root, const sp<AaptFile>& target, ResourceTable* table, diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 60d09012beda..186c7ca8fdd8 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -37,6 +37,12 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, int options = XML_COMPILE_STANDARD_RESOURCE); status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<AaptFile>& target, + const sp<AaptFile>& outTarget, + ResourceTable* table, + int options = XML_COMPILE_STANDARD_RESOURCE); + +status_t compileXmlFile(const sp<AaptAssets>& assets, const sp<XMLNode>& xmlTree, const sp<AaptFile>& target, ResourceTable* table, |