Android 14 Support (Partial) (#3206)

* fix: prevent over-reading config flags

* feat: add grammatical inflection

* fix: add natural requirement for U

* fix: UpsideDownCake is now 34

* test: test for grammatical inflection

* fix: add detection for compact resources

* fix: add detection for offset16 table types

* Revert "test: test for grammatical inflection"

This reverts commit fa08cef9fe6d436176f74152d85a652a771971ad.

* refactor: use enum instead of magic numbers
This commit is contained in:
Connor Tumbleson 2023-10-04 20:13:58 -04:00 committed by GitHub
parent 91a5863f16
commit bc7394080d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 6 deletions

View File

@ -191,6 +191,7 @@ public class ApkInfo implements YamlSerializable {
return ResConfigFlags.SDK_TIRAMISU;
case "UPSIDEDOWNCAKE":
case "UPSIDE_DOWN_CAKE":
return ResConfigFlags.SDK_UPSIDEDOWN_CAKE;
case "VANILLAICECREAM":
case "VANILLA_ICE_CREAM":
return ResConfigFlags.SDK_DEVELOPMENT;

View File

@ -32,6 +32,7 @@ public class ResConfigFlags {
public final byte keyboard;
public final byte navigation;
public final byte inputFlags;
public final byte grammaticalInflection;
public final short screenWidth;
public final short screenHeight;
@ -70,6 +71,7 @@ public class ResConfigFlags {
keyboard = KEYBOARD_ANY;
navigation = NAVIGATION_ANY;
inputFlags = KEYSHIDDEN_ANY | NAVHIDDEN_ANY;
grammaticalInflection = GRAMMATICAL_GENDER_ANY;
screenWidth = 0;
screenHeight = 0;
sdkVersion = 0;
@ -91,7 +93,7 @@ public class ResConfigFlags {
public ResConfigFlags(short mcc, short mnc, char[] language,
char[] region, byte orientation,
byte touchscreen, int density, byte keyboard, byte navigation,
byte inputFlags, short screenWidth, short screenHeight,
byte inputFlags, byte grammaticalInflection, short screenWidth, short screenHeight,
short sdkVersion, byte screenLayout, byte uiMode,
short smallestScreenWidthDp, short screenWidthDp,
short screenHeightDp, char[] localeScript, char[] localeVariant,
@ -149,6 +151,7 @@ public class ResConfigFlags {
this.keyboard = keyboard;
this.navigation = navigation;
this.inputFlags = inputFlags;
this.grammaticalInflection = grammaticalInflection;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.sdkVersion = sdkVersion;
@ -198,6 +201,18 @@ public class ResConfigFlags {
}
ret.append(getLocaleString());
switch (grammaticalInflection) {
case GRAMMATICAL_GENDER_NEUTER:
ret.append("-neuter");
break;
case GRAMMATICAL_GENDER_FEMININE:
ret.append("-feminine");
break;
case GRAMMATICAL_GENDER_MASCULINE:
ret.append("-masculine");
break;
}
switch (screenLayout & MASK_LAYOUTDIR) {
case SCREENLAYOUT_LAYOUTDIR_RTL:
ret.append("-ldrtl");
@ -421,6 +436,9 @@ public class ResConfigFlags {
}
private short getNaturalSdkVersionRequirement() {
if (grammaticalInflection != 0) {
return SDK_UPSIDEDOWN_CAKE;
}
if ((uiMode & MASK_UI_MODE_TYPE) == UI_MODE_TYPE_VR_HEADSET || (colorMode & COLOR_WIDE_MASK) != 0 || ((colorMode & COLOR_HDR_MASK) != 0)) {
return SDK_OREO;
}
@ -550,6 +568,7 @@ public class ResConfigFlags {
public final static byte SDK_S = 31;
public final static byte SDK_S_V2 = 32;
public final static byte SDK_TIRAMISU = 33;
public final static byte SDK_UPSIDEDOWN_CAKE = 34;
// AOSP has this as 10,000 for dev purposes.
// platform_frameworks_base/commit/c7a1109a1fe0771d4c9b572dcf178e2779fc4f2d
@ -590,6 +609,11 @@ public class ResConfigFlags {
public final static short SCREENLAYOUT_ROUND_NO = 0x1;
public final static short SCREENLAYOUT_ROUND_YES = 0x2;
public final static byte GRAMMATICAL_GENDER_ANY = 0;
public final static byte GRAMMATICAL_GENDER_NEUTER = 1;
public final static byte GRAMMATICAL_GENDER_FEMININE = 2;
public final static byte GRAMMATICAL_GENDER_MASCULINE = 3;
public final static byte KEYBOARD_ANY = 0;
public final static byte KEYBOARD_NOKEYS = 1;
public final static byte KEYBOARD_QWERTY = 2;

View File

@ -282,13 +282,18 @@ public class ARSCDecoder {
// Be sure we don't poison mResTable by marking the application as sparse
// Only flag the ResTable as sparse if the main package is not loaded.
if ((typeFlags & 0x01) != 0 && !mResTable.isMainPkgLoaded()) {
if ((typeFlags & TABLE_TYPE_FLAG_SPARSE) != 0 && !mResTable.isMainPkgLoaded()) {
mResTable.setSparseResources(true);
}
if ((typeFlags & TABLE_TYPE_FLAG_OFFSET16) != 0) {
LOGGER.warning("Please report this application to Apktool for a fix: https://github.com/iBotPeaches/Apktool/issues/3367");
throw new AndrolibException("Unexpected TYPE_FLAG_OFFSET16");
}
HashMap<Integer, Integer> entryOffsetMap = new LinkedHashMap<>();
for (int i = 0; i < entryCount; i++) {
if ((typeFlags & 0x01) != 0) {
if ((typeFlags & TABLE_TYPE_FLAG_SPARSE) != 0) {
entryOffsetMap.put(mIn.readUnsignedShort(), mIn.readUnsignedShort());
} else {
entryOffsetMap.put(i, mIn.readInt());
@ -352,7 +357,15 @@ public class ARSCDecoder {
return null;
}
ResValue value = (flags & ENTRY_FLAG_COMPLEX) == 0 ? readValue() : readComplexEntry();
boolean isComplex = (flags & ENTRY_FLAG_COMPLEX) != 0;
boolean isCompact = (flags & ENTRY_FLAG_COMPACT) != 0;
if (isCompact) {
LOGGER.warning("Please report this application to Apktool for a fix: https://github.com/iBotPeaches/Apktool/issues/3366");
throw new AndrolibException("Unexpected entry type: compact");
}
ResValue value = isComplex ? readComplexEntry() : readValue();
// #2824 - In some applications the res entries are duplicated with the 2nd being malformed.
// AOSP skips this, so we will do the same.
if (value == null) {
@ -483,11 +496,12 @@ public class ARSCDecoder {
byte keyboard = 0;
byte navigation = 0;
byte inputFlags = 0;
byte grammaticalInflection = 0;
if (size >= 20) {
keyboard = mIn.readByte();
navigation = mIn.readByte();
inputFlags = mIn.readByte();
mIn.skipBytes(1); // inputPad0
grammaticalInflection = mIn.readByte();
read = 20;
}
@ -545,6 +559,7 @@ public class ARSCDecoder {
}
int exceedingKnownSize = size - KNOWN_CONFIG_BYTES;
if (exceedingKnownSize > 0) {
byte[] buf = new byte[exceedingKnownSize];
read += exceedingKnownSize;
@ -569,7 +584,7 @@ public class ARSCDecoder {
return new ResConfigFlags(mcc, mnc, language, country,
orientation, touchscreen, density, keyboard, navigation,
inputFlags, screenWidth, screenHeight, sdkVersion,
inputFlags, grammaticalInflection, screenWidth, screenHeight, sdkVersion,
screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
screenHeightDp, localeScript, localeVariant, screenLayout2,
colorMode, localeNumberingSystem, isInvalid, size);
@ -663,6 +678,10 @@ public class ARSCDecoder {
private final static short ENTRY_FLAG_COMPLEX = 0x0001;
private final static short ENTRY_FLAG_PUBLIC = 0x0002;
private final static short ENTRY_FLAG_WEAK = 0x0004;
private final static short ENTRY_FLAG_COMPACT = 0x0008;
private final static short TABLE_TYPE_FLAG_SPARSE = 0x01;
private final static short TABLE_TYPE_FLAG_OFFSET16 = 0x02;
private static final int KNOWN_CONFIG_BYTES = 64;