Reworks Attr/Array Handler (#3326)

* test: add example pkcs key

* fix: rework towards ResScalarValue instead of ResIntValue

* fix: prefer res name instead of "guessing" based on ids
This commit is contained in:
Connor Tumbleson 2023-09-11 19:01:09 -04:00 committed by GitHub
parent c07e4a92e6
commit 515af4faf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 49 deletions

View File

@ -23,9 +23,11 @@ import java.util.*;
public final class ResTypeSpec {
public static final String RES_TYPE_NAME_ARRAY = "array";
public static final String RES_TYPE_NAME_PLURALS = "plurals";
public static final String RES_TYPE_NAME_STYLES = "style";
public static final String RES_TYPE_NAME_ATTR = "attr";
public static final String RES_TYPE_NAME_ATTR_PRIVATE = "^attr-private";
public static final String RES_TYPE_NAME_PLURALS = "plurals";
public static final String RES_TYPE_NAME_STRING = "string";
public static final String RES_TYPE_NAME_STYLES = "style";
private final String mName;
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<>();
@ -46,7 +48,7 @@ public final class ResTypeSpec {
}
public boolean isString() {
return mName.equalsIgnoreCase("string");
return mName.equalsIgnoreCase(RES_TYPE_NAME_STRING);
}
public ResResSpec getResSpec(String name) throws AndrolibException {

View File

@ -91,6 +91,4 @@ public class ResArrayValue extends ResBagValue implements ResValuesXmlSerializab
private final ResScalarValue[] mItems;
private final String[] AllowedArrayTypes = {"string", "integer"};
public static final int BAG_KEY_ARRAY_START = 0x02000000;
}

View File

@ -64,38 +64,39 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
public static ResAttr factory(ResReferenceValue parent,
Duo<Integer, ResScalarValue>[] items, ResValueFactory factory,
ResPackage pkg) throws AndrolibException {
int type = ((ResIntValue) items[0].m2).getValue();
int scalarType = type & 0xffff;
Integer min = null, max = null;
Boolean l10n = null;
int i;
for (i = 1; i < items.length; i++) {
switch (items[i].m1) {
case BAG_KEY_ATTR_MIN:
min = ((ResIntValue) items[i].m2).getValue();
min = (items[i].m2).getRawIntValue();
continue;
case BAG_KEY_ATTR_MAX:
max = ((ResIntValue) items[i].m2).getValue();
max = (items[i].m2).getRawIntValue();
continue;
case BAG_KEY_ATTR_L10N:
l10n = ((ResIntValue) items[i].m2).getValue() != 0;
l10n = (items[i].m2).getRawIntValue() != 0;
continue;
}
break;
}
// #2806 - Make sure we handle int-based values and not just ResIntValue
int rawValue = items[0].m2.getRawIntValue();
int scalarType = rawValue & 0xffff;
if (i == items.length) {
return new ResAttr(parent, scalarType, min, max, l10n);
}
Duo<ResReferenceValue, ResIntValue>[] attrItems = new Duo[items.length - i];
Duo<ResReferenceValue, ResScalarValue>[] attrItems = new Duo[items.length - i];
int j = 0;
for (; i < items.length; i++) {
int resId = items[i].m1;
pkg.addSynthesizedRes(resId);
attrItems[j++] = new Duo<>(factory.newReference(resId, null), (ResIntValue) items[i].m2);
attrItems[j++] = new Duo<>(factory.newReference(resId, null), items[i].m2);
}
switch (type & 0xff0000) {
switch (rawValue & 0xff0000) {
case TYPE_ENUM:
return new ResEnumAttr(parent, scalarType, min, max, l10n, attrItems);
case TYPE_FLAGS:
@ -145,7 +146,6 @@ public class ResAttr extends ResBagValue implements ResValuesXmlSerializable {
private final Integer mMax;
private final Boolean mL10n;
public static final int BAG_KEY_ATTR_TYPE = 0x01000000;
private static final int BAG_KEY_ATTR_MIN = 0x01000001;
private static final int BAG_KEY_ATTR_MAX = 0x01000002;
private static final int BAG_KEY_ATTR_L10N = 0x01000003;

View File

@ -29,7 +29,7 @@ import java.util.logging.Logger;
public class ResEnumAttr extends ResAttr {
ResEnumAttr(ResReferenceValue parent, int type, Integer min, Integer max,
Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
Boolean l10n, Duo<ResReferenceValue, ResScalarValue>[] items) {
super(parent, type, min, max, l10n);
mItems = items;
}
@ -48,8 +48,8 @@ public class ResEnumAttr extends ResAttr {
@Override
protected void serializeBody(XmlSerializer serializer, ResResource res) throws AndrolibException, IOException {
for (Duo<ResReferenceValue, ResIntValue> duo : mItems) {
int intVal = duo.m2.getValue();
for (Duo<ResReferenceValue, ResScalarValue> duo : mItems) {
int intVal = duo.m2.getRawIntValue();
// #2836 - Support skipping items if the resource cannot be identified.
ResResSpec m1Referent = duo.m1.getReferent();
@ -72,8 +72,8 @@ public class ResEnumAttr extends ResAttr {
String value2 = mItemsCache.get(value);
if (value2 == null) {
ResReferenceValue ref = null;
for (Duo<ResReferenceValue, ResIntValue> duo : mItems) {
if (duo.m2.getValue() == value) {
for (Duo<ResReferenceValue, ResScalarValue> duo : mItems) {
if (duo.m2.getRawIntValue() == value) {
ref = duo.m1;
break;
}
@ -86,7 +86,7 @@ public class ResEnumAttr extends ResAttr {
return value2;
}
private final Duo<ResReferenceValue, ResIntValue>[] mItems;
private final Duo<ResReferenceValue, ResScalarValue>[] mItems;
private final Map<Integer, String> mItemsCache = new HashMap<>();
private static final Logger LOGGER = Logger.getLogger(ResEnumAttr.class.getName());

View File

@ -29,12 +29,12 @@ import java.util.logging.Logger;
public class ResFlagsAttr extends ResAttr {
ResFlagsAttr(ResReferenceValue parent, int type, Integer min, Integer max,
Boolean l10n, Duo<ResReferenceValue, ResIntValue>[] items) {
Boolean l10n, Duo<ResReferenceValue, ResScalarValue>[] items) {
super(parent, type, min, max, l10n);
mItems = new FlagItem[items.length];
for (int i = 0; i < items.length; i++) {
mItems[i] = new FlagItem(items[i].m1, items[i].m2.getValue());
mItems[i] = new FlagItem(items[i].m1, items[i].m2.getRawIntValue());
}
}

View File

@ -59,6 +59,5 @@ public class ResPluralsValue extends ResBagValue implements
private final ResScalarValue[] mItems;
public static final int BAG_KEY_PLURALS_START = 0x01000004;
public static final int BAG_KEY_PLURALS_END = 0x01000009;
private static final String[] QUANTITY_MAP = new String[] { "other", "zero", "one", "two", "few", "many" };
}

View File

@ -80,40 +80,30 @@ public class ResValueFactory {
return new ResStringValue(value, rawValue);
}
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec)
throws AndrolibException {
ResReferenceValue parentVal = newReference(parent, null);
if (items.length == 0) {
return new ResBagValue(parentVal);
}
int key = items[0].m1;
if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
return ResAttr.factory(parentVal, items, this, mPackage);
}
String resTypeName = resTypeSpec.getName();
// Android O Preview added an unknown enum for c. This is hardcoded as 0 for now.
if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName)
|| key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
switch (resTypeName) {
case ResTypeSpec.RES_TYPE_NAME_ATTR:
case ResTypeSpec.RES_TYPE_NAME_ATTR_PRIVATE:
return ResAttr.factory(parentVal, items, this, mPackage);
case ResTypeSpec.RES_TYPE_NAME_ARRAY:
return new ResArrayValue(parentVal, items);
}
if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
(key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
case ResTypeSpec.RES_TYPE_NAME_PLURALS:
return new ResPluralsValue(parentVal, items);
}
if (ResTypeSpec.RES_TYPE_NAME_ATTR.equals(resTypeName)) {
return new ResAttr(parentVal, 0, null, null, null);
}
default:
if (resTypeName.startsWith(ResTypeSpec.RES_TYPE_NAME_STYLES)) {
return new ResStyleValue(parentVal, items, this);
}
throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
}
}
public ResReferenceValue newReference(int resID, String rawValue) {
return newReference(resID, rawValue, false);

View File

@ -35,4 +35,7 @@
<item>res/</item>
<item>view/</item>
</string-array>
<string-array name="issue_2806">
<item>MIICXAIBAAKBgQCjcGqTkOq0CR3rTx0ZSQSIdTrDrFAYl29611xN8aVgMQIWtDB/lD0W5TpKPuU9iaiG/sSn/VYt6EzN7Sr332jj7cyl2WrrHI6ujRswNy4HojMuqtfab5FFDpRmCuvl35fge18OvoQTJELhhJ1EvJ5KUeZiuJ3u3YyMnxxXzLuKbQIDAQABAoGAPrNDz7TKtaLBvaIuMaMXgBopHyQd3jFKbT/tg2Fu5kYm3PrnmCoQfZYXFKCoZUFIS/G1FBVWWGpD/MQ9tbYZkKpwuH+t2rGndMnLXiTC296/s9uix7gsjnT4Naci5N6EN9pVUBwQmGrYUTHFc58ThtelSiPARX7LSU2ibtJSv8ECQQDWBRrrAYmbCUN7ra0DFT6SppaDtvvuKtb+mUeKbg0B8U4y4wCIK5GH8EyQSwUWcXnNBO05rlUPbifsDLv/u82lAkEAw39sTJ0KmJJyaChqvqAJ8guulKlgucQJ0Et9ppZyet9iVwNKX/aW9UlwGBMQdafQ36nd1QMEA8AbAw4D+hw/KQJBANJbHDUGQtk2hrSmZNoV5HXB9Uiq7v4N71k5ER8XwgM5yVGs2tX8dMM3RhnBEtQXXs9LW1uJZSOQcv7JGXNnhN0CQBZenzrJAWxh3XtznHtBfsHWelyCYRIAj4rpCHCmaGUM6IjCVKFUawOYKp5mmAyObkUZf8ue87emJLEdynC1CLkCQHduNjP1hemAGWrd6v8BHhE3kKtcK6KHsPvJR5dOfzbdHAqVePERhISfN6cwZt5p8B3/JUwSR8el66DF7Jm57BM=</item>
</string-array>
</resources>