Handle BCP additional fields (script & variant)

layoutDirection was being read in error. layoutDirection is read
via bit shifting over screenLayout (byte 32, 33)

The then removed layoutDirection freed up 2 bytes. This gave us
12 bytes of unknown space from byte 36 to 48. This corresponded
to localeScript[4] and localeVariant[8]

Adding proper support for those bytes fixed BCP support
This commit is contained in:
Connor Tumbleson 2015-02-19 09:05:00 -06:00
parent af65dea319
commit d40710005f

View File

@ -291,9 +291,11 @@ public class ARSCDecoder {
screenHeightDp = mIn.readShort(); screenHeightDp = mIn.readShort();
} }
short layoutDirection = 0; char[] localeScript = {'\00'};
if (size >= 38) { char[] localeVariant = {'\00'};
layoutDirection = mIn.readShort(); if (size >= 48) {
localeScript = this.readScriptOrVariantChar(4).toCharArray();
localeVariant = this.readScriptOrVariantChar(8).toCharArray();
} }
int exceedingSize = size - KNOWN_CONFIG_BYTES; int exceedingSize = size - KNOWN_CONFIG_BYTES;
@ -313,29 +315,40 @@ public class ARSCDecoder {
} }
} }
return new ResConfigFlags(mcc, mnc, language, country, layoutDirection, return new ResConfigFlags(mcc, mnc, language, country,
orientation, touchscreen, density, keyboard, navigation, orientation, touchscreen, density, keyboard, navigation,
inputFlags, screenWidth, screenHeight, sdkVersion, inputFlags, screenWidth, screenHeight, sdkVersion,
screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp, screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
screenHeightDp, isInvalid); screenHeightDp, localeScript, localeVariant, isInvalid);
} }
private char[] unpackLanguageOrRegion(byte in0, byte in1, char base) throws AndrolibException { private char[] unpackLanguageOrRegion(byte in0, byte in1, char base) throws AndrolibException {
if (in0 == 0 && in1 == 0) { // check high bit, if so we have a packed 3 letter code
return new char[] {(char) in0, (char) in1}; if (((in0 >> 7) & 1) == 1) {
} else { int first = in1 & 0x1F;
// check high bit, if so we have a packed 3 letter code int second = ((in1 & 0xE0) >> 5) + ((in0 & 0x03) << 3);
if (((in0 >> 7) & 1) == 1) { int third = (in0 & 0x7C) >> 2;
int first = in1 & 0x1F;
int second = ((in1 & 0xE0) >> 5) + ((in0 & 0x03) << 3);
int third = (in0 & 0x7C) >> 2;
// since this function handles languages & regions, we add the value(s) to the base char // since this function handles languages & regions, we add the value(s) to the base char
// which is usually 'a' or '0' depending on language or region. // which is usually 'a' or '0' depending on language or region.
return new char[] { (char) (first + base), (char) (second + base), (char) (third + base) }; return new char[] { (char) (first + base), (char) (second + base), (char) (third + base) };
}
return new char[] { (char) in0, (char) in1 };
} }
return new char[] { (char) in0, (char) in1 };
}
private String readScriptOrVariantChar(int length) throws AndrolibException, IOException {
StringBuilder string = new StringBuilder(16);
while(length-- != 0) {
short ch = mIn.readByte();
if (ch == 0) {
break;
}
string.append((char) ch);
}
mIn.skipBytes(length);
return string.toString();
} }
private void addMissingResSpecs() throws AndrolibException { private void addMissingResSpecs() throws AndrolibException {
@ -434,7 +447,7 @@ public class ARSCDecoder {
} }
private static final Logger LOGGER = Logger.getLogger(ARSCDecoder.class.getName()); private static final Logger LOGGER = Logger.getLogger(ARSCDecoder.class.getName());
private static final int KNOWN_CONFIG_BYTES = 38; private static final int KNOWN_CONFIG_BYTES = 48;
public static class ARSCData { public static class ARSCData {