fix: use the res type spec name to create res bag value

Starting with the version 28.0.3 of the Android SDK build tools,
the internal ids of the items of an array bag seems to have changed.

Because of those changes, array resources were no longer decoded correctly.
They were decoded as style resources.

Instead of using the id of the first item within a resource bag,
the name of the res type spec is now used to choose the correct
resource bag value to create.

Note: a list of "legal names" for resource types  can be found in the source code of aapt2.
This commit is contained in:
Vincent Barthelemy 2019-01-29 09:12:35 +01:00
parent 72368fc0d4
commit 13e356f2ef
3 changed files with 23 additions and 6 deletions

View File

@ -24,6 +24,11 @@ import java.util.*;
* @author Ryszard Wiśniewski <brut.alll@gmail.com> * @author Ryszard Wiśniewski <brut.alll@gmail.com>
*/ */
public final class ResTypeSpec { 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";
private final String mName; private final String mName;
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>(); private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();

View File

@ -19,6 +19,7 @@ package brut.androlib.res.data.value;
import android.util.TypedValue; import android.util.TypedValue;
import brut.androlib.AndrolibException; import brut.androlib.AndrolibException;
import brut.androlib.res.data.ResPackage; import brut.androlib.res.data.ResPackage;
import brut.androlib.res.data.ResTypeSpec;
import brut.util.Duo; import brut.util.Duo;
/** /**
@ -83,7 +84,7 @@ public class ResValueFactory {
return new ResStringValue(value, rawValue); return new ResStringValue(value, rawValue);
} }
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items) throws AndrolibException { public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
ResReferenceValue parentVal = newReference(parent, null); ResReferenceValue parentVal = newReference(parent, null);
if (items.length == 0) { if (items.length == 0) {
@ -93,14 +94,25 @@ public class ResValueFactory {
if (key == ResAttr.BAG_KEY_ATTR_TYPE) { if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
return ResAttr.factory(parentVal, items, this, mPackage); return ResAttr.factory(parentVal, items, this, mPackage);
} }
// Android O Preview added an unknown enum for ResTable_map. This is hardcoded as 0 for now.
if (key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) { 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) {
return new ResArrayValue(parentVal, items); return new ResArrayValue(parentVal, items);
} }
if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) {
if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
(key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
return new ResPluralsValue(parentVal, items); return new ResPluralsValue(parentVal, items);
} }
return new ResStyleValue(parentVal, items, this);
if (ResTypeSpec.RES_TYPE_NAME_STYLES.equals(resTypeName)) {
return new ResStyleValue(parentVal, items, this);
}
throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
} }
public ResReferenceValue newReference(int resID, String rawValue) { public ResReferenceValue newReference(int resID, String rawValue) {

View File

@ -347,7 +347,7 @@ public class ARSCDecoder {
} }
} }
return factory.bagFactory(parent, items); return factory.bagFactory(parent, items, mTypeSpec);
} }
private ResIntBasedValue readValue() throws IOException, AndrolibException { private ResIntBasedValue readValue() throws IOException, AndrolibException {