Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 14 Support (Partial) #3206

Merged
merged 12 commits into from
Oct 5, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ private int mapSdkShorthandToVersion(String sdkVersion) {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,6 +71,7 @@ public ResConfigFlags() {
keyboard = KEYBOARD_ANY;
navigation = NAVIGATION_ANY;
inputFlags = KEYSHIDDEN_ANY | NAVHIDDEN_ANY;
grammaticalInflection = GRAMMATICAL_GENDER_ANY;
screenWidth = 0;
screenHeight = 0;
sdkVersion = 0;
Expand All @@ -91,7 +93,7 @@ public 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,
Expand Down Expand Up @@ -149,6 +151,7 @@ public ResConfigFlags(short mcc, short mnc, char[] language,
this.keyboard = keyboard;
this.navigation = navigation;
this.inputFlags = inputFlags;
this.grammaticalInflection = grammaticalInflection;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.sdkVersion = sdkVersion;
Expand Down Expand Up @@ -198,6 +201,18 @@ private String generateQualifiers() {
}
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");
Expand Down Expand Up @@ -421,6 +436,9 @@ private String generateQualifiers() {
}

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;
}
Expand Down Expand Up @@ -550,6 +568,7 @@ public int hashCode() {
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
Expand Down Expand Up @@ -590,6 +609,11 @@ public int hashCode() {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,18 @@ private ResType readTableType() throws IOException, AndrolibException {

// 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());
Expand Down Expand Up @@ -352,7 +357,15 @@ private EntryData readEntryData() throws IOException, AndrolibException {
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) {
Expand Down Expand Up @@ -483,11 +496,12 @@ private ResConfigFlags readConfigFlags() throws IOException, AndrolibException {
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;
}

Expand Down Expand Up @@ -545,6 +559,7 @@ private ResConfigFlags readConfigFlags() throws IOException, AndrolibException {
}

int exceedingKnownSize = size - KNOWN_CONFIG_BYTES;

if (exceedingKnownSize > 0) {
byte[] buf = new byte[exceedingKnownSize];
read += exceedingKnownSize;
Expand All @@ -569,7 +584,7 @@ private ResConfigFlags readConfigFlags() throws IOException, AndrolibException {

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);
Expand Down Expand Up @@ -663,6 +678,10 @@ private void checkChunkType(int expectedType) throws AndrolibException {
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;

Expand Down