diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java index 88cded092d..f967f54ec8 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResResSpec.java @@ -18,6 +18,7 @@ import brut.androlib.AndrolibException; import brut.androlib.err.UndefinedResObjectException; +import brut.androlib.res.decoder.ARSCDecoder; import org.apache.commons.lang3.StringUtils; import java.util.LinkedHashMap; @@ -28,11 +29,13 @@ public class ResResSpec { private final ResID mId; private final String mName; + private final int mFlags; private final ResPackage mPackage; private final ResTypeSpec mType; private final Map mResources = new LinkedHashMap<>(); - public ResResSpec(ResID id, String name, ResPackage pkg, ResTypeSpec type) { + public ResResSpec(ResID id, String name, int flags, ResPackage pkg, ResTypeSpec type) { + this.mFlags = flags; this.mId = id; String cleanName; @@ -72,13 +75,19 @@ public boolean hasDefaultResource() { return mResources.containsKey(new ResConfigFlags()); } + public boolean isPublicResource() { + return (getFlags() & ARSCDecoder.ENTRY_FLAG_PUBLIC) != 0; + } + public String getFullName(ResPackage relativeToPackage, boolean excludeType) { return getFullName(getPackage().equals(relativeToPackage), excludeType); } public String getFullName(boolean excludePackage, boolean excludeType) { - return (excludePackage ? "" : getPackage().getName() + ":") - + (excludeType ? "" : getType().getName() + "/") + getName(); + String privateSuffix = isPublicResource() ? "" : "*"; + String packageName = excludePackage ? "" : getPackage().getName() + ":"; + return (packageName.isEmpty() ? "" : privateSuffix + packageName) + + (excludeType ? "" : getType().getName() + "/") + getName(); } public ResID getId() { @@ -97,6 +106,10 @@ public ResTypeSpec getType() { return mType; } + public int getFlags() { + return mFlags; + } + public boolean isDummyResSpec() { return getName().startsWith("APKTOOL_DUMMY_"); } 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 e865a0b268..6360a053bd 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 @@ -309,12 +309,12 @@ private void readEntry(EntryData entryData) throws AndrolibException { if (spec.isDummyResSpec()) { removeResSpec(spec); - spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mTypeSpec); + spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), entryData.mFlags, mPkg, mTypeSpec); mPkg.addResSpec(spec); mTypeSpec.addResSpec(spec); } } else { - spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), mPkg, mTypeSpec); + spec = new ResResSpec(resId, mSpecNames.getString(specNamesId), entryData.mFlags, mPkg, mTypeSpec); mPkg.addResSpec(spec); mTypeSpec.addResSpec(spec); } @@ -511,7 +511,7 @@ private void addMissingResSpecs() throws AndrolibException { continue; } - ResResSpec spec = new ResResSpec(new ResID(resId | i), "APKTOOL_DUMMY_" + Integer.toHexString(i), mPkg, mTypeSpec); + ResResSpec spec = new ResResSpec(new ResID(resId | i), "APKTOOL_DUMMY_" + Integer.toHexString(i), ENTRY_FLAG_PUBLIC, mPkg, mTypeSpec); // If we already have this resID dont add it again. if (! mPkg.hasResSpec(new ResID(resId | i))) { @@ -575,7 +575,7 @@ private void nextChunkCheckType(int expectedType) throws IOException, AndrolibEx private final HashMap mResTypeSpecs = new HashMap<>(); private final static short ENTRY_FLAG_COMPLEX = 0x0001; - private final static short ENTRY_FLAG_PUBLIC = 0x0002; + public final static short ENTRY_FLAG_PUBLIC = 0x0002; private final static short ENTRY_FLAG_WEAK = 0x0004; public static class Header { diff --git a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java index f94462dfe3..214c6f97f2 100644 --- a/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java +++ b/brut.apktool/apktool-lib/src/test/java/brut/androlib/aapt2/BuildAndDecodeTest.java @@ -72,6 +72,16 @@ public void valuesStringsTest() throws BrutException { compareValuesFiles("values/strings.xml"); } + @Test + public void valuesColorsTest() throws BrutException { + compareValuesFiles("values/colors.xml"); + } + + @Test + public void valuesBoolsTest() throws BrutException { + compareValuesFiles("values/bools.xml"); + } + @Test public void valuesMaxLengthTest() throws BrutException { compareValuesFiles("values-es/strings.xml"); diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/bools.xml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/bools.xml new file mode 100644 index 0000000000..b36f3954aa --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/bools.xml @@ -0,0 +1,4 @@ + + + @*android:bool/config_enableActivityRecognitionHardwareOverlay + diff --git a/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/colors.xml b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/colors.xml new file mode 100644 index 0000000000..eb11a5b2b3 --- /dev/null +++ b/brut.apktool/apktool-lib/src/test/resources/aapt2/testapp/res/values/colors.xml @@ -0,0 +1,4 @@ + + + @*android:color/Indigo_700 +