"
*
* Optionally, the '@' symbol can be followed by one of '+' or '*'. '+' means that the resource
* will be created and added to the resource table. This is only usable with id resources. The '*',
@@ -225,10 +222,11 @@ fun parseAttributeReference(value: String): ReferenceInfo? {
* @return A [ReferenceInfo] representing the reference, or {@code null} if the input was invalid.
*
* + [ReferenceInfo.createNew] will be set if and only if a '+' followed the '@' and the reference
- * had a type of id. + [ReferenceInfo.reference] will be set as private if and only if a '*'
- * followed the '@' in the input.
+ * had a type of id.
+ * + [ReferenceInfo.reference] will be set as private if and only if a '*' followed the '@' in the
+ * input.
*/
-fun parseReference(value: String): ReferenceInfo? {
+fun parseReference(value: String) : ReferenceInfo? {
val trimmedValue = value.trim()
if (trimmedValue.isEmpty()) {
return null
@@ -271,16 +269,19 @@ data class ResourceNameInfo(val resourceName: ResourceName, val isPrivate: Boole
*
*
The resource name must be in one of the following forms:
*
- * + "" + "/" + ":" + ":/"
+ * + ""
+ * + "/"
+ * + ":"
+ * + ":/"
*
* The value may optionally be preceded by a '*' to represent that the resource name is private.
*
* @param value the value to be parsed.
* @return If parsing was successful, this function returns the [ResourceNameInfo] holding both the
- * valid [ResourceName] and whether the parsed name identifies a private resource. If the value
- * failed to parsed {@code null} is returned instead.
+ * valid [ResourceName] and whether the parsed name identifies a private resource. If the value
+ * failed to parsed {@code null} is returned instead.
*/
-fun parseResourceName(value: String): ResourceNameInfo? {
+fun parseResourceName(value: String) : ResourceNameInfo? {
if (value.isEmpty()) {
return null
@@ -307,16 +308,12 @@ fun parseResourceName(value: String): ResourceNameInfo? {
return ResourceNameInfo(
ResourceName(possibleResourceName.packageName, resourceType, possibleResourceName.entry),
- isPrivate
- )
+ isPrivate)
}
data class PossibleResourceName(
- val packageName: String,
- val typeName: String,
- val entry: String,
- val success: Boolean = true
-)
+ val packageName: String, val typeName: String, val entry: String, val success: Boolean = true)
+
fun extractResourceName(value: String): PossibleResourceName {
var packageName = ""
@@ -347,8 +344,8 @@ fun extractResourceName(value: String): PossibleResourceName {
}
val entryName = value.substring(offsetCurrent)
- val success =
- !(hasPackageSeparator && packageName.isEmpty()) && !((hasTypeSeparator) && typeName.isEmpty())
+ val success = !(hasPackageSeparator && packageName.isEmpty()) &&
+ !((hasTypeSeparator) && typeName.isEmpty())
return PossibleResourceName(packageName, typeName, entryName, success)
}
@@ -356,8 +353,7 @@ fun extractResourceName(value: String): PossibleResourceName {
fun tryParseItemForAttribute(
value: String,
resourceTypeMask: Int,
- onCreateReference: ((name: ResourceName) -> Boolean)? = null
-): Item? {
+ onCreateReference: ((name: ResourceName) -> Boolean)? = null): Item? {
val nullOrEmpty = tryParseNullOrEmpty(value)
if (nullOrEmpty != null) {
@@ -369,8 +365,8 @@ fun tryParseItemForAttribute(
reference.reference.typeFlags = resourceTypeMask
if (reference.createNew) {
val result = onCreateReference?.invoke(reference.reference.name)
- if (result != null && !result) {
- return null
+ if (result != null && !result) {
+ return null
}
}
return reference.reference
@@ -397,16 +393,13 @@ fun tryParseItemForAttribute(
}
}
- val floatMask =
- Resources.Attribute.FormatFlags.FLOAT_VALUE or
- Resources.Attribute.FormatFlags.DIMENSION_VALUE or
- Resources.Attribute.FormatFlags.FRACTION_VALUE
+ val floatMask = Resources.Attribute.FormatFlags.FLOAT_VALUE or
+ Resources.Attribute.FormatFlags.DIMENSION_VALUE or
+ Resources.Attribute.FormatFlags.FRACTION_VALUE
if ((resourceTypeMask and floatMask) != 0) {
val floatingPoint = tryParseFloat(value)
- if (
- floatingPoint != null &&
- (androidTypeToAttributeTypeMask(floatingPoint.resValue.dataType) and resourceTypeMask) != 0
- ) {
+ if (floatingPoint != null &&
+ (androidTypeToAttributeTypeMask(floatingPoint.resValue.dataType) and resourceTypeMask) != 0) {
return floatingPoint
}
}
@@ -578,16 +571,11 @@ fun parseStyleParentReference(str: String): ParsedParentInfo {
val resourceName =
ResourceName(
- possibleResourceName.packageName,
- AaptResourceType.STYLE,
- possibleResourceName.entry
- )
+ possibleResourceName.packageName, AaptResourceType.STYLE, possibleResourceName.entry)
- if (
- !hasLeadingIdentifiers &&
- resourceName.pck!!.isEmpty() &&
- possibleResourceName.typeName.isNotEmpty()
- ) {
+ if (!hasLeadingIdentifiers &&
+ resourceName.pck!!.isEmpty() &&
+ possibleResourceName.typeName.isNotEmpty()) {
val errorString = "Invalid parent reference '$str'"
return ParsedParentInfo(null, errorString)
}
@@ -596,9 +584,11 @@ fun parseStyleParentReference(str: String): ParsedParentInfo {
result.name = resourceName
result.isPrivate = privateRef
+
return ParsedParentInfo(result, "")
}
+
fun parseXmlAttributeName(str: String): Reference {
val name = str.trim()
@@ -612,10 +602,10 @@ fun parseXmlAttributeName(str: String): Reference {
var packageName = ""
var entryName = ""
- for (i in startOffset until name.length) {
+ for (i in startOffset..(name.length - 1)) {
if (name.codePointAt(i) == ':'.code) {
packageName = name.substring(startOffset, i)
- entryName = name.substring(i + 1)
+ entryName = name.substring(i+1)
}
}
@@ -642,7 +632,7 @@ fun tryParseFlagSymbol(attribute: AttributeResource, value: String): BinaryPrimi
// so we need to match against the 'entry' part of the identifier
val flagResourceName = symbol.symbol.name
if (trimmedPart == flagResourceName.entry) {
- flagsData = flagsData or symbol.value
+ flagsData = flagsData or symbol.value
flagSet = true
break
}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/ResourceValues.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/ResourceValues.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/SDKConstants.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/SDKConstants.kt
old mode 100755
new mode 100644
index 431095096..ccab0fdbe
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/SDKConstants.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/SDKConstants.kt
@@ -7,4 +7,5 @@ internal object SDKConstants {
const val SDK_LOLLIPOP = 21.toShort()
const val SDK_MARSHMALLOW = 23.toShort()
const val SDK_O = 26.toShort()
-}
\ No newline at end of file
+ const val SDK_U = 34.toShort()
+}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/Source.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/Source.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/StringPool.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/StringPool.kt
old mode 100755
new mode 100644
index 5747ce92a..d37dc392f
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/StringPool.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/StringPool.kt
@@ -175,9 +175,7 @@ class StringPool {
reAssignIndices()
}
- private fun flatten(out: BigBuffer, utf8: Boolean, logger: ILogger?): Boolean {
- var error = false
-
+ private fun flatten(out: BigBuffer, utf8: Boolean, logger: ILogger?) {
val header = ResStringPoolHeader(
ResChunkHeader(
ChunkType.STRING_POOL_TYPE.id.hostToDevice(),
@@ -208,18 +206,14 @@ class StringPool {
stringIndexBlock
.writeInt((out.size - beginStringsIndex).hostToDevice(), currentStringIndex)
currentStringIndex += 4
-
- val stringError = !encodeString(entry.value, utf8, out, logger)
- error = stringError || error
+ encodeString(entry.value, utf8, out)
}
// Strings come next
for (entry in strings) {
stringIndexBlock.writeInt((out.size - beginStringsIndex).hostToDevice(), currentStringIndex)
currentStringIndex += 4
-
- val stringError = !encodeString(entry.value, utf8, out, logger)
- error = stringError || error
+ encodeString(entry.value, utf8, out)
}
out.align4()
@@ -261,7 +255,6 @@ class StringPool {
// now we can set the size of the output in the header
header.header.size = (out.size - headerStart).hostToDevice()
encodeHeader(header, headerBlock)
- return !error
}
private fun encodeHeader(resHeader: ResStringPoolHeader, out: BigBuffer.BlockRef) {
@@ -283,21 +276,18 @@ class StringPool {
return 12
}
- private fun encodeString(
- str: String, utf8: Boolean, out: BigBuffer, logger: ILogger?): Boolean {
-
- if (utf8) {
+ private fun encodeString(str: String, utf8: Boolean, out: BigBuffer) {
+ if (utf8) {
val utf16Length = str.length
val utf8Str = str.toByteArray()
val utf8Length = utf8Str.size
// Make sure the lengths to be encoded do not exceed the maximum length that can be encoded
// using chars
- if (utf8Length > UTF8_ENCODE_LENGTH_MAX || utf16Length > UTF16_ENCODE_LENGTH_MAX) {
- val errorMsg = "String too large to encode using UTF-8. Writing the string instead as '%s'."
- logger?.error(null, errorMsg, STRING_TOO_LARGE)
- encodeString(STRING_TOO_LARGE, utf8, out, logger)
- return false
+ if (utf8Length > UTF8_ENCODE_LENGTH_MAX ) {
+ error("String of size $utf8Length bytes is too large to encode using UTF-8 " +
+ "($UTF8_ENCODE_LENGTH_MAX bytes). " +
+ "Affected string begins with: '${str.take(STRING_PREFIX_LENGTH_FOR_ERRORS)}'...")
}
val blockSize = getLengthUtf8(utf8Length) + getLengthUtf8(utf16Length) + utf8Length + 1
@@ -319,20 +309,15 @@ class StringPool {
// Now write null terminator
stringBlock.writeByte(0x00, locationToWrite)
-
- return true
} else {
val utf16Length = str.length
// Make sure the length to be encoded does not exceed the maximum possible length that can be
// encoded
if (utf16Length > UTF16_ENCODE_LENGTH_MAX) {
- val errorMsg =
- "String too large to encode using UTF-16. Writing the string instead as '%s'."
- logger?.error(null, errorMsg, STRING_TOO_LARGE)
-
- encodeString(STRING_TOO_LARGE, utf8, out, logger)
- return false
+ error("String of size ${str.toByteArray().size} is too large to encode using " +
+ "UTF-16 ($UTF16_ENCODE_LENGTH_MAX bytes). " +
+ "Affected string begins with: '${str.take(STRING_PREFIX_LENGTH_FOR_ERRORS)}'...")
}
val blockSize = getLengthUtf16(utf16Length) + utf16Length*2 + 2
@@ -351,7 +336,6 @@ class StringPool {
// now write null terminator
stringBlock.writeShort(0x0000.toShort(), locationToWrite)
- return true
}
}
@@ -422,7 +406,9 @@ class StringPool {
const val TWO_CHAR_UTF16_LENGTH_SIGNIFIER = 0x8000
const val ONE_CHAR_UTF16_ENCODE_LENGTH_MAX = 0x7fff
- private const val STRING_TOO_LARGE = "STRING_TOO_LARGE"
+ // The maximum number of chars that will be presented to the user if the size of the string
+ // exceeds the maximum permitted utf-8 or utf-16 byte size.
+ const val STRING_PREFIX_LENGTH_FOR_ERRORS = 42
val ENTRY_ON_VALUE = compareBy {it.value}
val STYLE_ON_VALUE = compareBy {it.value}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/TableExtractor.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/TableExtractor.kt
old mode 100755
new mode 100644
index 427092e3c..089938485
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/TableExtractor.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/TableExtractor.kt
@@ -3,6 +3,7 @@ package com.android.aaptcompiler
import com.android.aapt.Resources
import com.android.aaptcompiler.android.stringToInt
import com.itsaky.androidide.layoutlib.resources.ResourceVisibility
+import java.io.InputStream
import jaxp.xml.XMLConstants
import jaxp.xml.namespace.QName
import jaxp.xml.stream.XMLEventReader
@@ -12,7 +13,6 @@ import jaxp.xml.stream.events.Attribute
import jaxp.xml.stream.events.Comment
import jaxp.xml.stream.events.StartElement
import jaxp.xml.stream.events.XMLEvent
-import java.io.InputStream
/**
* Namespace uri for the xliff:g tag in XML.
@@ -25,17 +25,14 @@ private const val XLIFF_NS_URI = "urn:oasis:names:tc:xliff:document:1.2"
/**
* Resource parsed from the XML, with all relevant metadata.
*
- * @property config The config description of the resource. This should be the same as the config of
- * the source.
+ * @property config The config description of the resource. This should be the same as the config
+ * of the source.
* @property source The start location in the xml from which this resource was extracted.
* @property comment The comment describing the resource that appeared before it in the xml. This
- * will be an empty string if no comment was supplied.
+ * will be an empty string if no comment was supplied.
*/
private class ParsedResource(
- var config: ConfigDescription,
- val source: Source,
- val comment: String
-) {
+ var config: ConfigDescription, val source: Source, val comment: String) {
constructor() : this(ConfigDescription(), Source(""), "")
@@ -55,10 +52,10 @@ private class ParsedResource(
*/
var overlayableItem: OverlayableItem? = null
/**
- * The value of the resource, this might be null if this is a use of a resource. (i.e. an
- * within a
+ * The value of the resource, this might be null if this is a use of a resource. (i.e. an
+ * within a
*/
- var value: Value? = null
+ var value : Value? = null
/**
* The child resources of the given resource. These resources will be added to the table when
* {@code this} is added. The connection of the resources to this resource should be reflected in
@@ -73,17 +70,16 @@ private class ParsedResource(
* @property translatable Whether the default setting for this parser is to allow translation.
*
* @property errorOnPositionalArgs Whether positional arguments in formatted strings are treated as
- * errors or warnings.
+ * errors or warnings.
*
* @property visibility the default visibility of resources extracted. If non-null, all new
- * resources are set with this visibility, and will error if trying to parse the ,
- * , or tags.
+ * resources are set with this visibility, and will error if trying to parse the ,
+ * , or tags.
*/
data class TableExtractorOptions(
val translatable: Boolean = true,
val errorOnPositionalArgs: Boolean = true,
- val visibility: ResourceVisibility? = null
-)
+ val visibility: ResourceVisibility? = null)
/** Returns true if the element is or and can be safely ignored */
fun shouldIgnoreElement(elementName: QName): Boolean {
@@ -129,9 +125,9 @@ fun parseFormatAttribute(value: String): Int {
* Primarily, as each resource needs to be parsed, the name, package, and type of resource is
* extracted.
*
- *
Then, if an item, a call to [parseItem] is invoked with a type mask of the valid types the
- * xml element can be parsed as. This will result in a more specialized call to [parseXml] which
- * will proceed to flatten the xml subtree of the item (which may include span tags and
+ *
Then, if an item, a call to [parseItem] is invoked with a type mask of the valid types
+ * the xml element can be parsed as. This will result in a more specialized call to [parseXml]
+ * which will proceed to flatten the xml subtree of the item (which may include span tags and
* untranslatable section tags) and then attempt to process the flattened xml string (in accordance
* with the valid types specified by the type mask). Finally, the parsed resource value will be
* added to [ResourceTable], if successful.
@@ -152,11 +148,10 @@ class TableExtractor(
val source: Source,
val config: ConfigDescription,
val options: TableExtractorOptions,
- val logger: BlameLogger
-) {
+ val logger: BlameLogger) {
fun extract(inputFile: InputStream) {
- var eventReader: XMLEventReader? = null
+ var eventReader : XMLEventReader? = null
try {
eventReader = xmlInputFactory.createXMLEventReader(inputFile)
@@ -167,7 +162,7 @@ class TableExtractor(
}
var rootStart: XMLEvent? = null
- while (eventReader.hasNext()) {
+ while(eventReader.hasNext()) {
rootStart = eventReader.nextEvent()
// ignore comments and text before the root tag
if (rootStart.isStartElement) {
@@ -179,13 +174,15 @@ class TableExtractor(
val rootName = rootStart.asStartElement().name
if (rootName.namespaceURI != null && rootName.localPart != "resources") {
val userReadableSource = logger.getOriginalSource(blameSource(source)).toString().trim()
- error("Root xml element of resource table not labeled 'resources' ($userReadableSource).")
+ error(
+ "Root xml element of resource table not labeled 'resources' ($userReadableSource)."
+ )
}
extractResourceValues(eventReader)
} catch (xmlException: XMLStreamException) {
if (xmlException.message?.contains("Premature end of file.", true) != true) {
- // Having no root is not an error, but any other xml format exception is.
- throw xmlException
+ // Having no root is not an error, but any other xml format exception is.
+ throw xmlException
}
} finally {
eventReader?.close()
@@ -193,7 +190,7 @@ class TableExtractor(
}
private fun logError(source: BlameLogger.Source, message: String) {
- logger.error(message, source)
+ logger.error(message, source)
}
/**
@@ -234,7 +231,7 @@ class TableExtractor(
if (!event.isStartElement) {
errors +=
- "Unexpected element type: ${event.eventType}, ${blameSource(source, event.location)}."
+ "Unexpected element type: ${event.eventType}, ${blameSource(source, event.location)}."
}
val element = event.asStartElement()
@@ -270,26 +267,25 @@ class TableExtractor(
}
}
if (errors.any()) {
- error(errors.joinToString(separator = ","))
+ error(errors.joinToString(separator = ","))
}
}
/**
* Extracts the [Value] of a resource from the given element. This can be either an [Item] or a
- * nested value type.
+ * nested value type.
*
* @param element The start of the element to be translated as a [Value].
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource The [ParsedResource] to hold the extracted value upon success.
* @return Whether or not the parsing was a success.
*/
private fun extractResource(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element : StartElement,
+ eventReader : XMLEventReader,
+ parsedResource : ParsedResource): Boolean {
var resourceTypeName = element.name.localPart
@@ -311,8 +307,7 @@ class TableExtractor(
if (resourceFormat == 0) {
logError(
blameSource(parsedResource.source),
- "Resource has an invalid format of ${formatAttribute.value}."
- )
+ "Resource has an invalid format of ${formatAttribute.value}.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -326,6 +321,7 @@ class TableExtractor(
return false
}
resourceTypeName = typeAttribute.value
+
} else if (resourceTypeName == "bag") {
canBeItem = false
@@ -345,9 +341,7 @@ class TableExtractor(
if (resourceTypeName == "id") {
if (nameAttribute == null) {
logError(
- blameSource(parsedResource.source),
- "<${element.name}> is missing the 'name' attribute."
- )
+ blameSource(parsedResource.source), "<${element.name}> is missing the 'name' attribute.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -371,8 +365,7 @@ class TableExtractor(
// if an inner element exists, the inner element must be a reference to another id
logError(
blameSource(parsedResource.source),
- "<${element.name}> inner element must either be a resource reference or empty."
- )
+ "<${element.name}> inner element must either be a resource reference or empty.")
return false
}
}
@@ -380,43 +373,39 @@ class TableExtractor(
}
if (canBeItem) {
- val (type, typeMask) =
- when (resourceTypeName) {
- "bool" -> Pair(AaptResourceType.BOOL, Resources.Attribute.FormatFlags.BOOLEAN_VALUE)
- "color" -> Pair(AaptResourceType.COLOR, Resources.Attribute.FormatFlags.COLOR_VALUE)
- "configVarying" ->
- Pair(AaptResourceType.CONFIG_VARYING, Resources.Attribute.FormatFlags.ANY_VALUE)
- "dimen" ->
- Pair(
- AaptResourceType.DIMEN,
- Resources.Attribute.FormatFlags.FLOAT_VALUE or
- Resources.Attribute.FormatFlags.FRACTION_VALUE or
- Resources.Attribute.FormatFlags.DIMENSION_VALUE
- )
- "drawable" -> Pair(AaptResourceType.DRAWABLE, Resources.Attribute.FormatFlags.COLOR_VALUE)
- "fraction" ->
- Pair(
- AaptResourceType.FRACTION,
- Resources.Attribute.FormatFlags.FLOAT_VALUE or
- Resources.Attribute.FormatFlags.FRACTION_VALUE or
- Resources.Attribute.FormatFlags.DIMENSION_VALUE
- )
- "integer" -> Pair(AaptResourceType.INTEGER, Resources.Attribute.FormatFlags.INTEGER_VALUE)
- "string" -> Pair(AaptResourceType.STRING, Resources.Attribute.FormatFlags.STRING_VALUE)
- else -> Pair(null, Resources.Attribute.FormatFlags.ANY_VALUE)
- }
+ val (type, typeMask) = when (resourceTypeName) {
+ "bool" -> Pair(AaptResourceType.BOOL, Resources.Attribute.FormatFlags.BOOLEAN_VALUE)
+ "color" -> Pair(AaptResourceType.COLOR, Resources.Attribute.FormatFlags.COLOR_VALUE)
+ "configVarying" ->
+ Pair(AaptResourceType.CONFIG_VARYING, Resources.Attribute.FormatFlags.ANY_VALUE)
+ "dimen" ->
+ Pair(
+ AaptResourceType.DIMEN,
+ Resources.Attribute.FormatFlags.FLOAT_VALUE or
+ Resources.Attribute.FormatFlags.FRACTION_VALUE or
+ Resources.Attribute.FormatFlags.DIMENSION_VALUE)
+ "drawable" -> Pair(AaptResourceType.DRAWABLE, Resources.Attribute.FormatFlags.COLOR_VALUE)
+ "fraction" ->
+ Pair(
+ AaptResourceType.FRACTION,
+ Resources.Attribute.FormatFlags.FLOAT_VALUE or
+ Resources.Attribute.FormatFlags.FRACTION_VALUE or
+ Resources.Attribute.FormatFlags.DIMENSION_VALUE)
+ "integer" -> Pair(AaptResourceType.INTEGER, Resources.Attribute.FormatFlags.INTEGER_VALUE)
+ "string" -> Pair(AaptResourceType.STRING, Resources.Attribute.FormatFlags.STRING_VALUE)
+ else -> Pair(null, Resources.Attribute.FormatFlags.ANY_VALUE)
+ }
if (type != null) {
// this is an item record its type and format and start parsing.
if (nameAttribute == null) {
logError(
blameSource(parsedResource.source),
- "<${element.name}> is missing the 'name' attribute."
- )
+ "<${element.name}> is missing the 'name' attribute.")
walkToEndOfElement(element, eventReader)
return false
}
- parsedResource.name = ResourceName("", type, nameAttribute.value)
+ parsedResource.name = ResourceName( "", type, nameAttribute.value)
// Only use the implied format of the type when there is no explicit format.
if (resourceFormat == 0) {
@@ -427,25 +416,24 @@ class TableExtractor(
}
if (canBeBag) {
- val parseBagMethod =
- when (resourceTypeName) {
- "add-resource" -> ::parseAddResource
- "array" -> ::parseArray
- "attr" -> ::parseAttr
- "configVarying" -> ::parseConfigVarying
- "declare-styleable" -> ::parseDeclareStyleable
- "integer-array" -> ::parseIntegerArray
- "java-symbol" -> ::parseSymbol
- "macro" -> ::parseMacro
- "overlayable" -> ::parseOverlayable
- "plurals" -> ::parsePlural
- "public" -> ::parsePublic
- "public-group" -> ::parsePublicGroup
- "string-array" -> ::parseStringArray
- "style" -> ::parseStyle
- "symbol" -> ::parseSymbol
- else -> null
- }
+ val parseBagMethod = when(resourceTypeName) {
+ "add-resource" -> ::parseAddResource
+ "array" -> ::parseArray
+ "attr" -> ::parseAttr
+ "configVarying" -> ::parseConfigVarying
+ "declare-styleable" -> ::parseDeclareStyleable
+ "integer-array" -> ::parseIntegerArray
+ "java-symbol" -> ::parseSymbol
+ "macro" -> ::parseMacro
+ "overlayable" -> ::parseOverlayable
+ "plurals" -> ::parsePlural
+ "public" -> ::parsePublic
+ "public-group" -> ::parsePublicGroup
+ "string-array" -> ::parseStringArray
+ "style" -> ::parseStyle
+ "symbol" -> ::parseSymbol
+ else -> null
+ }
if (parseBagMethod != null) {
// ensure we have a name (unless this is a or ).
@@ -454,17 +442,17 @@ class TableExtractor(
walkToEndOfElement(element, eventReader)
logError(
blameSource(parsedResource.source),
- "<${element.name}> is missing the 'name' attribute."
- )
+ "<${element.name}> is missing the 'name' attribute.")
return false
}
- parsedResource.name = parsedResource.name.copy(entry = nameAttribute.value)
+ parsedResource.name = parsedResource.name.copy(entry=nameAttribute.value)
}
// Call the associated parse method. The type will be filled in by the parse function
return parseBagMethod(element, eventReader, parsedResource)
}
+
}
if (canBeItem) {
@@ -473,8 +461,7 @@ class TableExtractor(
if (nameAttribute == null) {
logError(
blameSource(parsedResource.source),
- "<${element.name}> is missing the 'name' attribute."
- )
+ "<${element.name}> is missing the 'name' attribute.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -486,8 +473,7 @@ class TableExtractor(
if (parsedResource.value == null) {
logError(
blameSource(parsedResource.source),
- "Invalid value for type '${parsedType.tagName}'. Expected a reference."
- )
+ "Invalid value for type '${parsedType.tagName}'. Expected a reference.")
return false
}
@@ -504,24 +490,23 @@ class TableExtractor(
* Parses the XML subtree and returns an Item.
*
* @param element The start of the element to be translated as an item type.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param resourceFormat A type mask that specifies which formats are valid for the xml to be
- * interpreted as.
+ * interpreted as.
* @param allowRawString If true, a [RawString] representing the xml is returned if it could not
- * be parsed as any valid resource [Item]. If false, {@code null} will be returned instead on
- * failure.
+ * be parsed as any valid resource [Item]. If false, {@code null} will be returned instead on
+ * failure.
*
* @return The [Item] that represents the xml subtree. This will be {@code null} if the xml failed
- * to be interpreted as a valid resource.
+ * to be interpreted as a valid resource.
*/
private fun parseXml(
element: StartElement,
eventReader: XMLEventReader,
resourceFormat: Int,
- allowRawString: Boolean
- ): Item? {
+ allowRawString : Boolean) : Item? {
val flattenedXml = flattenXmlSubTree(element, eventReader)
if (!flattenedXml.success) {
@@ -533,10 +518,8 @@ class TableExtractor(
return StyledString(
table.stringPool.makeRef(
flattenedXml.styleString,
- StringPool.Context(StringPool.Context.Priority.NORMAL.priority, config)
- ),
- flattenedXml.untranslatableSections
- )
+ StringPool.Context(StringPool.Context.Priority.NORMAL.priority, config)),
+ flattenedXml.untranslatableSections)
}
// Process the raw value
@@ -559,9 +542,9 @@ class TableExtractor(
if (resourceFormat and Resources.Attribute.FormatFlags.STRING_VALUE != 0) {
// use trimmed escaped string.
return BasicString(
- table.stringPool.makeRef(flattenedXml.styleString.str, StringPool.Context(config = config)),
- flattenedXml.untranslatableSections
- )
+ table.stringPool.makeRef(
+ flattenedXml.styleString.str, StringPool.Context(config = config)),
+ flattenedXml.untranslatableSections)
}
// if the text is empty, and the value is not allowed to be a string, encode it as a @null.
@@ -570,21 +553,20 @@ class TableExtractor(
}
if (allowRawString) {
- val raw =
- flattenedXml.rawString.let { raw ->
- // Remove space, newline character wrapping (typically due to IDE formatting)
- // and user added quotations for styleable children due to lack of type.
- val isNotWrappingChar: (Char) -> Boolean = { it !in setOf(' ', '\n') }
- val firstNonWrappingIndex = raw.indexOfFirst(isNotWrappingChar)
- val lastNonWrappingIndex = raw.indexOfLast(isNotWrappingChar)
- raw
- .substring(
- if (firstNonWrappingIndex == -1) 0 else firstNonWrappingIndex,
- if (lastNonWrappingIndex == -1) 0 else lastNonWrappingIndex + 1
+ val raw = flattenedXml.rawString.let { raw ->
+ // Remove space, newline character wrapping (typically due to IDE formatting)
+ // and user added quotations for styleable children due to lack of type.
+ val isNotWrappingChar: (Char) -> Boolean = { it !in setOf(' ', '\n') }
+ val firstNonWrappingIndex = raw.indexOfFirst(isNotWrappingChar)
+ val lastNonWrappingIndex = raw.indexOfLast(isNotWrappingChar)
+ raw.substring(
+ if (firstNonWrappingIndex == - 1) 0 else firstNonWrappingIndex,
+ if (lastNonWrappingIndex == - 1) 0 else lastNonWrappingIndex + 1
)
- .removeSurrounding("\"")
+ .removeSurrounding("\"")
}
- return RawString(table.stringPool.makeRef(raw, StringPool.Context(config = config)))
+ return RawString(
+ table.stringPool.makeRef(raw, StringPool.Context(config=config)))
}
return null
@@ -594,20 +576,19 @@ class TableExtractor(
* Attempts to parse the xml subtree as an item resource.
*
* @param element The start of the element to be translated as an item type.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource The resource to put the parsed [Item] into, if successful.
* @param resourceFormat A type mask that specifies which formats are valid for the xml to be
- * interpreted as.
+ * interpreted as.
* @return Whether or not the xml could be parsed.
*/
private fun parseItem(
element: StartElement,
eventReader: XMLEventReader,
parsedResource: ParsedResource,
- resourceFormat: Int
- ): Boolean {
+ resourceFormat: Int) : Boolean {
if (resourceFormat == Resources.Attribute.FormatFlags.STRING_VALUE) {
return parseString(element, eventReader, parsedResource)
@@ -617,8 +598,7 @@ class TableExtractor(
if (parsedResource.value == null) {
logError(
blameSource(parsedResource.source),
- "Invalid <${parsedResource.name.type.tagName}> for given resource value."
- )
+ "Invalid <${parsedResource.name.type.tagName}> for given resource value.")
return false
}
return true
@@ -629,18 +609,15 @@ class TableExtractor(
* translatable.
*
* @param element The start of the element to be translated at a string.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource the resource to put the parsed String into. The [ParsedResource.value]
- * will be set to either a [BasicString] or [StyleString] resource, if successful.
+ * will be set to either a [BasicString] or [StyleString] resource, if successful.
* @return Whether or not the element could be parsed as a String resource.
*/
private fun parseString(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
var formatted = true
val formattedAttribute = element.getAttributeByName(QName("formatted"))
if (formattedAttribute != null) {
@@ -649,8 +626,7 @@ class TableExtractor(
logError(
blameSource(parsedResource.source),
"Invalid value for the 'formatted' attribute. " +
- "Was '${formattedAttribute.value}', must be a boolean."
- )
+ "Was '${formattedAttribute.value}', must be a boolean.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -665,20 +641,17 @@ class TableExtractor(
logError(
blameSource(parsedResource.source),
"Invalid value for 'translatable' attribute. " +
- "Was '${translatableAttribute.value}', must be a boolean."
- )
+ "Was '${translatableAttribute.value}', must be a boolean.")
walkToEndOfElement(element, eventReader)
return false
}
translatable = maybeTranslatable
}
- val value = parseXml(element, eventReader, Resources.Attribute.FormatFlags.STRING_VALUE, false)
+ val value =
+ parseXml(element, eventReader, Resources.Attribute.FormatFlags.STRING_VALUE, false)
if (value == null) {
- logError(
- blameSource(parsedResource.source),
- "${parsedResource.name} does not contain a valid string resource."
- )
+ logError( blameSource(parsedResource.source), "${parsedResource.name} does not contain a valid string resource.")
return false
}
@@ -687,9 +660,8 @@ class TableExtractor(
if (formatted && translatable) {
if (!verifyJavaStringFormat(value.toString())) {
- val errorMsg =
- "Multiple substitutions specified in non-positional format of string " +
- "resource ${parsedResource.name}. Did you mean to add the formatted=\"false\" attribute?"
+ val errorMsg = "Multiple substitutions specified in non-positional format of string " +
+ "resource ${parsedResource.name}. Did you mean to add the formatted=\"false\" attribute?"
if (options.errorOnPositionalArgs) {
logError(blameSource(parsedResource.source), errorMsg)
return false
@@ -708,18 +680,15 @@ class TableExtractor(
* Parses the xml element specified by {@code element} as a Enum or Flag value of an Attribute.
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param tag The name of the flag or enum item.
* @return The child resource if the parsing was successful, or {@code null} if the parsing
- * failed.
+ * failed.
*/
private fun parseEnumOrFlagItem(
- element: StartElement,
- eventReader: XMLEventReader,
- tag: String
- ): AttributeResource.Symbol? {
+ element: StartElement, eventReader: XMLEventReader, tag: String): AttributeResource.Symbol? {
val elementSource = source.withLine(element.location.lineNumber)
walkToEndOfElement(element, eventReader)
@@ -739,9 +708,7 @@ class TableExtractor(
val resValue = stringToInt(valueAttribute.value)
if (resValue == null) {
logError(
- blameSource(elementSource),
- "Invalid value '$resValue' for <$tag>. Must be an integer."
- )
+ blameSource(elementSource), "Invalid value '$resValue' for <$tag>. Must be an integer.")
return null
}
@@ -754,18 +721,15 @@ class TableExtractor(
* Parses the xml element specified by {@code element} as an [Item] under the style.
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param style The parent style of which this resource is a part.
* @return The child resource if the parsing was successful, or {@code null} if the parsing
- * failed.
+ * failed.
*/
private fun parseStyleItem(
- element: StartElement,
- eventReader: XMLEventReader,
- style: Style
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, style: Style): Boolean {
val itemSource = source.withLine(element.location.lineNumber)
val nameAttribute = element.getAttributeByName(QName("name"))
@@ -784,8 +748,7 @@ class TableExtractor(
if (xmlItem == null) {
logError(
blameSource(source, element.location),
- "Could not parse style item with name '${nameAttribute.value}'."
- )
+ "Could not parse style item with name '${nameAttribute.value}'.")
return false
}
@@ -798,24 +761,20 @@ class TableExtractor(
* formatting).
*
* @param eventReader the xml to flattened. The reader should have just read the start of the
- * element that is needed to be flattened. After this method is invoked, the event reader will be
- * after the end of the element that the flattened xml is to represent.
- * @return If Parsing fails, the [FlattenedXml.success] fill be set to false and the rest of
- * the flattened xml will be left in a unspecified state.
Otherwise:
- * [FlattenedXml.styleString] contains the escaped and whitespace trimmed text with included
- * ```
- * spans. [FlattenedXml.rawString]
- * ```
- * contains the unescaped text. [FlattenedXml.untranslatableSections] contains the sections of the
- * string that should not be
- * ```
+ * element that is needed to be flattened. After this method is invoked, the event reader will
+ * be after the end of the element that the flattened xml is to represent.
+ * @return
+ *
If Parsing fails, the [FlattenedXml.success] fill be set to false and the rest of the
+ * flattened xml will be left in a unspecified state.
+ *
Otherwise:
+ * [FlattenedXml.styleString] contains the escaped and whitespace trimmed text with included
+ * spans.
+ * [FlattenedXml.rawString] contains the unescaped text.
+ * [FlattenedXml.untranslatableSections] contains the sections of the string that should not be
* translated.
- * ```
*/
private fun flattenXmlSubTree(
- startElement: StartElement,
- eventReader: XMLEventReader
- ): FlattenedXml {
+ startElement: StartElement, eventReader: XMLEventReader) : FlattenedXml {
var depth = 1
@@ -826,6 +785,7 @@ class TableExtractor(
when {
event.isCharacters -> builder.append(event.asCharacters().data)
+
event.isStartElement -> {
val element = event.asStartElement()
@@ -853,9 +813,9 @@ class TableExtractor(
// besides XLIFF, any other namespaced tags are unsupported and ignored.
logger?.warning(
"Ignoring element '$elementName' with unknown namespace '${elementName.namespaceURI}'.",
- blameSource(source.withLine(element.location.lineNumber))
- )
+ blameSource(source.withLine(element.location.lineNumber)))
}
+
}
++depth
}
@@ -886,8 +846,7 @@ class TableExtractor(
val resourceName = startElement.getAttributeByName(QName("name")).value
logError(
blameSource(source, startElement.location),
- "Failed to flatten XML for resource '$resourceName' with error: ${builder.error}"
- )
+ "Failed to flatten XML for resource '$resourceName' with error: ${builder.error}")
}
return flattenedXml
}
@@ -896,32 +855,27 @@ class TableExtractor(
* Parses the xml with a "symbol" tag
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the parsed symbol will be stored, if the parsing was successful.
* @return Whether of not the parsing was successful.
*/
private fun parseSymbol(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
var error = false
if (options.visibility != null) {
logError(
blameSource(source, element.location),
- " and tags are not supported with resource visibility."
- )
+ " and tags are not supported with resource visibility.")
error = true
}
// Symbols should have the default config
if (parsedResource.config != ConfigDescription()) {
logger?.warning(
- "Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ "Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
+ blameSource(source, element.location))
}
if (!parseSymbolImpl(element, eventReader, parsedResource)) {
@@ -933,10 +887,7 @@ class TableExtractor(
}
private fun parseMacro(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
parsedResource.name = parsedResource.name.copy(type = AaptResourceType.MACRO)
// Macros can only be defined in the default config
@@ -944,19 +895,17 @@ class TableExtractor(
if (parsedResource.config != defaultConfig) {
logError(
blameSource(source, element.location),
- " tags cannot be declared in configurations other than the default configuration"
- )
+ " tags cannot be declared in configurations other than the default configuration")
return false
}
val flattenedXml = flattenXmlSubTree(element, eventReader)
if (!flattenedXml.success) {
- return false
+ return false
}
// TODO(198264572): extract namespaces
- parsedResource.value =
- Macro(flattenedXml.rawString, flattenedXml.styleString, flattenedXml.untranslatableSections)
+ parsedResource.value = Macro(flattenedXml.rawString, flattenedXml.styleString, flattenedXml.untranslatableSections)
return true
}
@@ -965,17 +914,14 @@ class TableExtractor(
* Parses the xml with an "add-resource" tag.
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the parsed symbol will be stored, if the parsing was successful.
* @return Whether of not the parsing was successful.
*/
private fun parseAddResource(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
if (parseSymbolImpl(element, eventReader, parsedResource)) {
parsedResource.visibility = ResourceVisibility.UNDEFINED
parsedResource.allowNew = true
@@ -985,28 +931,24 @@ class TableExtractor(
}
/**
- * Parses the xml as a Symbol represented by the specified start element. Then, stores the value
- * in the parsed resource.
+ * Parses the xml as a Symbol represented by the specified start element. Then, stores the
+ * value in the parsed resource.
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the parsed symbol will be stored, if the parsing was successful.
* @return Whether of not the parsing was successful.
*/
private fun parseSymbolImpl(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
val typeAttribute = element.getAttributeByName(QName("type"))
if (typeAttribute == null) {
walkToEndOfElement(element, eventReader)
logError(
blameSource(source, element.location),
- "<${element.name}> must have a 'type' attribute."
- )
+ "<${element.name}> must have a 'type' attribute.")
return false
}
@@ -1015,8 +957,7 @@ class TableExtractor(
walkToEndOfElement(element, eventReader)
logError(
blameSource(source, element.location),
- "Invalid resource type '${typeAttribute.value}' in <${element.name}> resource."
- )
+ "Invalid resource type '${typeAttribute.value}' in <${element.name}> resource.")
return false
}
@@ -1029,26 +970,24 @@ class TableExtractor(
* Parses the xml represented by the "attr" tag.
*
* @param element The start element that represents the [AttributeResource] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the [AttributeResource] will be stored, if successful.
* @return Whether of not the parsing was successful.
*/
private fun parseAttr(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean = parseAttrImpl(element, eventReader, parsedResource, false)
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean =
+ parseAttrImpl(element, eventReader, parsedResource, false)
/**
* parses the xml as a [AttributeResource] represented by the specified start element. Then stores
* the value in the parsed resource.
*
* @param element The start element that represents the symbol to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the parsed symbol will be stored, if the parsing was successful.
* @param isWeak whether or not the resource should be parsed as a weak attr (declaration).
* @return Whether of not the parsing was successful.
@@ -1057,8 +996,7 @@ class TableExtractor(
element: StartElement,
eventReader: XMLEventReader,
parsedResource: ParsedResource,
- isWeak: Boolean
- ): Boolean {
+ isWeak: Boolean): Boolean {
parsedResource.name = parsedResource.name.copy(type = AaptResourceType.ATTR)
// Attributes only end up in default configuration
@@ -1066,8 +1004,7 @@ class TableExtractor(
if (parsedResource.config != defaultConfig) {
logger?.warning(
"Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ blameSource(source, element.location))
parsedResource.config = defaultConfig
}
@@ -1079,8 +1016,7 @@ class TableExtractor(
if (typeMask == 0) {
logError(
blameSource(source, element.location),
- "Invalid attribute format '${formatAttribute.value}'"
- )
+ "Invalid attribute format '${formatAttribute.value}'")
walkToEndOfElement(element, eventReader)
return false
}
@@ -1104,8 +1040,7 @@ class TableExtractor(
if (min == null) {
logError(
blameSource(source, element.location),
- "Invalid 'min' value '$minString'. Integer value required."
- )
+ "Invalid 'min' value '$minString'. Integer value required.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -1123,21 +1058,17 @@ class TableExtractor(
if (max == null) {
logError(
blameSource(source, element.location),
- "Invalid 'max' value '$maxString'. Integer value required."
- )
+ "Invalid 'max' value '$maxString'. Integer value required.")
walkToEndOfElement(element, eventReader)
return false
}
}
- if (
- (min != null || max != null) &&
- (typeMask and Resources.Attribute.FormatFlags.INTEGER_VALUE) == 0
- ) {
+ if ((min != null || max != null) &&
+ (typeMask and Resources.Attribute.FormatFlags.INTEGER_VALUE) == 0) {
logError(
blameSource(source, element.location),
- "'min' and 'max' attributes can only be used with format='integer' on <${element.name}> resource"
- )
+ "'min' and 'max' attributes can only be used with format='integer' on <${element.name}> resource")
walkToEndOfElement(element, eventReader)
return false
}
@@ -1167,18 +1098,15 @@ class TableExtractor(
val childSource = source.withLine(event.location.lineNumber)
val childName = childElement.name
- if (
- childName.namespaceURI.isEmpty() &&
- (childName.localPart == "flag" || childName.localPart == "enum")
- ) {
+ if (childName.namespaceURI.isEmpty() &&
+ (childName.localPart == "flag" || childName.localPart == "enum")) {
var itemError = false
when (childName.localPart) {
"enum" -> {
if ((typeMask and Resources.Attribute.FormatFlags.FLAGS_VALUE) != 0) {
logError(
blameSource(source, childElement.location),
- "Cannot define both and under the same <${element.name}> resource."
- )
+ "Cannot define both and under the same <${element.name}> resource.")
error = true
itemError = true
}
@@ -1188,8 +1116,7 @@ class TableExtractor(
if ((typeMask and Resources.Attribute.FormatFlags.ENUM_VALUE) != 0) {
logError(
blameSource(source, childElement.location),
- "Cannot define both and under the same <${element.name}> resource."
- )
+ "Cannot define both and under the same <${element.name}> resource.")
error = true
itemError = true
}
@@ -1222,7 +1149,7 @@ class TableExtractor(
?: blameSource(symbolMap[symbolName]!!.symbol.source)
val errorMsg =
"Duplicate symbol '$symbolName' defined here: $newSource" +
- " and here: $previousSource"
+ " and here: $previousSource"
logError(blameSource(symbol.symbol.source), errorMsg)
error = true
}
@@ -1230,12 +1157,11 @@ class TableExtractor(
} else {
error = true
}
- } else {
+ } else{
if (!shouldIgnoreElement(childName)) {
logError(
blameSource(childSource),
- "Unrecognized tag <$childName> of child element of <${element.name}>."
- )
+ "Unrecognized tag <$childName> of child element of <${element.name}>.")
error = true
}
walkToEndOfElement(childElement, eventReader)
@@ -1247,8 +1173,8 @@ class TableExtractor(
return false
}
- val resource =
- AttributeResource(if (typeMask == 0) Resources.Attribute.FormatFlags.ANY_VALUE else typeMask)
+ val resource = AttributeResource(
+ if (typeMask == 0) Resources.Attribute.FormatFlags.ANY_VALUE else typeMask)
resource.weak = isWeak
resource.symbols.addAll(symbolMap.values)
resource.minInt = min ?: Int.MIN_VALUE
@@ -1262,16 +1188,13 @@ class TableExtractor(
* parsed from the format attribute of {@code element}
*
* @param element The start element of the [ArrayResource] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the read resource will be placed.
*/
private fun parseArray(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
var resourceFormat = Resources.Attribute.FormatFlags.ANY_VALUE
val formatAttribute = element.getAttributeByName(QName("format"))
if (formatAttribute != null) {
@@ -1279,8 +1202,7 @@ class TableExtractor(
if (resourceFormat == 0) {
logError(
blameSource(source, element.location),
- "Invalid format value: '${formatAttribute.value}'."
- )
+ "Invalid format value: '${formatAttribute.value}'.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -1292,62 +1214,47 @@ class TableExtractor(
* Parse the xml that is contained by the "integer-array" tag.
*
* @param element The start element of the [ArrayResource] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the read resource will be placed.
*/
private fun parseIntegerArray(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ) =
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource) =
parseArrayImpl(
- element,
- eventReader,
- parsedResource,
- Resources.Attribute.FormatFlags.INTEGER_VALUE
- )
+ element, eventReader, parsedResource, Resources.Attribute.FormatFlags.INTEGER_VALUE)
/**
* Parse the xml that is contained by the "string-array" tag.
*
* @param element The start element of the [ArrayResource] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the read resource will be placed.
*/
private fun parseStringArray(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ) =
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource) =
parseArrayImpl(
- element,
- eventReader,
- parsedResource,
- Resources.Attribute.FormatFlags.STRING_VALUE
- )
+ element, eventReader, parsedResource, Resources.Attribute.FormatFlags.STRING_VALUE)
/**
* Parse the xml as an [ArrayResource].
*
* @param element The start element of the [ArrayResource] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource where the read resource will be placed.
* @param resourceFormat A type mask that specifies which formats are valid for the child elements
- * of the array to be interpreted as.
+ * of the array to be interpreted as.
* @return Whether or not the parsing was successful.
*/
private fun parseArrayImpl(
element: StartElement,
eventReader: XMLEventReader,
parsedResource: ParsedResource,
- resourceFormat: Int
- ): Boolean {
+ resourceFormat: Int): Boolean {
parsedResource.name = parsedResource.name.copy(type = AaptResourceType.ARRAY)
@@ -1360,8 +1267,7 @@ class TableExtractor(
if (translatableValue == null) {
logError(
blameSource(parsedResource.source),
- "Invalid value for 'translatable' attribute. Must be a boolean."
- )
+ "Invalid value for 'translatable' attribute. Must be a boolean.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -1397,9 +1303,7 @@ class TableExtractor(
}
!shouldIgnoreElement(childName) -> {
logError(
- blameSource(childSource),
- "Unknown tag <$childName> in <${element.name}> resource."
- )
+ blameSource(childSource), "Unknown tag <$childName> in <${element.name}> resource.")
error = true
walkToEndOfElement(childElement, eventReader)
}
@@ -1421,52 +1325,47 @@ class TableExtractor(
* Parses the xml contained in a "configVarying" tag.
*
* @param element The start element of the [Style] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parseConfigVarying(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ) = parseStyleImpl(element, eventReader, parsedResource, AaptResourceType.CONFIG_VARYING)
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource) =
+ parseStyleImpl(element, eventReader, parsedResource, AaptResourceType.CONFIG_VARYING)
/**
* Parses the xml contained in a "style" tag.
*
* @param element The start element of the [Style] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parseStyle(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ) = parseStyleImpl(element, eventReader, parsedResource, AaptResourceType.STYLE)
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource) =
+ parseStyleImpl(element, eventReader, parsedResource, AaptResourceType.STYLE)
/**
* Parses the xml element as a [Style].
*
* @param element The start element of the [Style] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @param type The actual type of the [Style] being parsed, which is reflected in the
- * [ResourceName] of the parsed resource.
+ * [ResourceName] of the parsed resource.
* @return returns whether or not the parsing was a success.
*/
private fun parseStyleImpl(
element: StartElement,
eventReader: XMLEventReader,
parsedResource: ParsedResource,
- type: AaptResourceType
- ): Boolean {
+ type: AaptResourceType): Boolean {
parsedResource.name = parsedResource.name.copy(type = type)
@@ -1524,8 +1423,7 @@ class TableExtractor(
if (!shouldIgnoreElement(childName)) {
logError(
blameSource(source, childElement.location),
- "Unrecognized child element <$childName> of <${element.name}> resource."
- )
+ "Unrecognized child element <$childName> of <${element.name}> resource.")
error = true
}
walkToEndOfElement(childElement, eventReader)
@@ -1544,17 +1442,14 @@ class TableExtractor(
* Parses the xml element contained by a "declare-styleable" tag as a [Styleable] resource.
*
* @param element The start element of the [Styleable] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parseDeclareStyleable(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
parsedResource.name = parsedResource.name.copy(type = AaptResourceType.STYLEABLE)
// TODO(b/153454907): add option for preservation of stylable visibility to match aapt2
@@ -1565,8 +1460,7 @@ class TableExtractor(
if (parsedResource.config != defaultConfig) {
logger?.warning(
"Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ blameSource(source, element.location))
parsedResource.config = defaultConfig
}
@@ -1624,12 +1518,11 @@ class TableExtractor(
styleable.entries.add(nameReference)
parsedResource.children.add(childResource)
+
} else {
if (!shouldIgnoreElement(childName)) {
logError(
- blameSource(itemSource),
- "Unknown tag of <$childName> in <${element.name}> resource."
- )
+ blameSource(itemSource), "Unknown tag of <$childName> in <${element.name}> resource.")
error = true
}
walkToEndOfElement(childElement, eventReader)
@@ -1650,32 +1543,26 @@ class TableExtractor(
* Parses the xml element surrounded by the "overlayable" tag as an [Overlayable] resource.
*
* @param element The start element of the [Overlayable] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parseOverlayable(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
val defaultConfig = ConfigDescription()
if (parsedResource.config != defaultConfig) {
logger?.warning(
"Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ blameSource(source, element.location))
}
val nameAttribute = element.getAttributeByName(QName(null, "name"))
if (nameAttribute == null) {
logError(
- blameSource(source, element.location),
- " tag must have a 'name' attribute"
- )
+ blameSource(source, element.location), " tag must have a 'name' attribute")
return false
}
@@ -1683,9 +1570,8 @@ class TableExtractor(
if (actorAttribute != null && !actorAttribute.value.startsWith(Overlayable.ACTOR_SCHEME_URI)) {
logError(
blameSource(source, element.location),
- " tag has a 'actor' attribute: '${actorAttribute.value}'. " +
- "Value must use the schema: ${Overlayable.ACTOR_SCHEME_URI}."
- )
+ " tag has a 'actor' attribute: '${actorAttribute.value}'. " +
+ "Value must use the schema: ${Overlayable.ACTOR_SCHEME_URI}.")
return false
}
@@ -1732,7 +1618,8 @@ class TableExtractor(
parsedResource.children.add(childResource)
}
}
- childName.namespaceURI == XMLConstants.NULL_NS_URI && childName.localPart == "policy" -> {
+ childName.namespaceURI == XMLConstants.NULL_NS_URI &&
+ childName.localPart == "policy" -> {
++depth
val newPolicy = parsePoliciesFromElement(childElement, currentPolicies)
@@ -1747,9 +1634,8 @@ class TableExtractor(
}
!shouldIgnoreElement(childName) -> {
logError(
- blameSource(source, childElement.location),
- "Unrecognized tag '$childName' within an resource."
- )
+ blameSource(source, childElement.location),
+ "Unrecognized tag '$childName' within an resource.")
error = true
}
else -> comment = ""
@@ -1763,29 +1649,27 @@ class TableExtractor(
* Parses the xml element as a [OverlayableItem] within an [Overlayable] resource.
*
* @param element The start element of the [OverlayableItem] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param policies The policies of the current policy block that this [OverlayableItem] is a part
- * of. The value of policies should be non-zero.
+ * of. The value of policies should be non-zero.
* @param overlayable The overlayable which the parsed resource will be a part of.
* @param comment The comment that applies to this element.
* @return The parsedResource representing the parsed Overlayable Item. If their is an issue
- * parsing, then {@code null} is returned.
+ * parsing, then {@code null} is returned.
*/
private fun parseOverlayableItem(
element: StartElement,
eventReader: XMLEventReader,
policies: Int,
overlayable: Overlayable,
- comment: String
- ): ParsedResource? {
+ comment: String): ParsedResource? {
if (policies == OverlayableItem.Policy.NONE) {
logError(
- blameSource(source, element.location),
- "- within an must be inside a block."
- )
+ blameSource(source, element.location),
+ "
- within an must be inside a block.")
walkToEndOfElement(element, eventReader)
return null
}
@@ -1794,9 +1678,8 @@ class TableExtractor(
val nameAttribute = element.getAttributeByName(QName(null, "name"))
if (nameAttribute == null || nameAttribute.value.isNullOrEmpty()) {
logError(
- blameSource(source, element.location),
- "
- within an must have a 'name' attribute."
- )
+ blameSource(source, element.location),
+ "
- within an must have a 'name' attribute.")
walkToEndOfElement(element, eventReader)
return null
}
@@ -1804,9 +1687,8 @@ class TableExtractor(
val typeAttribute = element.getAttributeByName(QName(null, "type"))
if (typeAttribute == null || typeAttribute.value.isNullOrEmpty()) {
logError(
- blameSource(source, element.location),
- "
- within an must have a 'type' attribute."
- )
+ blameSource(source, element.location),
+ "
- within an must have a 'type' attribute.")
walkToEndOfElement(element, eventReader)
return null
}
@@ -1814,9 +1696,8 @@ class TableExtractor(
val type = resourceTypeFromTag(typeAttribute.value)
if (type == null) {
logError(
- blameSource(source, element.location),
- "Invalid resource type '${typeAttribute.value}' in
- in resource."
- )
+ blameSource(source, element.location),
+ "Invalid resource type '${typeAttribute.value}' in
- in resource.")
walkToEndOfElement(element, eventReader)
return null
}
@@ -1833,22 +1714,21 @@ class TableExtractor(
}
/**
- * Parses the "type" attribute of the block for policies. This does not move the xml
- * parser, as this does not read
+ * Parses the "type" attribute of the block for policies. This does not move the
+ * xml parser, as this does not read
*
* @param element The start element of the block.
* @param oldPolicies The current policies to be overwritten. As nested policy blocks are not
- * allowed, the oldPolicies is expected to be [OverlayableItem.Policy.NONE].
+ * allowed, the oldPolicies is expected to be [OverlayableItem.Policy.NONE].
* @return The new policy values or null if an error occurred.
*/
- private fun parsePoliciesFromElement(element: StartElement, oldPolicies: Int): Int? {
+ private fun parsePoliciesFromElement(
+ element: StartElement, oldPolicies: Int): Int? {
if (oldPolicies != OverlayableItem.Policy.NONE) {
// If the policy list is not empty, then we are currently inside a policy element.
logError(
- blameSource(source, element.location),
- "Policy blocks should not be nested recursively."
- )
+ blameSource(source, element.location), "Policy blocks should not be nested recursively.")
return null
}
@@ -1862,24 +1742,21 @@ class TableExtractor(
// Parse the polices separated by vertical bar characters to allow for specifying multiple
// policies. Items within the policy tag will have the specified policy.
for (string in typeAttribute.value.split('|')) {
- newPolicy =
- newPolicy or
- when (string.trim()) {
- "odm" -> OverlayableItem.Policy.ODM
- "oem" -> OverlayableItem.Policy.OEM
- "product" -> OverlayableItem.Policy.PRODUCT
- "public" -> OverlayableItem.Policy.PUBLIC
- "signature" -> OverlayableItem.Policy.SIGNATURE
- "system" -> OverlayableItem.Policy.SYSTEM
- "vendor" -> OverlayableItem.Policy.VENDOR
- else -> {
- logError(
- blameSource(source, element.location),
- " has unsupported type '${string.trim()}'."
- )
- return null
- }
- }
+ newPolicy = newPolicy or when(string.trim()) {
+ "odm" -> OverlayableItem.Policy.ODM
+ "oem" -> OverlayableItem.Policy.OEM
+ "product" -> OverlayableItem.Policy.PRODUCT
+ "public" -> OverlayableItem.Policy.PUBLIC
+ "signature" -> OverlayableItem.Policy.SIGNATURE
+ "system" -> OverlayableItem.Policy.SYSTEM
+ "vendor" -> OverlayableItem.Policy.VENDOR
+ else -> {
+ logError(
+ blameSource(source, element.location),
+ " has unsupported type '${string.trim()}'.")
+ return null
+ }
+ }
}
return newPolicy
@@ -1889,18 +1766,15 @@ class TableExtractor(
* Parses the {@code element} as a [Plural] resource.
*
* @param element The start element of the [Plural] to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parsePlural(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
- parsedResource.name = parsedResource.name.copy(type = AaptResourceType.PLURALS)
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
+ parsedResource.name = parsedResource.name.copy(type=AaptResourceType.PLURALS)
val plural = Plural()
@@ -1924,32 +1798,29 @@ class TableExtractor(
val quantityAttribute = childElement.getAttributeByName(QName("quantity"))
if (quantityAttribute == null) {
logError(
- blameSource(source, childElement.location),
- "
- in are required to have the 'quantity' attribute."
- )
+ blameSource(source, childElement.location),
+ "
- in are required to have the 'quantity' attribute.")
walkToEndOfElement(childElement, eventReader)
error = true
continue
}
val trimmedQuantity = quantityAttribute.value.trim()
- val pluralType =
- when (trimmedQuantity) {
- "zero" -> Plural.Type.ZERO
- "one" -> Plural.Type.ONE
- "two" -> Plural.Type.TWO
- "few" -> Plural.Type.FEW
- "many" -> Plural.Type.MANY
- "other" -> Plural.Type.OTHER
- else -> null
- }
+ val pluralType = when (trimmedQuantity) {
+ "zero" -> Plural.Type.ZERO
+ "one" -> Plural.Type.ONE
+ "two" -> Plural.Type.TWO
+ "few" -> Plural.Type.FEW
+ "many" -> Plural.Type.MANY
+ "other" -> Plural.Type.OTHER
+ else -> null
+ }
if (pluralType == null) {
logError(
- blameSource(source, childElement.location),
- "Unrecognized quantity value '$trimmedQuantity' specified in
- " +
- "in resource."
- )
+ blameSource(source, childElement.location),
+ "Unrecognized quantity value '$trimmedQuantity' specified in
- " +
+ "in resource.")
walkToEndOfElement(childElement, eventReader)
error = true
continue
@@ -1959,9 +1830,8 @@ class TableExtractor(
if (plural.values[pluralIndex] != null) {
logError(
blameSource(source, childElement.location),
- "
- has quantity '$trimmedQuantity' which has already been specified " +
- "in resource '${element.name}'"
- )
+ "
- has quantity '$trimmedQuantity' which has already been specified " +
+ "in resource '${element.name}'")
error = true
walkToEndOfElement(childElement, eventReader)
continue
@@ -1975,9 +1845,8 @@ class TableExtractor(
} else {
if (!shouldIgnoreElement(childName)) {
logError(
- blameSource(source, childElement.location),
- "Unrecognized tag '$childName' within an resource."
- )
+ blameSource(source, childElement.location),
+ "Unrecognized tag '$childName' within an resource.")
error = true
}
walkToEndOfElement(childElement, eventReader)
@@ -1996,23 +1865,19 @@ class TableExtractor(
* Parses the {@code element} as a public resource.
*
* @param element The start element of the resource to be parsed.
- * @param eventReader The xml to be read. The event reader should have just pulled the {@code
- * StartElement} element. After this method is invoked the eventReader will be placed after the
- * corresponding end tag for element.
+ * @param eventReader The xml to be read. The event reader should have just pulled the
+ * {@code StartElement} element. After this method is invoked the eventReader will be placed
+ * after the corresponding end tag for element.
* @param parsedResource Where the parsed resource will be placed.
* @return returns whether or not the parsing was a success.
*/
private fun parsePublic(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
- if (options.visibility != null) {
+ if (options.visibility != null ) {
logError(
- blameSource(source, element.location),
- " tag not allowed with --visibility flag."
- )
+ blameSource(source, element.location),
+ " tag not allowed with --visibility flag.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2020,8 +1885,7 @@ class TableExtractor(
if (parsedResource.config != ConfigDescription()) {
logger?.warning(
"Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ blameSource(source, element.location))
}
val typeAttribute = element.getAttributeByName(QName("type"))
@@ -2034,9 +1898,8 @@ class TableExtractor(
val parsedType = resourceTypeFromTag(typeAttribute.value)
if (parsedType == null) {
logError(
- blameSource(source, element.location),
- "Invalid resource type '${typeAttribute.value}' in resource."
- )
+ blameSource(source, element.location),
+ "Invalid resource type '${typeAttribute.value}' in resource.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2048,9 +1911,8 @@ class TableExtractor(
val id = parseResourceId(idAttribute.value)
if (id == null) {
logError(
- blameSource(source, element.location),
- "Invalid resource Id '${idAttribute.value}' in resource."
- )
+ blameSource(source, element.location),
+ "Invalid resource Id '${idAttribute.value}' in resource.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2072,32 +1934,26 @@ class TableExtractor(
* corresponding end of {@code element}
*/
private fun parsePublicGroup(
- element: StartElement,
- eventReader: XMLEventReader,
- parsedResource: ParsedResource
- ): Boolean {
+ element: StartElement, eventReader: XMLEventReader, parsedResource: ParsedResource): Boolean {
if (options.visibility != null) {
logError(
- blameSource(source, element.location),
- " tag not allowed with --visibility flag."
- )
+ blameSource(source, element.location),
+ " tag not allowed with --visibility flag.")
walkToEndOfElement(element, eventReader)
return false
}
if (parsedResource.config != ConfigDescription()) {
logger?.warning(
- "Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
- blameSource(source, element.location)
- )
+ "Ignoring configuration '${parsedResource.config}' for <${element.name}> tag.",
+ blameSource(source, element.location))
}
val typeAttribute = element.getAttributeByName(QName("type"))
if (typeAttribute == null) {
logError(
- blameSource(source, element.location),
- " must have a 'type' attribute."
- )
+ blameSource(source, element.location),
+ " must have a 'type' attribute.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2105,9 +1961,8 @@ class TableExtractor(
val parsedType = resourceTypeFromTag(typeAttribute.value)
if (parsedType == null) {
logError(
- blameSource(source, element.location),
- "Invalid resource type '${typeAttribute.value}' in ."
- )
+ blameSource(source, element.location),
+ "Invalid resource type '${typeAttribute.value}' in .")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2115,9 +1970,8 @@ class TableExtractor(
val idAttribute = element.getAttributeByName(QName("first-id"))
if (idAttribute == null) {
logError(
- blameSource(source, element.location),
- " must have a 'first-id' attribute."
- )
+ blameSource(source, element.location),
+ " must have a 'first-id' attribute.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2125,9 +1979,8 @@ class TableExtractor(
val idVal = parseResourceId(idAttribute.value)
if (idVal == null) {
logError(
- blameSource(source, element.location),
- "Invalid resource ID '${idAttribute.value}' in . Integer expected."
- )
+ blameSource(source, element.location),
+ "Invalid resource ID '${idAttribute.value}' in . Integer expected.")
walkToEndOfElement(element, eventReader)
return false
}
@@ -2159,11 +2012,9 @@ class TableExtractor(
val itemSource = source.withLine(childElement.location.lineNumber)
if (childName.namespaceURI.isEmpty() && childName.localPart == "public") {
val nameAttribute = childElement.getAttributeByName(QName("name"))
- if (nameAttribute == null) {
+ if (nameAttribute == null) {
logError(
- blameSource(source, childElement.location),
- " must have a 'name' attribute."
- )
+ blameSource(source, childElement.location), " must have a 'name' attribute.")
walkToEndOfElement(childElement, eventReader)
error = true
continue
@@ -2172,9 +2023,8 @@ class TableExtractor(
val childIdAttribute = childElement.getAttributeByName(QName("id"))
if (childIdAttribute != null) {
logError(
- blameSource(source, childElement.location),
- "'id' attribute is not allowed on tags within a ."
- )
+ blameSource(source, childElement.location),
+ "'id' attribute is not allowed on tags within a .")
walkToEndOfElement(childElement, eventReader)
error = true
continue
@@ -2183,9 +2033,8 @@ class TableExtractor(
val childTypeAttribute = childElement.getAttributeByName(QName("type"))
if (childTypeAttribute != null) {
logError(
- blameSource(source, childElement.location),
- "'type' attribute is not allowed on tags within a ."
- )
+ blameSource(source, childElement.location),
+ "'type' attribute is not allowed on tags within a .")
walkToEndOfElement(childElement, eventReader)
error = true
continue
@@ -2202,9 +2051,8 @@ class TableExtractor(
} else {
if (!shouldIgnoreElement(childName)) {
logError(
- blameSource(source, childElement.location),
- "Unrecognized tag '$childName' within an resource."
- )
+ blameSource(source, childElement.location),
+ "Unrecognized tag '$childName' within an resource.")
error = true
}
walkToEndOfElement(childElement, eventReader)
@@ -2247,15 +2095,12 @@ class TableExtractor(
resource.comment = parsedResource.comment
resource.source = parsedResource.source
- if (
- !table.addResourceWithId(
+ if (!table.addResourceWithId(
parsedResource.name,
parsedResource.resourceId,
parsedResource.config,
parsedResource.productString,
- resource
- )
- ) {
+ resource)) {
return false
}
}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/ToolFingerprint.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/ToolFingerprint.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/UnicodeUtil.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/UnicodeUtil.kt
old mode 100755
new mode 100644
index 014a384d4..55c925af0
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/UnicodeUtil.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/UnicodeUtil.kt
@@ -675,14 +675,15 @@ fun isJavaIdentifier(string: String): Boolean {
val firstCodePoint = string.codePointAt(0)
if (!isXidStart(firstCodePoint) &&
- firstCodePoint != '_'.toInt() &&
- firstCodePoint != '$'.toInt()) {
+ firstCodePoint != '_'.code &&
+ firstCodePoint != '$'.code
+ ) {
return false
}
for (i in 1.until(string.codePointCount(0, string.length))) {
val codePoint = string.codePointAt(i)
- if (!isXidContinue(codePoint) && codePoint != '$'.toInt()) {
+ if (!isXidContinue(codePoint) && codePoint != '$'.code) {
return false
}
}
@@ -700,15 +701,15 @@ fun isValidResourceEntryName(string: String): Boolean {
// Resources can start with '_'.
val firstCodePoint = string.codePointAt(0)
- if (!isXidStart(firstCodePoint) && firstCodePoint != '_'.toInt()) {
+ if (!isXidStart(firstCodePoint) && firstCodePoint != '_'.code) {
return false
}
for (i in 1.until(string.codePointCount(0, string.length))) {
val codePoint = string.codePointAt(i)
- if (!isXidContinue(codePoint) && codePoint != '.'.toInt() && codePoint != '-'.toInt()) {
+ if (!isXidContinue(codePoint) && codePoint != '.'.code && codePoint != '-'.code) {
return false
}
}
return true
-}
\ No newline at end of file
+}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlProcessor.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlProcessor.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlResource.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlResource.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlResourceBuilder.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlResourceBuilder.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlStringBuilder.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlStringBuilder.kt
old mode 100755
new mode 100644
index aefff9eb4..909764ce6
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlStringBuilder.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlStringBuilder.kt
@@ -107,11 +107,11 @@ class XmlStringBuilder(private val preserveSpaces: Boolean = false) {
str: String
): Boolean {
when (codePoint) {
- 't'.toInt() -> textBuilder.append('\t')
- 'n'.toInt() -> textBuilder.append('\n')
- '#'.toInt(), '@'.toInt(), '?'.toInt(), '"'.toInt(), '\''.toInt(), '\\'.toInt() ->
+ 't'.code -> textBuilder.append('\t')
+ 'n'.code -> textBuilder.append('\n')
+ '#'.code, '@'.code, '?'.code, '"'.code, '\''.code, '\\'.code ->
textBuilder.appendCodePoint(codePoint)
- 'u'.toInt() -> {
+ 'u'.code -> {
if (!appendUnicodeEscapeSequence(codePoints, textBuilder)) {
error = "Invalid unicode escape sequence in string\n\"$str\""
return false
@@ -160,7 +160,7 @@ class XmlStringBuilder(private val preserveSpaces: Boolean = false) {
lastChar = textBuilder.length
lastCodepointWasBackslash = false
}
- codePoint == '\\'.toInt() -> {
+ codePoint == '\\'.code -> {
if (codePoints.hasNext()) {
codePoint = codePoints.nextInt()
if (!handleEscape(codePoint, textBuilder, codePoints, str)) {
@@ -171,7 +171,7 @@ class XmlStringBuilder(private val preserveSpaces: Boolean = false) {
lastCodepointWasBackslash = true
}
}
- codePoint == '\"'.toInt() && !preserveSpaces -> {
+ codePoint == '\"'.code && !preserveSpaces -> {
// only toggle quote when we are not preserving spaces.
inQuote = !inQuote
if (firstQuote == -1) {
@@ -180,7 +180,7 @@ class XmlStringBuilder(private val preserveSpaces: Boolean = false) {
lastQuote = textBuilder.length
lastChar = textBuilder.length
}
- codePoint == '\''.toInt() && !preserveSpaces && !inQuote -> {
+ codePoint == '\''.code && !preserveSpaces && !inQuote -> {
// this should be escaped when we are not preserving spaces
error = "Invalid unicode escape sequence in string\n\"{str}\""
return this
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlUtil.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlUtil.kt
old mode 100755
new mode 100644
index d0c63fd4b..e2fac5248
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlUtil.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/XmlUtil.kt
@@ -1,11 +1,12 @@
package com.android.aaptcompiler
import com.android.SdkConstants
+import jaxp.sun.xml.internal.stream.XMLInputFactoryImpl
import jaxp.xml.stream.XMLEventReader
import jaxp.xml.stream.XMLInputFactory
import jaxp.xml.stream.events.StartElement
-internal val xmlInputFactory = XMLInputFactory.newFactory()
+internal val xmlInputFactory = XMLInputFactoryImpl()
const val SCHEMA_PUBLIC_PREFIX = SdkConstants.URI_PREFIX
const val SCHEMA_PRIVATE_PREFIX = "http://schemas.android.com/apk/prv/res/"
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/AConfiguration.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/AConfiguration.kt
old mode 100755
new mode 100644
index 0f3e5ad29..c864faa4f
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/AConfiguration.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/AConfiguration.kt
@@ -179,6 +179,26 @@ object AConfiguration {
* resource qualifier.
*/
const val ACONFIGURATION_NAVHIDDEN_YES : Byte = 0x0002
+ /** Grammatical gender: not specified. */
+ const val ACONFIGURATION_GRAMMATICAL_GENDER_ANY : Byte = 0x00
+ /**
+ * Grammatical gender: const value corresponding to the
+ * [neuter](@dacRoot/guide/topics/resources/providing-resources.html#GrammaticalInflectionQualifier)
+ * resource qualifier.
+ */
+ const val ACONFIGURATION_GRAMMATICAL_GENDER_NEUTER : Byte = 0x01
+ /**
+ * Grammatical gender: const value corresponding to the
+ * [feminine](@dacRoot/guide/topics/resources/providing-resources.html#GrammaticalInflectionQualifier)
+ * resource qualifier.
+ */
+ const val ACONFIGURATION_GRAMMATICAL_GENDER_FEMININE : Byte = 0x02
+ /**
+ * Grammatical gender: const value corresponding to the
+ * [masculine](@dacRoot/guide/topics/resources/providing-resources.html#GrammaticalInflectionQualifier)
+ * resource qualifier.
+ */
+ const val ACONFIGURATION_GRAMMATICAL_GENDER_MASCULINE : Byte = 0x03
/** Screen size: not specified. */
const val ACONFIGURATION_SCREENSIZE_ANY : Byte = 0x00
/**
@@ -440,5 +460,11 @@ object AConfiguration {
* 0 cannot be used, since it is used to represent an undefined MNC.
*/
const val ACONFIGURATION_MNC_ZERO : Int = 0xffff
+ /**
+ * Bit mask for
+ * [grammatical gender](@dacRoot/guide/topics/resources/providing-resources.html#GrammaticalInflectionQualifier)
+ * configuration.
+ */
+ const val ACONFIGURATION_GRAMMATICAL_GENDER : Int = 0x20000
}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleData.java b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleData.java
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleDataTables.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleDataTables.kt
old mode 100755
new mode 100644
index dfeeb75d1..343b726de
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleDataTables.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/LocaleDataTables.kt
@@ -1,5 +1,7 @@
package com.android.aaptcompiler.android
+import com.itsaky.androidide.utils.intByteMapOf
+
internal val SCRIPT_CODES = arrayOf(
/* 0 */ byteArrayOf('A'.code.toByte(), 'h'.code.toByte(), 'o'.code.toByte(), 'm'.code.toByte()),
/* 1 */ byteArrayOf('A'.code.toByte(), 'r'.code.toByte(), 'a'.code.toByte(), 'b'.code.toByte()),
@@ -91,7 +93,7 @@ internal val SCRIPT_CODES = arrayOf(
/* 87 */ byteArrayOf('~'.code.toByte(), '~'.code.toByte(), '~'.code.toByte(), 'A'.code.toByte()),
/* 88 */ byteArrayOf('~'.code.toByte(), '~'.code.toByte(), '~'.code.toByte(), 'B'.code.toByte()))
-internal val LIKELY_SCRIPTS = mapOf(
+internal val LIKELY_SCRIPTS = intByteMapOf(
0x61610000 to 40, // aa -> Latn
0xa0000000.toInt() to 40, // aai -> Latn
0xa8000000.toInt() to 40, // aak -> Latn
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Ref.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Ref.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResTableConfig.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResTableConfig.kt
old mode 100755
new mode 100644
index 53cee21a5..1f8403c8d
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResTableConfig.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResTableConfig.kt
@@ -2,6 +2,7 @@ package com.android.aaptcompiler.android
import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_COLOR_MODE
import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_DENSITY
+import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_GRAMMATICAL_GENDER
import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_KEYBOARD
import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_KEYBOARD_HIDDEN
import com.android.aaptcompiler.android.AConfiguration.ACONFIGURATION_LAYOUTDIR
@@ -52,6 +53,7 @@ open class ResTableConfig(
var keyboard: Byte = 0,
var navigation: Byte = 0,
var inputFlags: Byte = 0,
+ var grammaticalInflection: Byte = 0,
// padding: Byte,
// screenSize block
var screenWidth: Int = 0,
@@ -84,6 +86,7 @@ open class ResTableConfig(
locale: Int,
screenType: Int,
input: Int,
+ grammaticalInflection: Int,
screenSize: Int,
version: Int,
screenConfig: Int,
@@ -104,6 +107,7 @@ open class ResTableConfig(
keyboardFromInput(input),
navigationFromInput(input),
inputFlagsFromInput(input),
+ grammaticalInflection.deviceToHost().toByte(),
screenWidthFromScreenSize(screenSize),
screenHeightFromScreenSize(screenSize),
sdkVersionFromVersion(version),
@@ -132,6 +136,7 @@ open class ResTableConfig(
other.keyboard,
other.navigation,
other.inputFlags,
+ other.grammaticalInflection,
other.screenWidth,
other.screenHeight,
other.sdkVersion,
@@ -231,6 +236,17 @@ open class ResTableConfig(
appendDirLocale(result)
+ if (grammaticalInflection != GRAMMATICAL_GENDER.ANY) {
+ result.append(
+ when (grammaticalInflection) {
+ GRAMMATICAL_GENDER.NEUTER -> "neuter"
+ GRAMMATICAL_GENDER.FEMININE -> "feminine"
+ GRAMMATICAL_GENDER.MASCULINE -> "masculine"
+ else -> "grammaticalInflection=$grammaticalInflection"
+ })
+ result.append("-")
+ }
+
val layoutDir = (screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK).toByte()
if (layoutDir != SCREEN_LAYOUT.DIR_ANY) {
result.append(
@@ -570,6 +586,9 @@ open class ResTableConfig(
if (compareLocales(other) != 0) {
result = result or CONFIG_LOCALE
}
+ if (grammaticalInflection != other.grammaticalInflection) {
+ result = result or CONFIG_GRAMMATICAL_GENDER
+ }
return result
}
@@ -586,6 +605,11 @@ open class ResTableConfig(
return localeDiff
}
+ when {
+ grammaticalInflection > other.grammaticalInflection -> return 1
+ grammaticalInflection < other.grammaticalInflection -> return -1
+ }
+
val screenType = getScreenType().deviceToHost()
val oScreenType = other.getScreenType().deviceToHost()
when {
@@ -648,7 +672,7 @@ open class ResTableConfig(
return 0
}
-
+
fun compareLocales(other: ResTableConfig): Int {
val locale = getLocale().deviceToHost()
val oLocale = other.getLocale().deviceToHost()
@@ -659,7 +683,7 @@ open class ResTableConfig(
locale > oLocale -> return 1
oLocale > locale -> return -1
}
-
+
// The language & region are equal, so compare the scripts, variants and numbering systems in
// that order. Comparison of variants and numbering systems should happen very infrequently (if
// at all.)
@@ -670,12 +694,12 @@ open class ResTableConfig(
if (scriptDiff != 0) {
return scriptDiff
}
-
+
val variantDiff = compareArrays(localeVariant, other.localeVariant)
if (variantDiff != 0) {
return variantDiff
}
-
+
return compareArrays(localeNumberSystem, other.localeNumberSystem)
}
@@ -699,6 +723,10 @@ open class ResTableConfig(
localeDiff > 0 -> return true
}
+ if (grammaticalInflection.isTruthy() || other.grammaticalInflection.isTruthy()) {
+ if (grammaticalInflection != other.grammaticalInflection) return grammaticalInflection.isTruthy()
+ }
+
if (screenLayout.isTruthy() || other.screenLayout.isTruthy()) {
if (screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK !=
other.screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK) {
@@ -881,6 +909,10 @@ open class ResTableConfig(
return true
}
+ if (grammaticalInflection != other.grammaticalInflection && requested.grammaticalInflection.isTruthy()) {
+ return grammaticalInflection.isTruthy()
+ }
+
if (screenLayout.isTruthy() || other.screenLayout.isTruthy()) {
val myLayoutDir = screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK
val otherLayoutDir = other.screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK
@@ -1258,6 +1290,10 @@ open class ResTableConfig(
}
}
+ if (grammaticalInflection.isTruthy() && grammaticalInflection != settings.grammaticalInflection) {
+ return false
+ }
+
if (getScreenConfig().isTruthy()) {
val layoutDir = screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK
val setLayoutDir = settings.screenLayout.toInt() and SCREEN_LAYOUT.DIR_MASK
@@ -1478,6 +1514,7 @@ open class ResTableConfig(
const val CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR
const val CONFIG_SCREEN_ROUND = ACONFIGURATION_SCREEN_ROUND
const val CONFIG_COLOR_MODE = ACONFIGURATION_COLOR_MODE
+ const val CONFIG_GRAMMATICAL_GENDER = ACONFIGURATION_GRAMMATICAL_GENDER
const val SCREEN_CONFIG_MIN_SIZE = 32
const val SCREEN_DP_MIN_SIZE = 36
@@ -1552,6 +1589,7 @@ open class ResTableConfig(
val locale = buffer.int
val screenType = buffer.int
val input = buffer.int
+ val grammaticalInflection = buffer.int
val screenSize = buffer.int
val version = buffer.int
@@ -1587,6 +1625,7 @@ open class ResTableConfig(
locale,
screenType,
input,
+ grammaticalInflection,
screenSize,
version,
screenConfig,
@@ -1660,12 +1699,14 @@ open class ResTableConfig(
const val ANY = AConfiguration.ACONFIGURATION_ORIENTATION_ANY
const val PORT = AConfiguration.ACONFIGURATION_ORIENTATION_PORT
const val LAND = AConfiguration.ACONFIGURATION_ORIENTATION_LAND
+ @Suppress("DEPRECATION") // Legacy support
const val SQUARE = AConfiguration.ACONFIGURATION_ORIENTATION_SQUARE
}
object TOUCHSCREEN {
const val ANY = AConfiguration.ACONFIGURATION_TOUCHSCREEN_ANY
const val NOTOUCH = AConfiguration.ACONFIGURATION_TOUCHSCREEN_NOTOUCH
+ @Suppress("DEPRECATION") // Legacy support
const val STYLUS = AConfiguration.ACONFIGURATION_TOUCHSCREEN_STYLUS
const val FINGER = AConfiguration.ACONFIGURATION_TOUCHSCREEN_FINGER
}
@@ -1717,6 +1758,13 @@ open class ResTableConfig(
(AConfiguration.ACONFIGURATION_NAVHIDDEN_YES.toInt() shl NAVHIDDEN_SHIFT).toByte()
}
+ object GRAMMATICAL_GENDER {
+ const val ANY = AConfiguration.ACONFIGURATION_GRAMMATICAL_GENDER_ANY
+ const val NEUTER = AConfiguration.ACONFIGURATION_GRAMMATICAL_GENDER_NEUTER
+ const val FEMININE = AConfiguration.ACONFIGURATION_GRAMMATICAL_GENDER_FEMININE
+ const val MASCULINE = AConfiguration.ACONFIGURATION_GRAMMATICAL_GENDER_MASCULINE
+ }
+
// Screensize values
object SCREENSIZE {
const val WIDTH_ANY = 0
@@ -1799,4 +1847,4 @@ open class ResTableConfig(
const val HDR_NO = (AConfiguration.ACONFIGURATION_HDR_NO.toInt() shl HDR_SHIFT).toByte()
const val HDR_YES = (AConfiguration.ACONFIGURATION_HDR_YES.toInt() shl HDR_SHIFT).toByte()
}
-}
\ No newline at end of file
+}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResourceTypes.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResourceTypes.kt
old mode 100755
new mode 100644
index e4c4e55c6..3a60afb5f
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResourceTypes.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/ResourceTypes.kt
@@ -20,22 +20,25 @@ import com.android.aaptcompiler.StringPool
import com.android.aaptcompiler.parseFloat
import java.nio.ByteBuffer
import java.nio.ByteOrder
+import kotlin.text.Charsets
/**
- * Definitions of resource data structures.
Transliterated from: *
+ * Definitions of resource data structures.
+ *
Transliterated from: *
* https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/libs/androidfw/ResourceTypes.cpp
*/
-/** Header that appears at the front of every data chunk in a resource. */
+/**
+ * Header that appears at the front of every data chunk in a resource.
+ */
class ResChunkHeader(
// Type identifier for this chunk. The meaning of this value depends on the containing chunk.
val typeId: Short,
// Size of the chunk header (in bytes). Adding this value to the address of the chunk will be
// the address of the associated data if any.
- val headerSize: Short
-) {
+ val headerSize: Short) {
- constructor() : this(0, 0)
+ constructor(): this(0, 0)
// Total size of this chunk (in bytes). This is the chunkSize plus the size of any data
// associated with this chunk. Adding the this to the address of this chunk will completely skip
@@ -71,52 +74,48 @@ enum class ChunkType(val id: Short) {
TABLE_OVERLAYABLE_POLICY_TYPE(0x0205),
}
-/** Representation of a value in a resource, supplying type information. */
+/**
+ * Representation of a value in a resource, supplying type information.
+ */
data class ResValue(val dataType: DataType, val data: Int, val size: Short = 0) {
constructor() : this(DataType.NULL, 0)
- /** type of the data value. */
+ // type of the data value.
enum class DataType(val byteValue: Byte) {
- /**
- * The 'data' is either 0 or 1, specifying this resource is undefined or empty, respectively.
- */
+ // The 'data' is either 0 or 1, specifying this resource is undefined or empty, respectively.
NULL(0X00),
- /** The 'data' holds a ResTable reference, i.e. a reference to another resource. */
+ // The 'data' holds a ResTable reference, i.e. a reference to another resource.
REFERENCE(0x01),
- /** The 'data' holds an attribute resource identifier. */
+ // The 'data' holds an attribute resource identifier.
ATTRIBUTE(0x02),
- /** The 'data' holds an index into the containing resource table's string pool. */
+ // The 'data' holds an index into the containing resource table's string pool.
STRING(0x03),
- /** The 'data' holds a single-precision floating point number. */
+ // The 'data' holds a single-precision floating point number.
FLOAT(0x04),
- /** The 'data' holds a fixed point number encoding a dimension value, e.g. 100in. */
+ // The 'data' holds a fixed point number encoding a dimension value, e.g. 100in.
DIMENSION(0x05),
- /** The 'data' holds a fixed point number encoding a fraction of a container. */
+ // The 'data' holds a fixed point number encoding a fraction of a container.
FRACTION(0x06),
- /**
- * The 'data' holds a dynamic ResTable reference, which needs to be resolved before it can be
- * used as a REFERENCE.
- */
+ // The 'data' holds a dynamic ResTable reference, which needs to be resolved before it can be
+ // used as a REFERENCE.
DYNAMIC_REFERENCE(0x07),
- /**
- * The 'data' holds an attribute resource identifier, which needs to be resolved before it can
- * be used like a ATTRIBUTE.
- */
+ // The 'data' holds an attribute resource identifier, which needs to be resolved before it can
+ // be used like a ATTRIBUTE.
DYNAMIC_ATTRIBUTE(0x08),
- /** The 'data' is a raw integer of the form n..n. */
+ // The 'data' is a raw integer of the form n..n.
INT_DEC(0x10),
- /** The 'data' is a raw integer value of the form 0xn..n. */
+ // The 'data' is a raw integer value of the form 0xn..n.
INT_HEX(0x11),
- /** The 'data' is either 0 or 1, for input 'false' or 'true' respectively. */
+ // The 'data' is either 0 or 1, for input 'false' or 'true' respectively.
INT_BOOLEAN(0x12),
- /** The 'data' is a raw integer value of the form #aarrggbb. */
+ // The 'data' is a raw integer value of the form #aarrggbb.
INT_COLOR_ARGB8(0x1c),
- /** The 'data' is a raw integer value of the form #rrggbb. */
+ // The 'data' is a raw integer value of the form #rrggbb.
INT_COLOR_RGB8(0x1d),
- /** The 'data' is a raw integer value of the form #argb */
+ // The 'data' is a raw integer value of the form #argb
INT_COLOR_ARGB4(0x1e),
- /** The 'data is a raw integer value of the form #rgb */
+ // The 'data is a raw integer value of the form #rgb
INT_COLOR_RGB4(0x1f);
companion object {
@@ -134,10 +133,6 @@ data class ResValue(val dataType: DataType, val data: Int, val size: Short = 0)
const val UNIT_SHIFT = 0
const val UNIT_MASK = 0xf
- // ==================================
- // The values here are same as specified in TypedValue
- // ==================================
-
// TYPE_DIMENSION: Value is raw pixels.
const val UNIT_PX = 0
// TYPE_DIMENSION: Value is Device Independent Pixels.
@@ -184,12 +179,14 @@ data class ResValue(val dataType: DataType, val data: Int, val size: Short = 0)
}
}
-/** Reference to a string in a string pool */
+
+/**
+ * Reference to a string in a string pool
+ */
data class ResStringPoolRef(
// Index into the string pool table (unsigned 32 bit offset from the indices immediately after
// ResStringPoolHeader) at which to find the location of the string data in the pool
- val index: Int
-)
+ val index: Int)
/**
* Definition of a pool of strings.
@@ -202,8 +199,8 @@ data class ResStringPoolRef(
* to indicate this format is being used.
*
*
If {@code styleCount} is not zero, then immediately following the array of indices into the
- * string table is another array of indices into a style table starting at {@code stylesStart}. Each
- * entry in the style table is an array of {@code ResStringPoolSpan} structures.
+ * string table is another array of indices into a style table starting at {@code stylesStart}.
+ * Each entry in the style table is an array of {@code ResStringPoolSpan} structures.
*/
data class ResStringPoolHeader(
val header: ResChunkHeader,
@@ -211,10 +208,9 @@ data class ResStringPoolHeader(
val stringCount: Int,
// Number of style span arrays in the pool (number of 32 bit indices that follow the string
// indices).
- val styleCount: Int
-) {
+ val styleCount: Int) {
- constructor() : this(ResChunkHeader(), 0, 0)
+ constructor(): this(ResChunkHeader(), 0, 0)
var flags: Int = 0
// Index from header of the string data.
@@ -230,7 +226,9 @@ data class ResStringPoolHeader(
}
}
-/** This structure defines a span of style information associated with a string in the pool. */
+/**
+ * This structure defines a span of style information associated with a string in the pool.
+ */
data class ResStringPoolSpan(
// this is the name of the span -- that is, the name of the XML tag that defined it. The special
// value END indicates the end of an array of spans.
@@ -246,15 +244,13 @@ data class ResStringPoolSpan(
}
/** Convenience class for accessing data in a String Pool Flattened Resource */
-class ResStringPool
-private constructor(
+class ResStringPool private constructor(
val data: ByteBuffer,
val header: ResStringPoolHeader,
val stringPoolSize: Int,
val strings: List,
val stylesPoolSize: Int,
- val styles: List>
-) {
+ val styles: List>) {
companion object {
fun get(buffer: ByteBuffer, length: Int): ResStringPool {
@@ -268,11 +264,10 @@ private constructor(
val headerSize = buffer.getShort(2).deviceToHost()
val resourceSize = buffer.getInt(4).deviceToHost()
- if (
- typeId != ChunkType.STRING_POOL_TYPE.id ||
- headerSize != ResStringPoolHeader.SIZE ||
- resourceSize < headerSize ||
- resourceSize > length
+ if (typeId != ChunkType.STRING_POOL_TYPE.id ||
+ headerSize != ResStringPoolHeader.SIZE ||
+ resourceSize < headerSize ||
+ resourceSize > length
) {
error("Invalid StringPool: Header has invalid format.")
}
@@ -283,10 +278,7 @@ private constructor(
val header =
ResStringPoolHeader(
- chunkHeader,
- buffer.getInt(8).deviceToHost(),
- buffer.getInt(12).deviceToHost()
- )
+ chunkHeader, buffer.getInt(8).deviceToHost(), buffer.getInt(12).deviceToHost())
header.flags = buffer.getInt(16).deviceToHost()
header.stringsStart = buffer.getInt(20).deviceToHost()
header.stylesStart = buffer.getInt(24).deviceToHost()
@@ -295,10 +287,8 @@ private constructor(
val strings = mutableListOf()
if (header.stringCount != 0) {
// we need to check overflow and ensure the string indexes can fit.
- if (
- header.stringCount * 4 < header.stringCount ||
- (header.header.headerSize + (header.stringCount * 4)) > resourceSize
- ) {
+ if (header.stringCount*4 < header.stringCount ||
+ (header.header.headerSize + (header.stringCount*4)) > resourceSize) {
error("Invalid StringPool: Buffer not large enough for string indices.")
}
@@ -306,7 +296,7 @@ private constructor(
// There should at least be enough space for the smallest string.
// (2 bytes length, null terminator)
- if (header.stringsStart + 2 >= resourceSize) {
+ if (header.stringsStart+2 >= resourceSize) {
error("Invalid StringPool: Buffer not large enough for strings.")
}
@@ -324,7 +314,7 @@ private constructor(
stringPoolSize = (header.stylesStart - header.stringsStart) / charSize
}
- if (stringPoolSize == 0) {
+ if (stringPoolSize ==0) {
error("Invalid StringPool: Space for strings in header is too small.")
}
@@ -343,13 +333,13 @@ private constructor(
val styles = mutableListOf>()
if (header.styleCount != 0) {
- var currentStyleIndex = headerSize.toInt() + header.stringCount * 4
+ var currentStyleIndex = headerSize.toInt() + header.stringCount*4
// invariant: integer overflow in calculating styles
if (currentStyleIndex < headerSize.toInt()) {
error("Invalid StringPool: Integer overflow encountered while decoding styles.")
}
- stylePoolSize = (resourceSize - header.stylesStart) / 4
+ stylePoolSize = (resourceSize - header.stylesStart)/4
for (i in 0.until(header.styleCount)) {
val styleLocation = buffer.getInt(currentStyleIndex).deviceToHost() + header.stylesStart
@@ -370,31 +360,29 @@ private constructor(
val firstByteUTF16 = buffer.get(stringPosition)
++stringPosition
- val utf16Length =
- when {
- (firstByteUTF16.toInt() and StringPool.TWO_BYTE_UTF8_LENGTH_SIGNIFIER) != 0 -> {
- val secondByte = buffer.get(stringPosition).toInt() and 0xff
- ++stringPosition
+ val utf16Length = when {
+ (firstByteUTF16.toInt() and StringPool.TWO_BYTE_UTF8_LENGTH_SIGNIFIER) != 0 -> {
+ val secondByte = buffer.get(stringPosition).toInt() and 0xff
+ ++stringPosition
- ((firstByteUTF16.toInt() shl 8) + secondByte) and StringPool.UTF8_ENCODE_LENGTH_MAX
- }
- else -> firstByteUTF16.toInt()
+ ((firstByteUTF16.toInt() shl 8) + secondByte) and StringPool.UTF8_ENCODE_LENGTH_MAX
}
+ else -> firstByteUTF16.toInt()
+ }
// In UTF8 mode, the length in UTF8 comes next
val firstByteUTF8 = buffer.get(stringPosition)
++stringPosition
- val utf8Length =
- when {
- (firstByteUTF8.toInt() and StringPool.TWO_BYTE_UTF8_LENGTH_SIGNIFIER) != 0 -> {
- val secondByte = buffer.get(stringPosition).toInt() and 0xff
- ++stringPosition
+ val utf8Length = when {
+ (firstByteUTF8.toInt() and StringPool.TWO_BYTE_UTF8_LENGTH_SIGNIFIER) != 0 -> {
+ val secondByte = buffer.get(stringPosition).toInt() and 0xff
+ ++stringPosition
- ((firstByteUTF8.toInt() shl 8) + secondByte) and StringPool.UTF8_ENCODE_LENGTH_MAX
- }
- else -> firstByteUTF8.toInt()
+ ((firstByteUTF8.toInt() shl 8) + secondByte) and StringPool.UTF8_ENCODE_LENGTH_MAX
}
+ else -> firstByteUTF8.toInt()
+ }
// pull the bytes out of the buffer.
val array = ByteArray(utf8Length)
@@ -420,15 +408,14 @@ private constructor(
val firstShort = buffer.getShort(stringPosition).deviceToHost()
stringPosition += 2
- val utf16Length =
- when {
- (firstShort.toInt() and StringPool.TWO_CHAR_UTF16_LENGTH_SIGNIFIER) != 0 -> {
- val secondShort = buffer.getShort(stringPosition).deviceToHost().toInt() and 0xffff
- stringPosition += 2
- ((firstShort.toInt() shl 16) + secondShort) and StringPool.UTF16_ENCODE_LENGTH_MAX
- }
- else -> firstShort.toInt()
+ val utf16Length = when {
+ (firstShort.toInt() and StringPool.TWO_CHAR_UTF16_LENGTH_SIGNIFIER) != 0 -> {
+ val secondShort = buffer.getShort(stringPosition).deviceToHost().toInt() and 0xffff
+ stringPosition += 2
+ ((firstShort.toInt() shl 16) + secondShort) and StringPool.UTF16_ENCODE_LENGTH_MAX
}
+ else -> firstShort.toInt()
+ }
// pull the chars out of the buffer
val array = CharArray(utf16Length)
@@ -466,7 +453,7 @@ private constructor(
}
fun parseHex(codePoint: Int) =
- when (codePoint) {
+ when(codePoint) {
in '0'.code..'9'.code -> codePoint - '0'.code
in 'A'.code..'F'.code -> codePoint - 'A'.code + 10
in 'a'.code..'f'.code -> codePoint - 'a'.code + 10
@@ -490,17 +477,17 @@ fun stringToInt(string: String): ResValue? {
isNegative = true
}
- if (codePointCount == index || trimmedString.codePointAt(index) !in '0'.code..'9'.code) {
+ if (codePointCount == index
+ || trimmedString.codePointAt(index) !in '0'.code..'9'.code
+ ) {
return null
}
val isHex: Boolean
- if (
- codePointCount >= index + 2 &&
- trimmedString.codePointAt(index) == '0'.code &&
- trimmedString.codePointAt(index + 1) == 'x'.code
- ) {
+ if (codePointCount >= index + 2
+ && trimmedString.codePointAt(index) == '0'.code
+ && trimmedString.codePointAt(index+1) == 'x'.code) {
isHex = true
index += 2
@@ -538,7 +525,7 @@ fun stringToInt(string: String): ResValue? {
++index
val decValue = codePoint - '0'.code
- value = (value * 10) + decValue
+ value = (value*10) + decValue
val outOfBounds =
if (isNegative) -value < Int.MIN_VALUE.toLong() else value > Int.MAX_VALUE.toLong()
@@ -553,37 +540,26 @@ fun stringToInt(string: String): ResValue? {
}
return ResValue(
- if (isHex) ResValue.DataType.INT_HEX else ResValue.DataType.INT_DEC,
- value.toInt()
- )
+ if(isHex) ResValue.DataType.INT_HEX else ResValue.DataType.INT_DEC,
+ value.toInt())
}
private data class UnitEntry(
- val name: String,
- val dataType: ResValue.DataType,
- val unitValue: Int,
- val scale: Float = 1.0f
-)
+ val name: String, val dataType: ResValue.DataType, val unitValue: Int, val scale: Float = 1.0f)
-private val unitSuffixes =
- listOf(
- UnitEntry("px", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_PX),
- UnitEntry("dip", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_DIP),
- UnitEntry("dp", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_DIP),
- UnitEntry("sp", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_SP),
- UnitEntry("pt", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_PT),
- UnitEntry("in", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_IN),
- UnitEntry("mm", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_MM),
- UnitEntry("%", ResValue.DataType.FRACTION, ResValue.ComplexFormat.UNIT_FRACTION, 1.0f / 100),
- UnitEntry(
- "%p",
- ResValue.DataType.FRACTION,
- ResValue.ComplexFormat.UNIT_FRACTION_PARENT,
- 1.0f / 100
- )
- )
+private val unitSuffixes = listOf(
+ UnitEntry("px", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_PX),
+ UnitEntry("dip", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_DIP),
+ UnitEntry("dp", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_DIP),
+ UnitEntry("sp", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_SP),
+ UnitEntry("pt", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_PT),
+ UnitEntry("in", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_IN),
+ UnitEntry("mm", ResValue.DataType.DIMENSION, ResValue.ComplexFormat.UNIT_MM),
+ UnitEntry("%", ResValue.DataType.FRACTION, ResValue.ComplexFormat.UNIT_FRACTION, 1.0f/100),
+ UnitEntry(
+ "%p", ResValue.DataType.FRACTION, ResValue.ComplexFormat.UNIT_FRACTION_PARENT, 1.0f/100))
-private fun parseUnitType(string: String): UnitEntry? {
+private fun parseUnitType(string: String) : UnitEntry? {
for (entry in unitSuffixes) {
if (string.endsWith(entry.name)) {
return entry
@@ -605,7 +581,7 @@ fun stringToFloat(string: String): ResValue? {
if (entry != null) trimmedString.lastIndexOf(entry.name) else trimmedString.length
// no spaces allowed between suffix and floating point value
- if (suffixIndex == 0 || Character.isWhitespace(trimmedString.codePointAt(suffixIndex - 1))) {
+ if (suffixIndex == 0 || Character.isWhitespace(trimmedString.codePointAt(suffixIndex-1))) {
return null
}
@@ -615,7 +591,8 @@ fun stringToFloat(string: String): ResValue? {
// i.e "0x1d.dp" should be considered: "0x1d.d p" not "0x1d. dp"
if (parseHex(entry?.name?.codePointAt(0) ?: 0) != -1) {
// try to parse the float value with the beginning of the suffix considered.
- if (trimmedString.contains("0x", true) && !stringToParse.contains('p')) {
+ if (trimmedString.contains("0x", true) &&
+ !stringToParse.contains('p')) {
// ambiguous value string, resulting in a parse failure.
return null
}
@@ -647,39 +624,37 @@ fun stringToFloat(string: String): ResValue? {
// Transform the float to (rounded) integer with the lower 23 bits representing the fraction
// and bits 45 to 23 representing the whole number part.
- val bits = (parsedValue * (1 shl 23) + .5f).toLong()
+ val bits = (parsedValue*(1 shl 23) + .5f).toLong()
- val (radix, shift) =
- when {
- bits and ((1L shl 23) - 1) == 0L ->
- // Always use 23p0 if there is no fraction, as it is easier to read.
- Pair(ResValue.ComplexFormat.RADIX_23p0, 23)
- bits and ((1L shl 23) - 1).inv() == 0L ->
- // Whole number part is zero -- can fit into 0 leading bits of precision.
- Pair(ResValue.ComplexFormat.RADIX_0p23, 0)
- bits and ((1L shl 31) - 1).inv() == 0L ->
- // Magnitude can fit in 8 leading bits of precision.
- Pair(ResValue.ComplexFormat.RADIX_8p15, 8)
- bits and ((1L shl 39) - 1).inv() == 0L ->
- // Magnitude can fit in 16 leading bits of precision.
- Pair(ResValue.ComplexFormat.RADIX_16p7, 16)
- else ->
- // Need whole range, so no fractional part.
- Pair(ResValue.ComplexFormat.RADIX_23p0, 23)
- }
+ val (radix, shift) = when {
+ bits and ((1L shl 23) - 1) == 0L ->
+ // Always use 23p0 if there is no fraction, as it is easier to read.
+ Pair(ResValue.ComplexFormat.RADIX_23p0, 23)
+ bits and ((1L shl 23) - 1).inv() == 0L ->
+ // Whole number part is zero -- can fit into 0 leading bits of precision.
+ Pair(ResValue.ComplexFormat.RADIX_0p23, 0)
+ bits and ((1L shl 31) -1).inv() == 0L ->
+ // Magnitude can fit in 8 leading bits of precision.
+ Pair(ResValue.ComplexFormat.RADIX_8p15, 8)
+ bits and ((1L shl 39) -1).inv() == 0L ->
+ // Magnitude can fit in 16 leading bits of precision.
+ Pair(ResValue.ComplexFormat.RADIX_16p7, 16)
+ else ->
+ // Need whole range, so no fractional part.
+ Pair(ResValue.ComplexFormat.RADIX_23p0, 23)
+ }
var mantissa = (bits ushr shift).toInt() and ResValue.ComplexFormat.MANTISSA_MASK
if (negative) {
mantissa = (-mantissa) and ResValue.ComplexFormat.MANTISSA_MASK
}
- val dataValue =
- (entry.unitValue shl ResValue.ComplexFormat.UNIT_SHIFT) or
- (radix shl ResValue.ComplexFormat.RADIX_SHIFT) or
- (mantissa shl ResValue.ComplexFormat.MANTISSA_SHIFT)
+ val dataValue = (entry.unitValue shl ResValue.ComplexFormat.UNIT_SHIFT) or
+ (radix shl ResValue.ComplexFormat.RADIX_SHIFT) or
+ (mantissa shl ResValue.ComplexFormat.MANTISSA_SHIFT)
return ResValue(entry.dataType, dataValue)
}
return ResValue(ResValue.DataType.FLOAT, parsedValue.toRawBits())
-}
\ No newline at end of file
+}
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Util.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Util.kt
old mode 100755
new mode 100644
index 109a21014..02a08e239
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Util.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/android/Util.kt
@@ -16,6 +16,7 @@
package com.android.aaptcompiler.android
+import androidx.collection.mutableIntIntMapOf
import java.nio.ByteOrder
private val littleEndian = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/buffer/BigBuffer.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/buffer/BigBuffer.kt
old mode 100755
new mode 100644
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt
old mode 100755
new mode 100644
index c4a04068e..dc7de2d48
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoDeserialize.kt
@@ -1,6 +1,6 @@
package com.android.aaptcompiler.proto
-import androidx.collection.MutableIntObjectMap
+import androidx.collection.mutableIntObjectMapOf
import com.android.aapt.ConfigurationOuterClass
import com.android.aapt.Resources
import com.android.aaptcompiler.AllowNew
@@ -45,7 +45,8 @@ import com.android.utils.ILogger
import com.itsaky.androidide.layoutlib.resources.ResourceVisibility
fun deserializeConfigFromPb(
- config: ConfigurationOuterClass.Configuration, logger: ILogger?): ConfigDescription? {
+ config: ConfigurationOuterClass.Configuration, logger: ILogger?
+): ConfigDescription? {
val mcc = config.getMcc().toShort()
val mnc = config.getMnc().toShort()
@@ -62,8 +63,10 @@ fun deserializeConfigFromPb(
val screenLayoutDir = when (config.getLayoutDirection()) {
ConfigurationOuterClass.Configuration.LayoutDirection.LAYOUT_DIRECTION_LTR ->
ResTableConfig.SCREEN_LAYOUT.DIR_LTR
+
ConfigurationOuterClass.Configuration.LayoutDirection.LAYOUT_DIRECTION_RTL ->
ResTableConfig.SCREEN_LAYOUT.DIR_RTL
+
else -> ResTableConfig.SCREEN_LAYOUT.DIR_ANY
}
@@ -74,36 +77,46 @@ fun deserializeConfigFromPb(
val screenLayoutSize = when (config.getScreenLayoutSize()) {
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_SMALL ->
ResTableConfig.SCREEN_LAYOUT.SIZE_SMALL
+
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_NORMAL ->
ResTableConfig.SCREEN_LAYOUT.SIZE_NORMAL
+
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_LARGE ->
ResTableConfig.SCREEN_LAYOUT.SIZE_LARGE
+
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_XLARGE ->
ResTableConfig.SCREEN_LAYOUT.SIZE_XLARGE
+
else -> ResTableConfig.SCREEN_LAYOUT.SIZE_ANY
}
val screenLayoutLong = when (config.getScreenLayoutLong()) {
ConfigurationOuterClass.Configuration.ScreenLayoutLong.SCREEN_LAYOUT_LONG_LONG ->
ResTableConfig.SCREEN_LAYOUT.SCREENLONG_YES
+
ConfigurationOuterClass.Configuration.ScreenLayoutLong.SCREEN_LAYOUT_LONG_NOTLONG ->
ResTableConfig.SCREEN_LAYOUT.SCREENLONG_NO
+
else -> ResTableConfig.SCREEN_LAYOUT.SCREENLONG_ANY
}
val screenRound = when (config.getScreenRound()) {
ConfigurationOuterClass.Configuration.ScreenRound.SCREEN_ROUND_ROUND ->
ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_YES
+
ConfigurationOuterClass.Configuration.ScreenRound.SCREEN_ROUND_NOTROUND ->
ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_NO
+
else -> ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_ANY
}
val wideGamutColor = when (config.getWideColorGamut()) {
ConfigurationOuterClass.Configuration.WideColorGamut.WIDE_COLOR_GAMUT_WIDECG ->
ResTableConfig.COLOR_MODE.WIDE_GAMUT_YES
+
ConfigurationOuterClass.Configuration.WideColorGamut.WIDE_COLOR_GAMUT_NOWIDECG ->
ResTableConfig.COLOR_MODE.WIDE_GAMUT_NO
+
else -> ResTableConfig.COLOR_MODE.WIDE_GAMUT_ANY
}
@@ -116,36 +129,48 @@ fun deserializeConfigFromPb(
val orientation = when (config.getOrientation()) {
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_PORT ->
ResTableConfig.ORIENTATION.PORT
+
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_LAND ->
ResTableConfig.ORIENTATION.LAND
+
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_SQUARE ->
ResTableConfig.ORIENTATION.SQUARE
+
else -> ResTableConfig.ORIENTATION.ANY
}
val uiModeType = when (config.getUiModeType()) {
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_NORMAL ->
ResTableConfig.UI_MODE.TYPE_NORMAL
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_DESK ->
ResTableConfig.UI_MODE.TYPE_DESK
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_CAR ->
ResTableConfig.UI_MODE.TYPE_CAR
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_TELEVISION ->
ResTableConfig.UI_MODE.TYPE_TELEVISION
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_APPLIANCE ->
ResTableConfig.UI_MODE.TYPE_APPLIANCE
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_WATCH ->
ResTableConfig.UI_MODE.TYPE_WATCH
+
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_VRHEADSET ->
ResTableConfig.UI_MODE.TYPE_VR_HEADSET
+
else -> ResTableConfig.UI_MODE.TYPE_ANY
}
val uiModeNight = when (config.getUiModeNight()) {
ConfigurationOuterClass.Configuration.UiModeNight.UI_MODE_NIGHT_NIGHT ->
ResTableConfig.UI_MODE.NIGHT_YES
+
ConfigurationOuterClass.Configuration.UiModeNight.UI_MODE_NIGHT_NOTNIGHT ->
ResTableConfig.UI_MODE.NIGHT_NO
+
else -> ResTableConfig.UI_MODE.NIGHT_ANY
}
@@ -154,53 +179,81 @@ fun deserializeConfigFromPb(
val touchscreen = when (config.getTouchscreen()) {
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_NOTOUCH ->
ResTableConfig.TOUCHSCREEN.NOTOUCH
+
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_STYLUS ->
ResTableConfig.TOUCHSCREEN.STYLUS
+
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_FINGER ->
ResTableConfig.TOUCHSCREEN.FINGER
+
else -> ResTableConfig.TOUCHSCREEN.ANY
}
val keysHidden = when (config.getKeysHidden()) {
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSEXPOSED ->
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_NO
+
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSHIDDEN ->
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_YES
+
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSSOFT ->
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_SOFT
+
else -> ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_ANY
}
val keyboard = when (config.getKeyboard()) {
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_NOKEYS ->
ResTableConfig.KEYBOARD.NOKEYS
+
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_QWERTY ->
ResTableConfig.KEYBOARD.QWERTY
+
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_TWELVEKEY ->
ResTableConfig.KEYBOARD.TWELVEKEY
+
else -> ResTableConfig.KEYBOARD.ANY
}
val navHidden = when (config.getNavHidden()) {
ConfigurationOuterClass.Configuration.NavHidden.NAV_HIDDEN_NAVHIDDEN ->
ResTableConfig.INPUT_FLAGS.NAVHIDDEN_YES
+
ConfigurationOuterClass.Configuration.NavHidden.NAV_HIDDEN_NAVEXPOSED ->
ResTableConfig.INPUT_FLAGS.NAVHIDDEN_NO
+
else -> ResTableConfig.INPUT_FLAGS.NAVHIDDEN_ANY
}
val navigation = when (config.getNavigation()) {
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_NONAV ->
ResTableConfig.NAVIGATION.NONAV
+
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_DPAD ->
ResTableConfig.NAVIGATION.DPAD
+
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_TRACKBALL ->
ResTableConfig.NAVIGATION.TRACKBALL
+
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_WHEEL ->
ResTableConfig.NAVIGATION.WHEEL
+
else -> ResTableConfig.NAVIGATION.ANY
}
+ val grammaticalGender = when (config.grammaticalGender) {
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_NEUTER ->
+ ResTableConfig.GRAMMATICAL_GENDER.NEUTER
+
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_FEMININE ->
+ ResTableConfig.GRAMMATICAL_GENDER.FEMININE
+
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_MASCULINE ->
+ ResTableConfig.GRAMMATICAL_GENDER.MASCULINE
+
+ else -> ResTableConfig.GRAMMATICAL_GENDER.ANY
+ }
+
val screenWidth = config.getScreenWidth()
val screenHeight = config.getScreenHeight()
val sdkVersion = config.getSdkVersion().toShort()
@@ -214,6 +267,7 @@ fun deserializeConfigFromPb(
density = density,
keyboard = keyboard,
navigation = navigation,
+ grammaticalInflection = grammaticalGender,
inputFlags = (keysHidden.toInt() or navHidden.toInt()).toByte(),
screenWidth = screenWidth,
screenHeight = screenHeight,
@@ -226,7 +280,9 @@ fun deserializeConfigFromPb(
screenWidthDp = screenWidthDp,
screenHeightDp = screenHeightDp,
screenLayout2 = screenRound,
- colorMode = (wideGamutColor.toInt() or hdr.toInt()).toByte()))
+ colorMode = (wideGamutColor.toInt() or hdr.toInt()).toByte()
+ )
+ )
localeValue.writeTo(configDescription)
return configDescription
@@ -250,7 +306,7 @@ fun deserializeSourceFromPb(source: Resources.Source, sourcePool: ResStringPool)
return Source(path, line)
}
-fun deserializeVisibilityFromPb(level: Resources.Visibility.Level) = when(level) {
+fun deserializeVisibilityFromPb(level: Resources.Visibility.Level) = when (level) {
Resources.Visibility.Level.PRIVATE -> ResourceVisibility.PRIVATE
Resources.Visibility.Level.PUBLIC -> ResourceVisibility.PUBLIC
else -> ResourceVisibility.UNDEFINED
@@ -260,7 +316,8 @@ fun deserializeOverlayableFromPb(
item: Resources.OverlayableItem,
overlayable: Overlayable,
sourcePool: ResStringPool,
- logger: ILogger?): OverlayableItem? {
+ logger: ILogger?
+): OverlayableItem? {
var policies = 0
for (policy in item.getPolicyList()) {
@@ -289,45 +346,60 @@ fun deserializeOverlayableFromPb(
}
fun deserializeBinPrimitiveFromPb(
- primitive: Resources.Primitive, logger: ILogger?): BinaryPrimitive? {
+ primitive: Resources.Primitive, logger: ILogger?
+): BinaryPrimitive? {
- val (type, deviceValue) = when(primitive.getOneofValueCase()) {
+ val (type, deviceValue) = when (primitive.getOneofValueCase()) {
Resources.Primitive.OneofValueCase.NULL_VALUE ->
Pair(ResValue.DataType.NULL, ResValue.NullFormat.UNDEFINED)
+
Resources.Primitive.OneofValueCase.EMPTY_VALUE ->
Pair(ResValue.DataType.NULL, ResValue.NullFormat.EMPTY)
+
Resources.Primitive.OneofValueCase.FLOAT_VALUE -> {
val float = primitive.getFloatValue()
Pair(ResValue.DataType.FLOAT, float.toRawBits())
}
+
Resources.Primitive.OneofValueCase.DIMENSION_VALUE ->
Pair(ResValue.DataType.DIMENSION, primitive.getDimensionValue())
+
Resources.Primitive.OneofValueCase.FRACTION_VALUE ->
Pair(ResValue.DataType.FRACTION, primitive.getFractionValue())
+
Resources.Primitive.OneofValueCase.INT_DECIMAL_VALUE ->
Pair(ResValue.DataType.INT_DEC, primitive.getIntDecimalValue())
+
Resources.Primitive.OneofValueCase.INT_HEXADECIMAL_VALUE ->
Pair(ResValue.DataType.INT_HEX, primitive.getIntHexadecimalValue())
+
Resources.Primitive.OneofValueCase.BOOLEAN_VALUE -> {
val boolValue = if (primitive.getBooleanValue()) 0xffffffff.toInt() else 0
Pair(ResValue.DataType.INT_BOOLEAN, boolValue)
}
+
Resources.Primitive.OneofValueCase.COLOR_ARGB8_VALUE ->
Pair(ResValue.DataType.INT_COLOR_ARGB8, primitive.getColorArgb8Value())
+
Resources.Primitive.OneofValueCase.COLOR_RGB8_VALUE ->
Pair(ResValue.DataType.INT_COLOR_RGB8, primitive.getColorRgb8Value())
+
Resources.Primitive.OneofValueCase.COLOR_ARGB4_VALUE ->
Pair(ResValue.DataType.INT_COLOR_ARGB4, primitive.getColorArgb4Value())
+
Resources.Primitive.OneofValueCase.COLOR_RGB4_VALUE ->
Pair(ResValue.DataType.INT_COLOR_RGB4, primitive.getColorRgb4Value())
+
Resources.Primitive.OneofValueCase.DIMENSION_VALUE_DEPRECATED -> {
val float = primitive.getDimensionValueDeprecated()
Pair(ResValue.DataType.DIMENSION, float.toRawBits())
}
+
Resources.Primitive.OneofValueCase.FRACTION_VALUE_DEPRECATED -> {
val float = primitive.getFractionValueDeprecated()
Pair(ResValue.DataType.FRACTION, float.toRawBits())
}
+
else -> {
val errorMsg = "Value case unrecognized for Primitive proto: %s"
logger?.error(null, errorMsg, primitive.oneofValueCase)
@@ -344,7 +416,8 @@ fun deserializeRawFromPb(string: Resources.RawString, valuePool: StringPool) =
RawString(valuePool.makeRef(string.getValue()))
fun deserializeStyledStrFromPb(
- string: Resources.StyledString, valuePool: StringPool): StyledString {
+ string: Resources.StyledString, valuePool: StringPool
+): StyledString {
val spans = mutableListOf()
for (span in string.getSpanList()) {
@@ -376,19 +449,23 @@ fun deserializeReferenceFromPb(ref: Resources.Reference, logger: ILogger?): Refe
}
fun deserializeFileRefFromPb(
- file: Resources.FileReference, valuePool: StringPool, config: ConfigDescription): FileReference {
+ file: Resources.FileReference, valuePool: StringPool, config: ConfigDescription
+): FileReference {
val fileRef = FileReference(
valuePool.makeRef(
file.getPath(),
- StringPool.Context(StringPool.Context.Priority.HIGH.priority, config)))
+ StringPool.Context(StringPool.Context.Priority.HIGH.priority, config)
+ )
+ )
fileRef.type = deserializeFileTypeFromPb(file.getType())
return fileRef
}
fun deserializeAttrFromPb(
- attr: Resources.Attribute, sourcePool: ResStringPool, logger: ILogger?): AttributeResource? {
+ attr: Resources.Attribute, sourcePool: ResStringPool, logger: ILogger?
+): AttributeResource? {
val attrResource = AttributeResource(attr.getFormatFlags())
attrResource.minInt = attr.getMinInt()
@@ -404,7 +481,8 @@ fun deserializeAttrFromPb(
reference.comment = symbol.getComment()
attrResource.symbols.add(
- AttributeResource.Symbol(reference, symbol.getValue(), symbol.getType().toByte()))
+ AttributeResource.Symbol(reference, symbol.getValue(), symbol.getType().toByte())
+ )
}
return attrResource
@@ -415,7 +493,8 @@ fun deserializeStyleFromPb(
valuePool: StringPool,
config: ConfigDescription,
sourcePool: ResStringPool,
- logger: ILogger?): Style? {
+ logger: ILogger?
+): Style? {
val styleResource = Style()
if (style.hasParent()) {
@@ -449,12 +528,13 @@ fun deserializeStyleFromPb(
}
fun deserializeStyleableFromPb(
- styleable: Resources.Styleable, sourcePool: ResStringPool, logger: ILogger?): Styleable? {
+ styleable: Resources.Styleable, sourcePool: ResStringPool, logger: ILogger?
+): Styleable? {
val styleableResource = Styleable()
for (entry in styleable.getEntryList()) {
val reference = deserializeReferenceFromPb(entry.getAttr(), logger)
- reference?: return null
+ reference ?: return null
if (entry.hasSource()) {
reference.source = deserializeSourceFromPb(entry.getSource(), sourcePool)
}
@@ -469,7 +549,8 @@ fun deserializeArrayFromPb(
valuePool: StringPool,
config: ConfigDescription,
sourcePool: ResStringPool,
- logger: ILogger?): ArrayResource? {
+ logger: ILogger?
+): ArrayResource? {
val arrayResource = ArrayResource()
for (entry in array.getElementList()) {
@@ -499,7 +580,8 @@ fun deserializePluralFromPb(
valuePool: StringPool,
config: ConfigDescription,
sourcePool: ResStringPool,
- logger: ILogger?): Plural? {
+ logger: ILogger?
+): Plural? {
val pluralResource = Plural()
for (entry in plural.getEntryList()) {
@@ -526,32 +608,34 @@ fun deserializeMacroFromPb(
valuePool: StringPool,
config: ConfigDescription,
sourcePool: ResStringPool,
- logger: ILogger?): Macro {
+ logger: ILogger?
+): Macro {
val macro = Macro()
macro.rawValue = pbMacro.rawString
if (pbMacro.hasStyleString()) {
- val spans = ArrayList()
- for (span in pbMacro.styleString.spansList) {
- spans.add(Span(span.name, span.startIndex, span.endIndex))
- }
- macro.styleString = StyleString(pbMacro.styleString.str, spans)
+ val spans = ArrayList()
+ for (span in pbMacro.styleString.spansList) {
+ spans.add(Span(span.name, span.startIndex, span.endIndex))
+ }
+ macro.styleString = StyleString(pbMacro.styleString.str, spans)
}
val untranslatableList = ArrayList()
for (untranslatable in pbMacro.untranslatableSectionsList) {
- untranslatableList.add(
- UntranslatableSection(
- untranslatable.startIndex.toInt(), untranslatable.endIndex.toInt())
+ untranslatableList.add(
+ UntranslatableSection(
+ untranslatable.startIndex.toInt(), untranslatable.endIndex.toInt()
)
+ )
}
macro.untranslatables = untranslatableList
val aliasNamespaces = ArrayList()
for (namespace in pbMacro.namespaceStackList) {
aliasNamespaces.add(
- Macro.Namespace(namespace.prefix, namespace.packageName, namespace.isPrivate)
+ Macro.Namespace(namespace.prefix, namespace.packageName, namespace.isPrivate)
)
}
macro.aliasNamespaces = aliasNamespaces
@@ -563,13 +647,15 @@ fun deserializeItemFromPb(
item: Resources.Item,
valuePool: StringPool,
config: ConfigDescription,
- logger: ILogger?): Item? = when (item.getValueCase()) {
+ logger: ILogger?
+): Item? = when (item.getValueCase()) {
Resources.Item.ValueCase.REF -> deserializeReferenceFromPb(item.getRef(), logger)
Resources.Item.ValueCase.STR -> deserializeStringFromPb(item.getStr(), valuePool)
Resources.Item.ValueCase.RAW_STR -> deserializeRawFromPb(item.getRawStr(), valuePool)
Resources.Item.ValueCase.STYLED_STR ->
deserializeStyledStrFromPb(item.getStyledStr(), valuePool)
+
Resources.Item.ValueCase.FILE -> deserializeFileRefFromPb(item.getFile(), valuePool, config)
Resources.Item.ValueCase.ID -> Id()
Resources.Item.ValueCase.PRIM -> deserializeBinPrimitiveFromPb(item.getPrim(), logger)
@@ -585,7 +671,8 @@ fun deserializeValueFromPb(
valuePool: StringPool,
config: ConfigDescription,
sourcePool: ResStringPool,
- logger: ILogger?): Value? {
+ logger: ILogger?
+): Value? {
val valueResource = when {
value.hasItem() -> deserializeItemFromPb(value.getItem(), valuePool, config, logger)
@@ -595,16 +682,22 @@ fun deserializeValueFromPb(
when (compoundValue.getValueCase()) {
Resources.CompoundValue.ValueCase.ATTR ->
deserializeAttrFromPb(compoundValue.getAttr(), sourcePool, logger)
+
Resources.CompoundValue.ValueCase.STYLE ->
deserializeStyleFromPb(compoundValue.getStyle(), valuePool, config, sourcePool, logger)
+
Resources.CompoundValue.ValueCase.STYLEABLE ->
deserializeStyleableFromPb(compoundValue.getStyleable(), sourcePool, logger)
+
Resources.CompoundValue.ValueCase.ARRAY ->
deserializeArrayFromPb(compoundValue.getArray(), valuePool, config, sourcePool, logger)
+
Resources.CompoundValue.ValueCase.PLURAL ->
deserializePluralFromPb(compoundValue.getPlural(), valuePool, config, sourcePool, logger)
+
Resources.CompoundValue.ValueCase.MACRO ->
deserializeMacroFromPb(compoundValue.getMacro(), valuePool, config, sourcePool, logger)
+
else -> {
val errorMsg = "Unrecognized compoundValue value case %s"
logger?.error(null, errorMsg, compoundValue.valueCase)
@@ -612,6 +705,7 @@ fun deserializeValueFromPb(
}
}
}
+
else -> {
val errorMsg = "Unrecognized case for serialized value %s"
logger?.error(null, errorMsg, value.valueCase)
@@ -634,12 +728,13 @@ fun deserializePackageFromPb(
sourcePool: ResStringPool,
overlayables: List,
logger: ILogger?,
- table: ResourceTable): Boolean {
+ table: ResourceTable
+): Boolean {
val packageId =
if (original.hasPackageId()) original.getPackageId().getId().toByte() else 0.toByte()
- val idIndex = MutableIntObjectMap()
+ val idIndex = mutableIntObjectMapOf()
val resourcePackage =
table.createPackageAllowingDuplicateNames(original.getPackageName(), packageId)
@@ -672,11 +767,12 @@ fun deserializePackageFromPb(
// Propagate the visibility up to the type group.
ResourceVisibility.PUBLIC -> resourceGroup.visibility = ResourceVisibility.PUBLIC
// Propagate private, only if previously undefined.
- ResourceVisibility.PRIVATE-> {
+ ResourceVisibility.PRIVATE -> {
if (resourceGroup.visibility == ResourceVisibility.UNDEFINED) {
resourceGroup.visibility = ResourceVisibility.PRIVATE
}
}
+
else -> {}
}
@@ -706,7 +802,7 @@ fun deserializePackageFromPb(
val overlayableItem = entry.getOverlayableItem()
if (overlayableItem.getOverlayableIdx() >= overlayables.size) {
val errorMsg = "Illegal value for overlayable id '%s'. Because only '%s' overlayables" +
- "exist in proto."
+ "exist in proto."
logger?.error(null, errorMsg, overlayableItem.overlayableIdx, overlayables.size)
return false
}
@@ -715,7 +811,8 @@ fun deserializePackageFromPb(
overlayableItem,
overlayables[overlayableItem.getOverlayableIdx()],
sourcePool,
- logger)
+ logger
+ )
resourceOverlayable ?: return false
resourceEntry.overlayable = resourceOverlayable
@@ -724,9 +821,11 @@ fun deserializePackageFromPb(
val resourceId = resourceIdFromParts(
original.getPackageId().getId().toByte(),
group.getTypeId().getId().toByte(),
- entry.getEntryId().getId().toShort())
+ entry.getEntryId().getId().toShort()
+ )
if (resourceId.isValidId()) {
- idIndex.put(resourceId, ResourceName(resourcePackage.name, resourceGroup.type, resourceEntry.name))
+ idIndex[resourceId] =
+ ResourceName(resourcePackage.name, resourceGroup.type, resourceEntry.name)
}
for (configValue in entry.getConfigValueList()) {
@@ -744,13 +843,15 @@ fun deserializePackageFromPb(
errorMsg,
ResourceName(resourcePackage.name, resourceGroup.type, resourceEntry.name),
resourceConfig,
- config.product)
+ config.product
+ )
return false
}
resourceConfigValue.value =
deserializeValueFromPb(
- configValue.getValue(), table.stringPool, resourceConfig, sourcePool, logger)
+ configValue.getValue(), table.stringPool, resourceConfig, sourcePool, logger
+ )
resourceConfigValue.value ?: return false
}
@@ -780,11 +881,13 @@ fun deserializePackageFromPb(
}
fun deserializeTableFromPb(
- table: Resources.ResourceTable, outTable: ResourceTable, logger: ILogger?): Boolean {
+ table: Resources.ResourceTable, outTable: ResourceTable, logger: ILogger?
+): Boolean {
val sourcePool = ResStringPool.get(
table.getSourcePool().getData().asReadOnlyByteBuffer(),
- table.getSourcePool().getSerializedSize())
+ table.getSourcePool().getSerializedSize()
+ )
// Deserialize the overlayable groups of a table
val overlayables = mutableListOf()
diff --git a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoSerialize.kt b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoSerialize.kt
old mode 100755
new mode 100644
index af8aeb10c..d4b5f19dd
--- a/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoSerialize.kt
+++ b/subprojects/aaptcompiler/src/main/java/com/android/aaptcompiler/proto/ProtoSerialize.kt
@@ -1,6 +1,7 @@
package com.android.aaptcompiler.proto
import android.aapt.pb.internal.ResourcesInternal
+import androidx.collection.intIntMapOf
import com.android.aapt.ConfigurationOuterClass
import com.android.aapt.Resources
import com.android.aaptcompiler.ArrayResource
@@ -17,6 +18,7 @@ import com.android.aaptcompiler.OverlayableItem
import com.android.aaptcompiler.Plural
import com.android.aaptcompiler.RawString
import com.android.aaptcompiler.Reference
+import com.android.aaptcompiler.ResourceCompilationException
import com.android.aaptcompiler.ResourceFile
import com.android.aaptcompiler.ResourceName
import com.android.aaptcompiler.ResourceTable
@@ -31,13 +33,17 @@ import com.android.aaptcompiler.android.ResTableConfig
import com.android.aaptcompiler.android.ResValue
import com.android.aaptcompiler.blameSource
import com.android.aaptcompiler.buffer.BigBuffer
-import com.itsaky.androidide.layoutlib.resources.ResourceVisibility
import com.android.utils.ILogger
import com.google.protobuf.ByteString
+import com.itsaky.androidide.layoutlib.resources.ResourceVisibility
internal fun serializePoolToPb(pool: StringPool, logger: ILogger?): Resources.StringPool {
val buffer = BigBuffer(1024)
- pool.flattenUtf8(buffer, logger)
+ try {
+ pool.flattenUtf8(buffer, logger)
+ } catch (e: Exception) {
+ throw ResourceCompilationException("Failed to flatten utf-8 string.", e)
+ }
val builder = Resources.StringPool.newBuilder()
builder.setData(ByteString.copyFrom(buffer.toBytes()))
@@ -53,7 +59,8 @@ internal fun serializeSourceToPb(source: Source, sourcePool: StringPool): Resour
sourceBuilder.setPathIdx(ref.index())
if (source.line != null) {
sourceBuilder.setPosition(
- Resources.SourcePosition.newBuilder().setLineNumber(source.line).build())
+ Resources.SourcePosition.newBuilder().setLineNumber(source.line).build()
+ )
}
return sourceBuilder.build()
}
@@ -63,10 +70,12 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
val sourcePool = StringPool()
- tableBuilder.addToolFingerprint(Resources.ToolFingerprint.newBuilder()
- .setTool(ToolFingerprint.TOOL_NAME)
- .setVersion(ToolFingerprint.FINGERPRINT)
- .build())
+ tableBuilder.addToolFingerprint(
+ Resources.ToolFingerprint.newBuilder()
+ .setTool(ToolFingerprint.TOOL_NAME)
+ .setVersion(ToolFingerprint.FINGERPRINT)
+ .build()
+ )
val overlayables = mutableListOf()
for (resourcePackage in table.packages) {
val packageBuilder = Resources.Package.newBuilder()
@@ -76,7 +85,8 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
packageBuilder.setPackageId(
Resources.PackageId.newBuilder()
.setId(packageId.toInt())
- .build())
+ .build()
+ )
}
packageBuilder.setPackageName(resourcePackage.name)
@@ -88,7 +98,8 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
groupBuilder.setTypeId(
Resources.TypeId.newBuilder()
.setId(groupId.toInt())
- .build())
+ .build()
+ )
}
groupBuilder.setName(resourceGroup.type.tagName)
@@ -102,7 +113,8 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
entryBuilder.setEntryId(
Resources.EntryId.newBuilder()
.setId(entryId.toInt())
- .build())
+ .build()
+ )
}
entryBuilder.setName(entry.name)
@@ -114,7 +126,8 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
visibilityBuilder
.setLevel(serializeVisibilityToPb(entry.visibility.level))
.setComment(entry.visibility.comment)
- .build())
+ .build()
+ )
val entryAllowNew = entry.allowNew
if (entryAllowNew != null) {
@@ -125,7 +138,8 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
entryBuilder.setAllowNew(
allowNewBuilder
.setComment(entryAllowNew.comment)
- .build())
+ .build()
+ )
}
val entryOverlayableItem = entry.overlayable
@@ -136,7 +150,9 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
entryOverlayableItem,
overlayables,
tableBuilder,
- sourcePool))
+ sourcePool
+ )
+ )
}
for (configValue in entry.values) {
@@ -159,9 +175,10 @@ fun serializeTableToPb(table: ResourceTable, logger: ILogger? = null): Resources
}
fun serializeVisibilityToPb(resourceVisibility: ResourceVisibility) =
- when(resourceVisibility) {
+ when (resourceVisibility) {
ResourceVisibility.PRIVATE,
- ResourceVisibility.PRIVATE_XML_ONLY -> Resources.Visibility.Level.PRIVATE
+ ResourceVisibility.PRIVATE_XML_ONLY -> Resources.Visibility.Level.PRIVATE
+
ResourceVisibility.PUBLIC -> Resources.Visibility.Level.PUBLIC
else -> Resources.Visibility.Level.UNKNOWN
}
@@ -179,7 +196,9 @@ fun serializeCompiledFileToPb(file: ResourceFile): ResourcesInternal.CompiledFil
.setResourceName(exportedResourceName.name.toString())
.setSource(
Resources.SourcePosition.newBuilder()
- .setLineNumber(exportedResourceName.line)))
+ .setLineNumber(exportedResourceName.line)
+ )
+ )
}
return compiledFile.build()
}
@@ -187,7 +206,8 @@ fun serializeCompiledFileToPb(file: ResourceFile): ResourcesInternal.CompiledFil
fun serializeConfigToPb(
config: ConfigDescription,
product: String?,
- logger: ILogger?): ConfigurationOuterClass.Configuration {
+ logger: ILogger?
+): ConfigurationOuterClass.Configuration {
val configBuilder = ConfigurationOuterClass.Configuration.newBuilder()
configBuilder.setMcc(config.mcc.toInt() and 0xffff)
@@ -198,10 +218,13 @@ fun serializeConfigToPb(
when ((config.screenLayout.toInt() and ResTableConfig.SCREEN_LAYOUT.DIR_MASK).toByte()) {
ResTableConfig.SCREEN_LAYOUT.DIR_LTR ->
ConfigurationOuterClass.Configuration.LayoutDirection.LAYOUT_DIRECTION_LTR
+
ResTableConfig.SCREEN_LAYOUT.DIR_RTL ->
ConfigurationOuterClass.Configuration.LayoutDirection.LAYOUT_DIRECTION_RTL
+
else -> ConfigurationOuterClass.Configuration.LayoutDirection.LAYOUT_DIRECTION_UNSET
- })
+ }
+ )
configBuilder.setScreenWidth(config.screenWidth)
configBuilder.setScreenHeight(config.screenHeight)
@@ -213,14 +236,19 @@ fun serializeConfigToPb(
when ((config.screenLayout.toInt() and ResTableConfig.SCREEN_LAYOUT.SIZE_MASK).toByte()) {
ResTableConfig.SCREEN_LAYOUT.SIZE_SMALL ->
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_SMALL
+
ResTableConfig.SCREEN_LAYOUT.SIZE_NORMAL ->
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_NORMAL
+
ResTableConfig.SCREEN_LAYOUT.SIZE_LARGE ->
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_LARGE
+
ResTableConfig.SCREEN_LAYOUT.SIZE_XLARGE ->
ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_XLARGE
+
else -> ConfigurationOuterClass.Configuration.ScreenLayoutSize.SCREEN_LAYOUT_SIZE_UNSET
- })
+ }
+ )
configBuilder.setScreenLayoutLong(
when (
@@ -228,10 +256,13 @@ fun serializeConfigToPb(
ResTableConfig.SCREEN_LAYOUT.SCREENLONG_YES ->
ConfigurationOuterClass.Configuration.ScreenLayoutLong.SCREEN_LAYOUT_LONG_LONG
+
ResTableConfig.SCREEN_LAYOUT.SCREENLONG_NO ->
ConfigurationOuterClass.Configuration.ScreenLayoutLong.SCREEN_LAYOUT_LONG_NOTLONG
+
else -> ConfigurationOuterClass.Configuration.ScreenLayoutLong.SCREEN_LAYOUT_LONG_UNSET
- })
+ }
+ )
configBuilder.setScreenRound(
when (
@@ -239,65 +270,87 @@ fun serializeConfigToPb(
ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_YES ->
ConfigurationOuterClass.Configuration.ScreenRound.SCREEN_ROUND_ROUND
+
ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_NO ->
ConfigurationOuterClass.Configuration.ScreenRound.SCREEN_ROUND_NOTROUND
+
else -> ConfigurationOuterClass.Configuration.ScreenRound.SCREEN_ROUND_UNSET
- })
+ }
+ )
configBuilder.setWideColorGamut(
when ((config.colorMode.toInt() and ResTableConfig.COLOR_MODE.WIDE_GAMUT_MASK).toByte()) {
ResTableConfig.COLOR_MODE.WIDE_GAMUT_YES ->
ConfigurationOuterClass.Configuration.WideColorGamut.WIDE_COLOR_GAMUT_WIDECG
+
ResTableConfig.COLOR_MODE.WIDE_GAMUT_NO ->
ConfigurationOuterClass.Configuration.WideColorGamut.WIDE_COLOR_GAMUT_NOWIDECG
+
else -> ConfigurationOuterClass.Configuration.WideColorGamut.WIDE_COLOR_GAMUT_UNSET
- })
+ }
+ )
configBuilder.setHdr(
when ((config.colorMode.toInt() and ResTableConfig.COLOR_MODE.HDR_MASK).toByte()) {
ResTableConfig.COLOR_MODE.HDR_YES -> ConfigurationOuterClass.Configuration.Hdr.HDR_HIGHDR
ResTableConfig.COLOR_MODE.HDR_NO -> ConfigurationOuterClass.Configuration.Hdr.HDR_LOWDR
else -> ConfigurationOuterClass.Configuration.Hdr.HDR_UNSET
- })
+ }
+ )
configBuilder.setOrientation(
when (config.orientation) {
ResTableConfig.ORIENTATION.PORT ->
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_PORT
+
ResTableConfig.ORIENTATION.LAND ->
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_LAND
+
ResTableConfig.ORIENTATION.SQUARE ->
ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_SQUARE
+
else -> ConfigurationOuterClass.Configuration.Orientation.ORIENTATION_UNSET
- })
+ }
+ )
configBuilder.setUiModeType(
when ((config.uiMode.toInt() and ResTableConfig.UI_MODE.TYPE_MASK).toByte()) {
ResTableConfig.UI_MODE.TYPE_NORMAL ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_NORMAL
+
ResTableConfig.UI_MODE.TYPE_DESK ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_DESK
+
ResTableConfig.UI_MODE.TYPE_CAR ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_CAR
+
ResTableConfig.UI_MODE.TYPE_TELEVISION ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_TELEVISION
+
ResTableConfig.UI_MODE.TYPE_APPLIANCE ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_APPLIANCE
+
ResTableConfig.UI_MODE.TYPE_WATCH ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_WATCH
+
ResTableConfig.UI_MODE.TYPE_VR_HEADSET ->
ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_VRHEADSET
+
else -> ConfigurationOuterClass.Configuration.UiModeType.UI_MODE_TYPE_UNSET
- })
+ }
+ )
configBuilder.setUiModeNight(
when ((config.uiMode.toInt() and ResTableConfig.UI_MODE.NIGHT_MASK).toByte()) {
ResTableConfig.UI_MODE.NIGHT_YES ->
ConfigurationOuterClass.Configuration.UiModeNight.UI_MODE_NIGHT_NIGHT
+
ResTableConfig.UI_MODE.NIGHT_NO ->
ConfigurationOuterClass.Configuration.UiModeNight.UI_MODE_NIGHT_NOTNIGHT
+
else -> ConfigurationOuterClass.Configuration.UiModeNight.UI_MODE_NIGHT_UNSET
- })
+ }
+ )
configBuilder.setDensity(config.density)
@@ -305,56 +358,91 @@ fun serializeConfigToPb(
when (config.touchscreen) {
ResTableConfig.TOUCHSCREEN.NOTOUCH ->
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_NOTOUCH
+
ResTableConfig.TOUCHSCREEN.STYLUS ->
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_STYLUS
+
ResTableConfig.TOUCHSCREEN.FINGER ->
ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_FINGER
+
else -> ConfigurationOuterClass.Configuration.Touchscreen.TOUCHSCREEN_UNSET
- })
+ }
+ )
configBuilder.setKeysHidden(
when ((config.inputFlags.toInt() and ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_MASK).toByte()) {
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_NO ->
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSEXPOSED
+
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_YES ->
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSHIDDEN
+
ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_SOFT ->
ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_KEYSSOFT
+
else -> ConfigurationOuterClass.Configuration.KeysHidden.KEYS_HIDDEN_UNSET
- })
+ }
+ )
configBuilder.setKeyboard(
when (config.keyboard) {
ResTableConfig.KEYBOARD.NOKEYS ->
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_NOKEYS
+
ResTableConfig.KEYBOARD.QWERTY ->
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_QWERTY
+
ResTableConfig.KEYBOARD.TWELVEKEY ->
ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_TWELVEKEY
+
else -> ConfigurationOuterClass.Configuration.Keyboard.KEYBOARD_UNSET
- })
+ }
+ )
configBuilder.setNavHidden(
when ((config.inputFlags.toInt() and ResTableConfig.INPUT_FLAGS.NAVHIDDEN_MASK).toByte()) {
ResTableConfig.INPUT_FLAGS.NAVHIDDEN_YES ->
ConfigurationOuterClass.Configuration.NavHidden.NAV_HIDDEN_NAVHIDDEN
+
ResTableConfig.INPUT_FLAGS.NAVHIDDEN_NO ->
ConfigurationOuterClass.Configuration.NavHidden.NAV_HIDDEN_NAVEXPOSED
+
else -> ConfigurationOuterClass.Configuration.NavHidden.NAV_HIDDEN_UNSET
- })
+ }
+ )
configBuilder.setNavigation(
when (config.navigation) {
ResTableConfig.NAVIGATION.NONAV ->
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_NONAV
+
ResTableConfig.NAVIGATION.DPAD ->
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_DPAD
+
ResTableConfig.NAVIGATION.TRACKBALL ->
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_TRACKBALL
+
ResTableConfig.NAVIGATION.WHEEL ->
ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_WHEEL
+
else -> ConfigurationOuterClass.Configuration.Navigation.NAVIGATION_UNSET
- })
+ }
+ )
+
+ configBuilder.setGrammaticalGender(
+ when (config.grammaticalInflection) {
+ ResTableConfig.GRAMMATICAL_GENDER.NEUTER ->
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_NEUTER
+
+ ResTableConfig.GRAMMATICAL_GENDER.FEMININE ->
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_FEMININE
+
+ ResTableConfig.GRAMMATICAL_GENDER.MASCULINE ->
+ ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_MASCULINE
+
+ else -> ConfigurationOuterClass.Configuration.GrammaticalGender.GRAM_GENDER_USET
+ }
+ )
configBuilder.setSdkVersion(config.sdkVersion.toInt() and 0xffff)
@@ -369,7 +457,8 @@ fun serializeOverlayableToPb(
item: OverlayableItem,
overlayables: MutableList,
table: Resources.ResourceTable.Builder,
- sourcePool: StringPool): Resources.OverlayableItem {
+ sourcePool: StringPool
+): Resources.OverlayableItem {
// Retrieve the index of the overlayable in the list of groups that have already been serialized.
val foundIndex = overlayables.indexOf(item.overlayable)
@@ -427,6 +516,7 @@ fun serializeOverlayableToPb(
fun serializeReferenceTypeToPb(type: Reference.Type) = when (type) {
Reference.Type.RESOURCE ->
Resources.Reference.Type.REFERENCE
+
Reference.Type.ATTRIBUTE ->
Resources.Reference.Type.ATTRIBUTE
}
@@ -495,7 +585,8 @@ fun serializeBinPrimitiveToPb(primitive: BinaryPrimitive, logger: ILogger?): Res
if (resVal == null) {
logger?.error(
- null, "%s, Failed to serialize primitive %s.", blameSource(primitive.source), primitive)
+ null, "%s, Failed to serialize primitive %s.", blameSource(primitive.source), primitive
+ )
return primitiveBuilder.build()
}
@@ -504,14 +595,17 @@ fun serializeBinPrimitiveToPb(primitive: BinaryPrimitive, logger: ILogger?): Res
when (resVal.data) {
ResValue.NullFormat.UNDEFINED ->
primitiveBuilder.setNullValue(Resources.Primitive.NullType.newBuilder().build())
+
ResValue.NullFormat.EMPTY ->
primitiveBuilder.setEmptyValue(Resources.Primitive.EmptyType.newBuilder().build())
+
else -> {
val errorMsg = "%s, Invalid null format value '%s' for primitive %s."
logger?.error(null, errorMsg, blameSource(primitive.source), resVal.data, primitive)
}
}
}
+
ResValue.DataType.FLOAT -> primitiveBuilder.setFloatValue(Float.fromBits(resVal.data))
ResValue.DataType.DIMENSION -> primitiveBuilder.setDimensionValue(resVal.data)
ResValue.DataType.FRACTION -> primitiveBuilder.setFractionValue(resVal.data)
@@ -548,7 +642,8 @@ fun serializeAttrToPb(attribute: AttributeResource, sourcePool: StringPool): Res
.setName(serializeReferenceToPb(symbol.symbol))
.setValue(symbol.value)
.setType(symbol.type.toInt())
- .build())
+ .build()
+ )
}
return attrBuilder.build()
@@ -575,7 +670,8 @@ fun serializeStyleToPb(style: Style, sourcePool: StringPool, logger: ILogger?):
.setKey(serializeReferenceToPb(entry.key))
.setComment(entry.key.comment)
.setItem(serializeItemToPb(entry.value!!, logger))
- .build())
+ .build()
+ )
}
return styleBuilder.build()
}
@@ -592,13 +688,15 @@ fun serializeStyleableToPb(styleable: Styleable, sourcePool: StringPool): Resour
entryBuilder
.setComment(entry.comment)
.setAttr(serializeReferenceToPb(entry))
- .build())
+ .build()
+ )
}
return styleableBuilder.build()
}
fun serializeArrayToPb(
- array: ArrayResource, sourcePool: StringPool, logger: ILogger?): Resources.Array {
+ array: ArrayResource, sourcePool: StringPool, logger: ILogger?
+): Resources.Array {
val arrayBuilder = Resources.Array.newBuilder()
for (element in array.elements) {
@@ -610,13 +708,15 @@ fun serializeArrayToPb(
entryBuilder
.setComment(element.comment)
.setItem(serializeItemToPb(element, logger))
- .build())
+ .build()
+ )
}
return arrayBuilder.build()
}
fun serializePluralToPb(
- plural: Plural, sourcePool: StringPool, logger: ILogger?): Resources.Plural {
+ plural: Plural, sourcePool: StringPool, logger: ILogger?
+): Resources.Plural {
val pluralBuilder = Resources.Plural.newBuilder()
for (type in Plural.Type.TYPES) {
@@ -631,43 +731,43 @@ fun serializePluralToPb(
.setComment(entry.comment)
.setArity(serializePluralTypeToPb(type))
.setItem(serializeItemToPb(entry, logger))
- .build())
+ .build()
+ )
}
return pluralBuilder.build()
}
fun serializeMacroToPb(macro: Macro): Resources.MacroBody {
+ val macroBuilder = Resources.MacroBody.newBuilder()
+ macroBuilder.rawString = macro.rawValue!!
- val macroBuilder = Resources.MacroBody.newBuilder()
- macroBuilder.rawString = macro.rawValue!!
+ val styleString = Resources.StyleString.newBuilder()
+ styleString.str = macro.styleString!!.str
+ for (span in macro.styleString!!.spans) {
+ val spansBuilder = Resources.StyleString.Span.newBuilder()
+ spansBuilder.name = span.name
+ spansBuilder.startIndex = span.firstChar
+ spansBuilder.endIndex = span.lastChar
+ styleString.addSpans(spansBuilder.build())
+ }
+ macroBuilder.styleString = styleString.build()
- val styleString = macroBuilder.styleStringBuilder
- styleString.str = macro.styleString!!.str
- for (span in macro.styleString!!.spans) {
- val spansBuilder = styleString.addSpansBuilder()
- spansBuilder.name = span.name
- spansBuilder.startIndex = span.firstChar
- spansBuilder.endIndex = span.lastChar
- styleString.addSpans(spansBuilder.build())
- }
- macroBuilder.styleString = styleString.build()
+ for (untranslatables in macro.untranslatables) {
+ val section = Resources.UntranslatableSection.newBuilder()
+ section.startIndex = untranslatables.startIndex.toLong()
+ section.endIndex = untranslatables.endIndex.toLong()
+ macroBuilder.addUntranslatableSections(section.build())
+ }
- for (untranslatables in macro.untranslatables) {
- val section = macroBuilder.addUntranslatableSectionsBuilder()
- section.startIndex = untranslatables.startIndex.toLong()
- section.endIndex = untranslatables.endIndex.toLong()
- macroBuilder.addUntranslatableSections(section.build())
- }
+ for (aliasNamespace in macro.aliasNamespaces) {
+ val namespace = Resources.NamespaceAlias.newBuilder()
+ namespace.prefix = aliasNamespace.alias
+ namespace.packageName = aliasNamespace.packageName
+ namespace.isPrivate = aliasNamespace.isPrivate
+ macroBuilder.addNamespaceStack(namespace.build())
+ }
- for (aliasNamespace in macro.aliasNamespaces) {
- val namespace = macroBuilder.addNamespaceStackBuilder()
- namespace.prefix = aliasNamespace.alias
- namespace.packageName = aliasNamespace.packageName
- namespace.isPrivate = aliasNamespace.isPrivate
- macroBuilder.addNamespaceStack(namespace.build())
- }
-
- return macroBuilder.build()
+ return macroBuilder.build()
}
fun serializeItemToPb(item: Item, logger: ILogger?): Resources.Item {
@@ -709,7 +809,7 @@ fun serializeValueToPb(value: Value, sourcePool: StringPool, logger: ILogger?):
}
valueBuilder.setCompoundValue(compoundBuilder.build())
}
- if (value.source.isNotEmpty()){
+ if (value.source.isNotEmpty()) {
valueBuilder.setSource(serializeSourceToPb(value.source, sourcePool))
}
return valueBuilder
diff --git a/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Configuration.proto b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Configuration.proto
new file mode 100644
index 000000000..3998ab033
--- /dev/null
+++ b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Configuration.proto
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+syntax = "proto3";
+
+//package aapt.pb;
+
+option java_package = "com.android.aapt";
+
+// A description of the requirements a device must have in order for a
+// resource to be matched and selected.
+message Configuration {
+ enum LayoutDirection {
+ LAYOUT_DIRECTION_UNSET = 0;
+ LAYOUT_DIRECTION_LTR = 1;
+ LAYOUT_DIRECTION_RTL = 2;
+ }
+ enum ScreenLayoutSize {
+ SCREEN_LAYOUT_SIZE_UNSET = 0;
+ SCREEN_LAYOUT_SIZE_SMALL = 1;
+ SCREEN_LAYOUT_SIZE_NORMAL = 2;
+ SCREEN_LAYOUT_SIZE_LARGE = 3;
+ SCREEN_LAYOUT_SIZE_XLARGE = 4;
+ }
+ enum ScreenLayoutLong {
+ SCREEN_LAYOUT_LONG_UNSET = 0;
+ SCREEN_LAYOUT_LONG_LONG = 1;
+ SCREEN_LAYOUT_LONG_NOTLONG = 2;
+ }
+ enum ScreenRound {
+ SCREEN_ROUND_UNSET = 0;
+ SCREEN_ROUND_ROUND = 1;
+ SCREEN_ROUND_NOTROUND = 2;
+ }
+ enum WideColorGamut {
+ WIDE_COLOR_GAMUT_UNSET = 0;
+ WIDE_COLOR_GAMUT_WIDECG = 1;
+ WIDE_COLOR_GAMUT_NOWIDECG = 2;
+ }
+ enum Hdr {
+ HDR_UNSET = 0;
+ HDR_HIGHDR = 1;
+ HDR_LOWDR = 2;
+ }
+ enum Orientation {
+ ORIENTATION_UNSET = 0;
+ ORIENTATION_PORT = 1;
+ ORIENTATION_LAND = 2;
+ ORIENTATION_SQUARE = 3;
+ }
+ enum UiModeType {
+ UI_MODE_TYPE_UNSET = 0;
+ UI_MODE_TYPE_NORMAL = 1;
+ UI_MODE_TYPE_DESK = 2;
+ UI_MODE_TYPE_CAR = 3;
+ UI_MODE_TYPE_TELEVISION = 4;
+ UI_MODE_TYPE_APPLIANCE = 5;
+ UI_MODE_TYPE_WATCH = 6;
+ UI_MODE_TYPE_VRHEADSET = 7;
+ }
+ enum UiModeNight {
+ UI_MODE_NIGHT_UNSET = 0;
+ UI_MODE_NIGHT_NIGHT = 1;
+ UI_MODE_NIGHT_NOTNIGHT = 2;
+ }
+ enum Touchscreen {
+ TOUCHSCREEN_UNSET = 0;
+ TOUCHSCREEN_NOTOUCH = 1;
+ TOUCHSCREEN_STYLUS = 2;
+ TOUCHSCREEN_FINGER = 3;
+ }
+ enum KeysHidden {
+ KEYS_HIDDEN_UNSET = 0;
+ KEYS_HIDDEN_KEYSEXPOSED = 1;
+ KEYS_HIDDEN_KEYSHIDDEN = 2;
+ KEYS_HIDDEN_KEYSSOFT = 3;
+ }
+ enum Keyboard {
+ KEYBOARD_UNSET = 0;
+ KEYBOARD_NOKEYS = 1;
+ KEYBOARD_QWERTY = 2;
+ KEYBOARD_TWELVEKEY = 3;
+ }
+ enum NavHidden {
+ NAV_HIDDEN_UNSET = 0;
+ NAV_HIDDEN_NAVEXPOSED = 1;
+ NAV_HIDDEN_NAVHIDDEN = 2;
+ }
+ enum Navigation {
+ NAVIGATION_UNSET = 0;
+ NAVIGATION_NONAV = 1;
+ NAVIGATION_DPAD = 2;
+ NAVIGATION_TRACKBALL = 3;
+ NAVIGATION_WHEEL = 4;
+ }
+ enum GrammaticalGender {
+ GRAM_GENDER_USET = 0;
+ GRAM_GENDER_NEUTER = 1;
+ GRAM_GENDER_FEMININE = 2;
+ GRAM_GENDER_MASCULINE = 3;
+ }
+ //
+ // Axis/dimensions that are understood by the runtime.
+ //
+ // Mobile country code.
+ uint32 mcc = 1;
+ // Mobile network code.
+ uint32 mnc = 2;
+ // BCP-47 locale tag.
+ string locale = 3;
+ // Left-to-right, right-to-left...
+ LayoutDirection layout_direction = 4;
+ // Screen width in pixels. Prefer screen_width_dp.
+ uint32 screen_width = 5;
+ // Screen height in pixels. Prefer screen_height_dp.
+ uint32 screen_height = 6;
+ // Screen width in density independent pixels (dp).
+ uint32 screen_width_dp = 7;
+ // Screen height in density independent pixels (dp).
+ uint32 screen_height_dp = 8;
+ // The smallest screen dimension, regardless of orientation, in dp.
+ uint32 smallest_screen_width_dp = 9;
+ // Whether the device screen is classified as small, normal, large, xlarge.
+ ScreenLayoutSize screen_layout_size = 10;
+ // Whether the device screen is long.
+ ScreenLayoutLong screen_layout_long = 11;
+ // Whether the screen is round (Android Wear).
+ ScreenRound screen_round = 12;
+ // Whether the screen supports wide color gamut.
+ WideColorGamut wide_color_gamut = 13;
+ // Whether the screen has high dynamic range.
+ Hdr hdr = 14;
+ // Which orientation the device is in (portrait, landscape).
+ Orientation orientation = 15;
+ // Which type of UI mode the device is in (television, car, etc.).
+ UiModeType ui_mode_type = 16;
+ // Whether the device is in night mode.
+ UiModeNight ui_mode_night = 17;
+ // The device's screen density in dots-per-inch (dpi).
+ uint32 density = 18;
+ // Whether a touchscreen exists, supports a stylus, or finger.
+ Touchscreen touchscreen = 19;
+ // Whether the keyboard hardware keys are currently hidden, exposed, or
+ // if the keyboard is a software keyboard.
+ KeysHidden keys_hidden = 20;
+ // The type of keyboard present (none, QWERTY, 12-key).
+ Keyboard keyboard = 21;
+ // Whether the navigation is exposed or hidden.
+ NavHidden nav_hidden = 22;
+ // The type of navigation present on the device
+ // (trackball, wheel, dpad, etc.).
+ Navigation navigation = 23;
+ // The minimum SDK version of the device.
+ uint32 sdk_version = 24;
+ // Grammatical gender.
+ GrammaticalGender grammatical_gender = 26;
+ //
+ // Build-time only dimensions.
+ //
+ string product = 25;
+}
\ No newline at end of file
diff --git a/subprojects/aaptcompiler/src/main/proto/com/android/aapt/README.md b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/README.md
new file mode 100644
index 000000000..2bfb38a06
--- /dev/null
+++ b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/README.md
@@ -0,0 +1,5 @@
+# AAPT2 Protobuf sources
+
+These files are taken from
+the [AAPT2 sources](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/tools/aapt2/),
+licensed under The Apache License 2.0. See the files for the license.
\ No newline at end of file
diff --git a/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Resources.proto b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Resources.proto
new file mode 100644
index 000000000..668d58599
--- /dev/null
+++ b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/Resources.proto
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+syntax = "proto3";
+
+import "com/android/aapt/Configuration.proto";
+
+// package aapt.pb;
+
+option java_package = "com.android.aapt";
+
+
+// A string pool that wraps the binary form of the C++ class android::ResStringPool.
+message StringPool {
+ bytes data = 1;
+}
+// The position of a declared entity within a file.
+message SourcePosition {
+ uint32 line_number = 1;
+ uint32 column_number = 2;
+}
+// Developer friendly source file information for an entity in the resource table.
+message Source {
+ // The index of the string path within the source string pool of a ResourceTable.
+ uint32 path_idx = 1;
+ SourcePosition position = 2;
+}
+// The name and version fingerprint of a build tool.
+message ToolFingerprint {
+ string tool = 1;
+ string version = 2;
+}
+// References to non local resources
+message DynamicRefTable {
+ PackageId package_id = 1;
+ string package_name = 2;
+}
+// Top level message representing a resource table.
+message ResourceTable {
+ // The string pool containing source paths referenced throughout the resource table. This does
+ // not end up in the final binary ARSC file.
+ StringPool source_pool = 1;
+ // Resource definitions corresponding to an Android package.
+ repeated Package package = 2;
+ // The declarations within the resource table.
+ repeated Overlayable overlayable = 3;
+ // The version fingerprints of the tools that built the resource table.
+ repeated ToolFingerprint tool_fingerprint = 4;
+ repeated DynamicRefTable dynamic_ref_table = 5;
+}
+// A package ID in the range [0x00, 0xff].
+message PackageId {
+ uint32 id = 1;
+}
+// Defines resources for an Android package.
+message Package {
+ // The package ID of this package, in the range [0x00, 0xff].
+ // - ID 0x00 is reserved for shared libraries, or when the ID is assigned at run-time.
+ // - ID 0x01 is reserved for the 'android' package (framework).
+ // - ID range [0x02, 0x7f) is reserved for auto-assignment to shared libraries at run-time.
+ // - ID 0x7f is reserved for the application package.
+ // - IDs > 0x7f are reserved for the application as well and are treated as feature splits.
+ // This may not be set if no ID was assigned.
+ PackageId package_id = 1;
+ // The Java compatible Android package name of the app.
+ string package_name = 2;
+ // The series of types defined by the package.
+ repeated Type type = 3;
+}
+// A type ID in the range [0x01, 0xff].
+message TypeId {
+ uint32 id = 1;
+}
+// A set of resources grouped under a common type. Such types include string, layout, xml, dimen,
+// attr, etc. This maps to the second part of a resource identifier in Java (R.type.entry).
+message Type {
+ // The ID of the type. This may not be set if no ID was assigned.
+ TypeId type_id = 1;
+ // The name of the type. This corresponds to the 'type' part of a full resource name of the form
+ // package:type/entry. The set of legal type names is listed in Resource.cpp.
+ string name = 2;
+ // The entries defined for this type.
+ repeated Entry entry = 3;
+}
+// The Visibility of a symbol/entry (public, private, undefined).
+message Visibility {
+ // The visibility of the resource outside of its package.
+ enum Level {
+ // No visibility was explicitly specified. This is typically treated as private.
+ // The distinction is important when two separate R.java files are generated: a public and
+ // private one. An unknown visibility, in this case, would cause the resource to be omitted
+ // from either R.java.
+ UNKNOWN = 0;
+ // A resource was explicitly marked as private. This means the resource can not be accessed
+ // outside of its package unless the @*package:type/entry notation is used (the asterisk being
+ // the private accessor). If two R.java files are generated (private + public), the resource
+ // will only be emitted to the private R.java file.
+ PRIVATE = 1;
+ // A resource was explicitly marked as public. This means the resource can be accessed
+ // from any package, and is emitted into all R.java files, public and private.
+ PUBLIC = 2;
+ }
+ Level level = 1;
+ // The path at which this entry's visibility was defined (eg. public.xml).
+ Source source = 2;
+ // The comment associated with the tag.
+ string comment = 3;
+ // Indicates that the resource id may change across builds and that the public R.java identifier
+ // for this resource should not be final. This is set to `true` for resources in `staging-group`
+ // tags.
+ bool staged_api = 4;
+}
+// Whether a resource comes from a compile-time overlay and is explicitly allowed to not overlay an
+// existing resource.
+message AllowNew {
+ // Where this was defined in source.
+ Source source = 1;
+ // Any comment associated with the declaration.
+ string comment = 2;
+}
+// Represents a set of overlayable resources.
+message Overlayable {
+ // The name of the .
+ string name = 1;
+ // The location of the declaration in the source.
+ Source source = 2;
+ // The component responsible for enabling and disabling overlays targeting this .
+ string actor = 3;
+}
+// Represents an overlayable - declaration within an tag.
+message OverlayableItem {
+ enum Policy {
+ NONE = 0;
+ PUBLIC = 1;
+ SYSTEM = 2;
+ VENDOR = 3;
+ PRODUCT = 4;
+ SIGNATURE = 5;
+ ODM = 6;
+ OEM = 7;
+ ACTOR = 8;
+ CONFIG_SIGNATURE = 9;
+ }
+ // The location of the
- declaration in source.
+ Source source = 1;
+ // Any comment associated with the declaration.
+ string comment = 2;
+ // The policy defined by the enclosing tag of this
- .
+ repeated Policy policy = 3;
+ // The index into overlayable list that points to the tag that contains
+ // this
- .
+ uint32 overlayable_idx = 4;
+}
+// The staged resource ID definition of a finalized resource.
+message StagedId {
+ Source source = 1;
+ uint32 staged_id = 2;
+}
+// An entry ID in the range [0x0000, 0xffff].
+message EntryId {
+ uint32 id = 1;
+}
+// An entry declaration. An entry has a full resource ID that is the combination of package ID,
+// type ID, and its own entry ID. An entry on its own has no value, but values are defined for
+// various configurations/variants.
+message Entry {
+ // The ID of this entry. Together with the package ID and type ID, this forms a full resource ID
+ // of the form 0xPPTTEEEE, where PP is the package ID, TT is the type ID, and EEEE is the entry
+ // ID.
+ // This may not be set if no ID was assigned.
+ EntryId entry_id = 1;
+ // The name of this entry. This corresponds to the 'entry' part of a full resource name of the
+ // form package:type/entry.
+ string name = 2;
+ // The visibility of this entry (public, private, undefined).
+ Visibility visibility = 3;
+ // Whether this resource, when originating from a compile-time overlay, is allowed to NOT overlay
+ // any existing resources.
+ AllowNew allow_new = 4;
+ // Whether this resource can be overlaid by a runtime resource overlay (RRO).
+ OverlayableItem overlayable_item = 5;
+ // The set of values defined for this entry, each corresponding to a different
+ // configuration/variant.
+ repeated ConfigValue config_value = 6;
+ // The staged resource ID of this finalized resource.
+ StagedId staged_id = 7;
+}
+// A Configuration/Value pair.
+message ConfigValue {
+ Configuration config = 1;
+ Value value = 2;
+}
+// The generic meta-data for every value in a resource table.
+message Value {
+ // Where the value was defined.
+ Source source = 1;
+ // Any comment associated with the value.
+ string comment = 2;
+ // Whether the value can be overridden.
+ bool weak = 3;
+ // The value is either an Item or a CompoundValue.
+ oneof value {
+ Item item = 4;
+ CompoundValue compound_value = 5;
+ }
+}
+// An Item is an abstract type. It represents a value that can appear inline in many places, such
+// as XML attribute values or on the right hand side of style attribute definitions. The concrete
+// type is one of the types below. Only one can be set.
+message Item {
+ oneof value {
+ Reference ref = 1;
+ String str = 2;
+ RawString raw_str = 3;
+ StyledString styled_str = 4;
+ FileReference file = 5;
+ Id id = 6;
+ Primitive prim = 7;
+ }
+}
+// A CompoundValue is an abstract type. It represents a value that is a made of other values.
+// These can only usually appear as top-level resources. The concrete type is one of the types
+// below. Only one can be set.
+message CompoundValue {
+ oneof value {
+ Attribute attr = 1;
+ Style style = 2;
+ Styleable styleable = 3;
+ Array array = 4;
+ Plural plural = 5;
+ MacroBody macro = 6;
+ }
+}
+// Message holding a boolean, so it can be optionally encoded.
+message Boolean {
+ bool value = 1;
+}
+// A value that is a reference to another resource. This reference can be by name or resource ID.
+message Reference {
+ enum Type {
+ // A plain reference (@package:type/entry).
+ REFERENCE = 0;
+ // A reference to a theme attribute (?package:type/entry).
+ ATTRIBUTE = 1;
+ }
+ Type type = 1;
+ // The resource ID (0xPPTTEEEE) of the resource being referred. This is optional.
+ uint32 id = 2;
+ // The name of the resource being referred. This is optional if the resource ID is set.
+ string name = 3;
+ // Whether this reference is referencing a private resource (@*package:type/entry).
+ bool private = 4;
+ // Whether this reference is dynamic.
+ Boolean is_dynamic = 5;
+ // The type flags used when compiling the reference. Used for substituting the contents of macros.
+ uint32 type_flags = 6;
+ // Whether raw string values would have been accepted in place of this reference definition. Used
+ // for substituting the contents of macros.
+ bool allow_raw = 7;
+}
+// A value that represents an ID. This is just a placeholder, as ID values are used to occupy a
+// resource ID (0xPPTTEEEE) as a unique identifier. Their value is unimportant.
+message Id {
+}
+// A value that is a string.
+message String {
+ string value = 1;
+}
+// A value that is a raw string, which is unescaped/uninterpreted. This is typically used to
+// represent the value of a style attribute before the attribute is compiled and the set of
+// allowed values is known.
+message RawString {
+ string value = 1;
+}
+// A string with styling information, like html tags that specify boldness, italics, etc.
+message StyledString {
+ // The raw text of the string.
+ string value = 1;
+ // A Span marks a region of the string text that is styled.
+ message Span {
+ // The name of the tag, and its attributes, encoded as follows:
+ // tag_name;attr1=value1;attr2=value2;[...]
+ string tag = 1;
+ // The first character position this span applies to, in UTF-16 offset.
+ uint32 first_char = 2;
+ // The last character position this span applies to, in UTF-16 offset.
+ uint32 last_char = 3;
+ }
+ repeated Span span = 2;
+}
+// A value that is a reference to an external entity, like an XML file or a PNG.
+message FileReference {
+ enum Type {
+ UNKNOWN = 0;
+ PNG = 1;
+ BINARY_XML = 2;
+ PROTO_XML = 3;
+ }
+ // Path to a file within the APK (typically res/type-config/entry.ext).
+ string path = 1;
+ // The type of file this path points to. For UAM bundle, this cannot be
+ // BINARY_XML.
+ Type type = 2;
+}
+// A value that represents a primitive data type (float, int, boolean, etc.).
+// Refer to Res_value in ResourceTypes.h for info on types and formatting
+message Primitive {
+ message NullType {
+ }
+ message EmptyType {
+ }
+ oneof oneof_value {
+ NullType null_value = 1;
+ EmptyType empty_value = 2;
+ float float_value = 3;
+ uint32 dimension_value = 13;
+ uint32 fraction_value = 14;
+ int32 int_decimal_value = 6;
+ uint32 int_hexadecimal_value = 7;
+ bool boolean_value = 8;
+ uint32 color_argb8_value = 9;
+ uint32 color_rgb8_value = 10;
+ uint32 color_argb4_value = 11;
+ uint32 color_rgb4_value = 12;
+ float dimension_value_deprecated = 4 [deprecated=true];
+ float fraction_value_deprecated = 5 [deprecated=true];
+ }
+}
+// A value that represents an XML attribute and what values it accepts.
+message Attribute {
+ // A Symbol used to represent an enum or a flag.
+ message Symbol {
+ // Where the enum/flag item was defined.
+ Source source = 1;
+ // Any comments associated with the enum or flag.
+ string comment = 2;
+ // The name of the enum/flag as a reference. Enums/flag items are generated as ID resource
+ // values.
+ Reference name = 3;
+ // The value of the enum/flag.
+ uint32 value = 4;
+ // The data type of the enum/flag as defined in android::Res_value.
+ uint32 type = 5;
+ }
+ // Bitmask of formats allowed for an attribute.
+ enum FormatFlags {
+ NONE = 0x0; // Proto3 requires a default of 0.
+ ANY = 0x0000ffff; // Allows any type except ENUM and FLAGS.
+ REFERENCE = 0x01; // Allows Reference values.
+ STRING = 0x02; // Allows String/StyledString values.
+ INTEGER = 0x04; // Allows any integer BinaryPrimitive values.
+ BOOLEAN = 0x08; // Allows any boolean BinaryPrimitive values.
+ COLOR = 0x010; // Allows any color BinaryPrimitive values.
+ FLOAT = 0x020; // Allows any float BinaryPrimitive values.
+ DIMENSION = 0x040; // Allows any dimension BinaryPrimitive values.
+ FRACTION = 0x080; // Allows any fraction BinaryPrimitive values.
+ ENUM = 0x00010000; // Allows enums that are defined in the Attribute's symbols.
+ // ENUM and FLAGS cannot BOTH be set.
+ FLAGS = 0x00020000; // Allows flags that are defined in the Attribute's symbols.
+ // ENUM and FLAGS cannot BOTH be set.
+ }
+ // A bitmask of types that this XML attribute accepts. Corresponds to the flags in the
+ // enum FormatFlags.
+ uint32 format_flags = 1;
+ // The smallest integer allowed for this XML attribute. Only makes sense if the format includes
+ // FormatFlags::INTEGER.
+ int32 min_int = 2;
+ // The largest integer allowed for this XML attribute. Only makes sense if the format includes
+ // FormatFlags::INTEGER.
+ int32 max_int = 3;
+ // The set of enums/flags defined in this attribute. Only makes sense if the format includes
+ // either FormatFlags::ENUM or FormatFlags::FLAGS. Having both is an error.
+ repeated Symbol symbol = 4;
+}
+// A value that represents a style.
+message Style {
+ // An XML attribute/value pair defined in the style.
+ message Entry {
+ // Where the entry was defined.
+ Source source = 1;
+ // Any comments associated with the entry.
+ string comment = 2;
+ // A reference to the XML attribute.
+ Reference key = 3;
+ // The Item defined for this XML attribute.
+ Item item = 4;
+ }
+ // The optinal style from which this style inherits attributes.
+ Reference parent = 1;
+ // The source file information of the parent inheritance declaration.
+ Source parent_source = 2;
+ // The set of XML attribute/value pairs for this style.
+ repeated Entry entry = 3;
+}
+// A value that represents a XML resource. These are not real resources and
+// only end up as Java fields in the generated R.java. They do not end up in the binary ARSC file.
+message Styleable {
+ // An attribute defined for this styleable.
+ message Entry {
+ // Where the attribute was defined within the block.
+ Source source = 1;
+ // Any comments associated with the declaration.
+ string comment = 2;
+ // The reference to the attribute.
+ Reference attr = 3;
+ }
+ // The set of attribute declarations.
+ repeated Entry entry = 1;
+}
+// A value that represents an array of resource values.
+message Array {
+ // A single element of the array.
+ message Element {
+ // Where the element was defined.
+ Source source = 1;
+ // Any comments associated with the element.
+ string comment = 2;
+ // The value assigned to this element.
+ Item item = 3;
+ }
+ // The list of array elements.
+ repeated Element element = 1;
+}
+// A value that represents a string and its many variations based on plurality.
+message Plural {
+ // The arity of the plural.
+ enum Arity {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ FEW = 3;
+ MANY = 4;
+ OTHER = 5;
+ }
+ // The plural value for a given arity.
+ message Entry {
+ // Where the plural was defined.
+ Source source = 1;
+ // Any comments associated with the plural.
+ string comment = 2;
+ // The arity of the plural.
+ Arity arity = 3;
+ // The value assigned to this plural.
+ Item item = 4;
+ }
+ // The set of arity/plural mappings.
+ repeated Entry entry = 1;
+}
+// Defines an abstract XmlNode that must be either an XmlElement, or
+// a text node represented by a string.
+message XmlNode {
+ oneof node {
+ XmlElement element = 1;
+ string text = 2;
+ }
+ // Source line and column info.
+ SourcePosition source = 3;
+}
+// An in an XML document.
+message XmlElement {
+ // Namespaces defined on this element.
+ repeated XmlNamespace namespace_declaration = 1;
+ // The namespace URI of this element.
+ string namespace_uri = 2;
+ // The name of this element.
+ string name = 3;
+ // The attributes of this element.
+ repeated XmlAttribute attribute = 4;
+ // The children of this element.
+ repeated XmlNode child = 5;
+}
+// A namespace declaration on an XmlElement (xmlns:android="http://...").
+message XmlNamespace {
+ string prefix = 1;
+ string uri = 2;
+ // Source line and column info.
+ SourcePosition source = 3;
+}
+// An attribute defined on an XmlElement (android:text="...").
+message XmlAttribute {
+ string namespace_uri = 1;
+ string name = 2;
+ string value = 3;
+ // Source line and column info.
+ SourcePosition source = 4;
+ // The optional resource ID (0xPPTTEEEE) of the attribute.
+ uint32 resource_id = 5;
+ // The optional interpreted/compiled version of the `value` string.
+ Item compiled_item = 6;
+}
+message MacroBody {
+ string raw_string = 1;
+ StyleString style_string = 2;
+ repeated UntranslatableSection untranslatable_sections = 3;
+ repeated NamespaceAlias namespace_stack = 4;
+ SourcePosition source = 5;
+}
+message NamespaceAlias {
+ string prefix = 1;
+ string package_name = 2;
+ bool is_private = 3;
+}
+message StyleString {
+ message Span {
+ string name = 1;
+ uint32 start_index = 2;
+ uint32 end_index = 3;
+ }
+ string str = 1;
+ repeated Span spans = 2;
+}
+message UntranslatableSection {
+ uint64 start_index = 1;
+ uint64 end_index = 2;
+}
\ No newline at end of file
diff --git a/subprojects/aaptcompiler/src/main/proto/com/android/aapt/ResourcesInternal.proto b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/ResourcesInternal.proto
new file mode 100644
index 000000000..e9791cbe6
--- /dev/null
+++ b/subprojects/aaptcompiler/src/main/proto/com/android/aapt/ResourcesInternal.proto
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+syntax = "proto3";
+
+import "com/android/aapt/Configuration.proto";
+import "com/android/aapt/Resources.proto";
+
+// package aapt.pb.internal;
+
+option java_package = "android.aapt.pb.internal";
+
+// The top level message representing an external resource file (layout XML, PNG, etc).
+// This is used to represent a compiled file before it is linked. Only useful to aapt2.
+message CompiledFile {
+ message Symbol {
+ // The name of the symbol (in the form package:type/name).
+ string resource_name = 1;
+ // The position in the file at which this symbol is defined. For debug use.
+ SourcePosition source = 2;
+ }
+ // The name of the resource (in the form package:type/name).
+ string resource_name = 1;
+ // The configuration for which the resource is defined.
+ Configuration config = 2;
+ // The type of the file.
+ FileReference.Type type = 3;
+ // The filesystem path to where the source file originated.
+ // Mainly used to display helpful error messages.
+ string source_path = 4;
+ // Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file).
+ repeated Symbol exported_symbol = 5;
+}
\ No newline at end of file