From 13e356f2efd635e27fe807022c41e6ee77694de8 Mon Sep 17 00:00:00 2001 From: Vincent Barthelemy Date: Tue, 29 Jan 2019 09:12:35 +0100 Subject: [PATCH] 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. --- .../brut/androlib/res/data/ResTypeSpec.java | 5 +++++ .../res/data/value/ResValueFactory.java | 22 ++++++++++++++----- .../androlib/res/decoder/ARSCDecoder.java | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java index 0c2de96d..df07f7c8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResTypeSpec.java @@ -24,6 +24,11 @@ import java.util.*; * @author Ryszard Wiśniewski */ 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 Map mResSpecs = new LinkedHashMap(); diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java index ee21befd..fae59dbc 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/value/ResValueFactory.java @@ -19,6 +19,7 @@ package brut.androlib.res.data.value; import android.util.TypedValue; import brut.androlib.AndrolibException; import brut.androlib.res.data.ResPackage; +import brut.androlib.res.data.ResTypeSpec; import brut.util.Duo; /** @@ -83,7 +84,7 @@ public class ResValueFactory { return new ResStringValue(value, rawValue); } - public ResBagValue bagFactory(int parent, Duo[] items) throws AndrolibException { + public ResBagValue bagFactory(int parent, Duo[] items, ResTypeSpec resTypeSpec) throws AndrolibException { ResReferenceValue parentVal = newReference(parent, null); if (items.length == 0) { @@ -93,14 +94,25 @@ public class ResValueFactory { if (key == ResAttr.BAG_KEY_ATTR_TYPE) { 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); } - 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 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) { diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java index 290a6615..86efecff 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ARSCDecoder.java @@ -347,7 +347,7 @@ public class ARSCDecoder { } } - return factory.bagFactory(parent, items); + return factory.bagFactory(parent, items, mTypeSpec); } private ResIntBasedValue readValue() throws IOException, AndrolibException {