/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.reandroid.arsc.value; import com.reandroid.arsc.base.Block; import com.reandroid.arsc.container.FixedBlockContainer; import com.reandroid.arsc.io.BlockLoad; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.ByteArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; import java.io.IOException; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONConvert, Comparable { private final IntegerItem configSize; private final ByteArray mValuesContainer; private String mQualifiers; private int mQualifiersStamp; public ResConfig(){ super(2); this.configSize = new IntegerItem(SIZE_64); this.mValuesContainer = new ByteArray(SIZE_64 - 4); addChild(0, configSize); addChild(1, mValuesContainer); this.configSize.setBlockLoad(this); this.mQualifiersStamp = 0; } public boolean isEqualOrMoreSpecificThan(ResConfig resConfig){ if(resConfig == null){ return false; } if(resConfig == this || resConfig.isDefault()){ return true; } byte[] bytes = ByteArray.trimTrailZeros(this.mValuesContainer.getBytes()); byte[] otherBytes = ByteArray.trimTrailZeros(resConfig.mValuesContainer.getBytes()); int max = otherBytes.length; if(max > bytes.length){ return false; } for(int i=0; i> 5) + ((in0 & 0x03) << 3)); byte third = (byte) ((in0 & 0x7c) >> 2); out[0] = (char) (first + base); out[1] = (char) (second + base); out[2] = (char) (third + base); }else if (in0 != 0) { out = new char[2]; out[0] = (char) in0; out[1] = (char) in1; }else { out = new char[2]; } return out; } private static byte[] packLanguage(char[] language) { return packLanguageOrRegion(language, 'a'); } private static byte[] packRegion(char[] region) { return packLanguageOrRegion(region, '0'); } private static byte[] packLanguageOrRegion(char[] in, char base) { byte[] out = new byte[2]; if(in==null || in.length<2){ return out; } if (in.length==2 || in[2] == 0 || in[2] == '-') { out[0] = (byte) in[0]; out[1] = (byte) in[1]; } else { byte first = (byte) ((in[0] - base) & 0x007f); byte second = (byte) ((in[1] - base) & 0x007f); byte third = (byte) ((in[2] - base) & 0x007f); out[0] = (byte) (0x80 | (third << 2) | (second >> 3)); out[1] = (byte) ((second << 5) | first); } return out; } private static byte[] toByteArray(char[] chs, int len){ byte[] bts=new byte[len]; if(chs==null){ return bts; } int sz=chs.length; for(int i=0; i= min){ return str; } StringBuilder builder = new StringBuilder(); builder.append(str); int remain = min - length; for(int i=0; i0 && str.charAt(index) == postfix){ str = str.substring(0, index); length = str.length(); index = length - 1; } return str; } public static boolean isValidSize(int size){ switch (size){ case SIZE_16: case SIZE_28: case SIZE_32: case SIZE_36: case SIZE_48: case SIZE_52: case SIZE_56: case SIZE_64: return true; default: return size > SIZE_64; } } public static final class Orientation extends Flag{ public static final int MASK = 0x0f; public static final Orientation PORT = new Orientation("port", 0x01); public static final Orientation LAND = new Orientation("land", 0x02); public static final Orientation SQUARE = new Orientation("square", 0x03); public static final Orientation[] VALUES = new Orientation[]{ PORT, LAND, SQUARE }; private Orientation(String name, int flag) { super(name, flag); } public static Orientation valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static Orientation valueOf(String name){ return Flag.valueOf(VALUES, name); } public static Orientation fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static Orientation fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(Orientation flag, int value){ return Flag.update(MASK, flag, value); } } public static final class Touchscreen extends Flag{ public static final int MASK = 0x0f; public static final Touchscreen NOTOUCH = new Touchscreen("notouch", 0x01); public static final Touchscreen STYLUS = new Touchscreen("stylus", 0x02); public static final Touchscreen FINGER = new Touchscreen("finger", 0x03); public static final Touchscreen[] VALUES = new Touchscreen[]{ NOTOUCH, STYLUS, FINGER }; private Touchscreen(String name, int flag) { super(name, flag); } public static Touchscreen valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static Touchscreen valueOf(String name){ return Flag.valueOf(VALUES, name); } public static Touchscreen fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static Touchscreen fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(Touchscreen flag, int value){ return Flag.update(MASK, flag, value); } } public static final class Density extends Flag{ public static final int MASK = 0xffff; public static final Density LDPI = new Density("ldpi", 120); public static final Density MDPI = new Density("mdpi", 160); public static final Density TVDPI = new Density("tvdpi", 213); public static final Density HDPI = new Density("hdpi", 240); public static final Density XHDPI = new Density("xhdpi", 320); public static final Density XXHDPI = new Density("xxhdpi", 480); public static final Density XXXHDPI = new Density("xxxhdpi", 640); public static final Density ANYDPI = new Density("anydpi", 0xfffe); public static final Density NODPI = new Density("nodpi", 0xffff); public static final Density[] VALUES = new Density[]{LDPI, MDPI, TVDPI, HDPI, XHDPI, XXHDPI, XXXHDPI, ANYDPI, NODPI }; private Density(String name, int flag) { super(name, flag); } public static Density valueOf(int flag){ if(flag==0){ return null; } Density density = Flag.valueOf(VALUES, MASK, flag); if(density == null){ flag = flag & MASK; density = new Density(flag+"dpi", flag); } return density; } public static Density valueOf(String name){ if(name == null || name.length() < 4){ return null; } name = name.toLowerCase(); if(name.charAt(0)=='-'){ name = name.substring(1); } Density density = Flag.valueOf(VALUES, name); if(density == null && name.endsWith("dpi")){ name = name.substring(0, name.length()-3); try{ int flag = Integer.parseInt(name); density = new Density(flag+"dpi", flag); }catch (NumberFormatException ignored){ } } return density; } public static Density fromQualifiers(String qualifiers){ return fromQualifiers(qualifiers.split("\\s*-\\s*")); } public static Density fromQualifiers(String[] qualifiers){ if(qualifiers==null){ return null; } for(int i=0; i < qualifiers.length;i++){ Density density = valueOf(qualifiers[i]); if(density==null){ continue; } qualifiers[i] = null; return density; } return null; } public static int update(Density flag, int value){ return Flag.update(MASK, flag, value); } } public static final class Keyboard extends Flag{ public static final int MASK = 0x0f; public static final Keyboard NOKEYS = new Keyboard("nokeys", 0x01); public static final Keyboard QWERTY = new Keyboard("qwerty", 0x02); public static final Keyboard KEY12 = new Keyboard("12key", 0x03); public static final Keyboard[] VALUES = new Keyboard[]{ NOKEYS, QWERTY, KEY12 }; private Keyboard(String name, int flag) { super(name, flag); } public static Keyboard valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static Keyboard valueOf(String name){ return Flag.valueOf(VALUES, name); } public static Keyboard fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static Keyboard fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(Keyboard flag, int value){ return Flag.update(MASK, flag, value); } } public static final class Navigation extends Flag{ public static final int MASK = 0x0f; public static final Navigation NONAV = new Navigation("nonav", 0x01); public static final Navigation DPAD = new Navigation("dpad", 0x02); public static final Navigation TRACKBALL = new Navigation("trackball", 0x03); public static final Navigation WHEEL = new Navigation("wheel", 0x04); public static final Navigation[] VALUES = new Navigation[]{ NONAV, DPAD, TRACKBALL, WHEEL }; private Navigation(String name, int flag) { super(name, flag); } public static Navigation valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static Navigation valueOf(String name){ return Flag.valueOf(VALUES, name); } public static Navigation fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static Navigation fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(Navigation flag, int value){ return Flag.update(MASK, flag, value); } } public static final class InputFlagsKeysHidden extends Flag{ public static final int MASK = 0x03; public static final InputFlagsKeysHidden KEYSEXPOSED = new InputFlagsKeysHidden("keysexposed", 0x01); public static final InputFlagsKeysHidden KEYSHIDDEN = new InputFlagsKeysHidden("keyshidden", 0x02); public static final InputFlagsKeysHidden KEYSSOFT = new InputFlagsKeysHidden("keyssoft", 0x03); public static final InputFlagsKeysHidden[] VALUES = new InputFlagsKeysHidden[]{ KEYSEXPOSED, KEYSHIDDEN, KEYSSOFT }; private InputFlagsKeysHidden(String name, int flag) { super(name, flag); } public static InputFlagsKeysHidden valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static InputFlagsKeysHidden valueOf(String name){ return Flag.valueOf(VALUES, name); } public static InputFlagsKeysHidden fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static InputFlagsKeysHidden fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(InputFlagsKeysHidden flag, int value){ return Flag.update(MASK, flag, value); } } public static final class InputFlagsNavHidden extends Flag{ public static final int MASK = 0x0C; public static final InputFlagsNavHidden NAVEXPOSED = new InputFlagsNavHidden("navexposed", 0x04); public static final InputFlagsNavHidden NAVHIDDEN = new InputFlagsNavHidden("navhidden", 0x08); public static final InputFlagsNavHidden[] VALUES = new InputFlagsNavHidden[]{ NAVEXPOSED, NAVHIDDEN }; private InputFlagsNavHidden(String name, int flag) { super(name, flag); } public static InputFlagsNavHidden valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static InputFlagsNavHidden valueOf(String name){ return Flag.valueOf(VALUES, name); } public static InputFlagsNavHidden fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static InputFlagsNavHidden fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(InputFlagsNavHidden flag, int value){ return Flag.update(MASK, flag, value); } } public static final class UiModeType extends Flag{ public static final int MASK = 0x0f; public static final UiModeType NORMAL = new UiModeType("normal", 0x01); public static final UiModeType DESK = new UiModeType("desk", 0x02); public static final UiModeType CAR = new UiModeType("car", 0x03); public static final UiModeType TELEVISION = new UiModeType("television", 0x04); public static final UiModeType APPLIANCE = new UiModeType("appliance", 0x05); public static final UiModeType WATCH = new UiModeType("watch", 0x06); public static final UiModeType VRHEADSET = new UiModeType("vrheadset", 0x07); public static final UiModeType GODZILLAUI = new UiModeType("godzillaui", 0x0b); public static final UiModeType SMALLUI = new UiModeType("smallui", 0x0c); public static final UiModeType MEDIUMUI = new UiModeType("mediumui", 0x0d); public static final UiModeType LARGEUI = new UiModeType("largeui", 0x0e); public static final UiModeType HUGEUI = new UiModeType("hugeui", 0x0f); private static final UiModeType[] VALUES = new UiModeType[]{ NORMAL, DESK, CAR, TELEVISION, APPLIANCE, WATCH, VRHEADSET, GODZILLAUI, SMALLUI, MEDIUMUI, LARGEUI, HUGEUI }; private UiModeType(String name, int flag) { super(name, flag); } public static UiModeType valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static UiModeType valueOf(String name){ return Flag.valueOf(VALUES, name); } public static UiModeType fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static UiModeType fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(UiModeType flag, int value){ return Flag.update(MASK, flag, value); } } public static final class UiModeNight extends Flag{ public static final int MASK = 0x30; public static final UiModeNight NOTNIGHT = new UiModeNight("notnight",0x10); public static final UiModeNight NIGHT = new UiModeNight("night",0x20); private static final UiModeNight[] VALUES = new UiModeNight[]{ NOTNIGHT, NIGHT }; private UiModeNight(String name, int flag) { super(name, flag); } public static UiModeNight valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static UiModeNight valueOf(String name){ return Flag.valueOf(VALUES, name); } public static UiModeNight fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static UiModeNight fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(UiModeNight flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ScreenLayoutSize extends Flag{ public static final int MASK = 0x0f; public static final ScreenLayoutSize SMALL = new ScreenLayoutSize("small", 0x01); public static final ScreenLayoutSize NORMAL = new ScreenLayoutSize("normal", 0x02); public static final ScreenLayoutSize LARGE = new ScreenLayoutSize("large", 0x03); public static final ScreenLayoutSize XLARGE = new ScreenLayoutSize("xlarge", 0x04); public static final ScreenLayoutSize[] VALUES = new ScreenLayoutSize[]{ SMALL, NORMAL, LARGE, XLARGE }; private ScreenLayoutSize(String name, int flag) { super(name, flag); } public static ScreenLayoutSize valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ScreenLayoutSize valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ScreenLayoutSize fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ScreenLayoutSize fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ScreenLayoutSize flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ScreenLayoutLong extends Flag{ public static final int MASK = 0x30; public static final ScreenLayoutLong NOTLONG = new ScreenLayoutLong("notlong", 0x10); public static final ScreenLayoutLong LONG = new ScreenLayoutLong("long", 0x20); public static final ScreenLayoutLong[] VALUES = new ScreenLayoutLong[]{ NOTLONG, LONG }; private ScreenLayoutLong(String name, int flag) { super(name, flag); } public static ScreenLayoutLong valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ScreenLayoutLong valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ScreenLayoutLong fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ScreenLayoutLong fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ScreenLayoutLong flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ScreenLayoutDir extends Flag{ public static final int MASK = 0xC0; public static final ScreenLayoutDir LDLTR = new ScreenLayoutDir("ldltr", 0x40); public static final ScreenLayoutDir LDRTL = new ScreenLayoutDir("ldrtl", 0x80); public static final ScreenLayoutDir[] VALUES = new ScreenLayoutDir[]{ LDLTR, LDRTL }; private ScreenLayoutDir(String name, int flag) { super(name, flag); } public static ScreenLayoutDir valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ScreenLayoutDir valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ScreenLayoutDir fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ScreenLayoutDir fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ScreenLayoutDir flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ScreenLayoutRound extends Flag{ public static final int MASK = 0x03; public static final ScreenLayoutRound NOTROUND = new ScreenLayoutRound("notround", 0x01); public static final ScreenLayoutRound ROUND = new ScreenLayoutRound("round", 0x02); public static final ScreenLayoutRound[] VALUES = new ScreenLayoutRound[]{ NOTROUND, ROUND }; private ScreenLayoutRound(String name, int flag) { super(name, flag); } public static ScreenLayoutRound valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ScreenLayoutRound valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ScreenLayoutRound fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ScreenLayoutRound fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ScreenLayoutRound flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ColorModeWide extends Flag{ public static final int MASK = 0x03; public static final ColorModeWide NOWIDECG = new ColorModeWide("nowidecg", 0x01); public static final ColorModeWide WIDECG = new ColorModeWide("widecg", 0x02); public static final ColorModeWide[] VALUES = new ColorModeWide[]{ NOWIDECG, WIDECG }; private ColorModeWide(String name, int flag) { super(name, flag); } public static ColorModeWide valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ColorModeWide valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ColorModeWide fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ColorModeWide fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ColorModeWide flag, int value){ return Flag.update(MASK, flag, value); } } public static final class ColorModeHdr extends Flag{ public static final int MASK = 0x0C; public static final ColorModeHdr LOWDR = new ColorModeHdr("lowdr", 0x04); public static final ColorModeHdr HIGHDR = new ColorModeHdr("highdr", 0x08); public static final ColorModeHdr[] VALUES = new ColorModeHdr[]{ LOWDR, HIGHDR }; private ColorModeHdr(String name, int flag) { super(name, flag); } public static ColorModeHdr valueOf(int flag){ return Flag.valueOf(VALUES, MASK, flag); } public static ColorModeHdr valueOf(String name){ return Flag.valueOf(VALUES, name); } public static ColorModeHdr fromQualifiers(String qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static ColorModeHdr fromQualifiers(String[] qualifiers){ return Flag.fromQualifiers(VALUES, qualifiers); } public static int update(ColorModeHdr flag, int value){ return Flag.update(MASK, flag, value); } } static class Flag{ private final String name; private final int flag; Flag(String name, int flag){ this.name = name; this.flag = flag; } public int getFlag() { return flag; } @Override public boolean equals(Object obj) { return obj == this; } @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { return name; } public static String toString(Flag flag){ if(flag!=null){ return flag.toString(); } return null; } static T fromQualifiers(T[] values, String qualifiers){ if(qualifiers == null){ return null; } return fromQualifiers(values, qualifiers.split("\\s*-\\s*")); } static T fromQualifiers(T[] values, String[] qualifiers){ if(qualifiers == null){ return null; } for(int i=0;i < qualifiers.length;i++){ T flag = Flag.valueOf(values, qualifiers[i]); if(flag != null){ qualifiers[i] = null; return flag; } } return null; } static T valueOf(T[] values, int mask, int flagValue){ flagValue = flagValue & mask; for(T flag:values){ if(flagValue == flag.getFlag()){ return flag; } } return null; } static T valueOf(T[] values, String name){ if(name == null || name.length()==0){ return null; } if(name.charAt(0)=='-'){ name = name.substring(1); } name = name.toLowerCase(); for(T flag:values){ if(name.equals(flag.toString())){ return flag; } } return null; } public static int update(int mask, Flag flag, int value){ int flip = (~mask) & 0xff; value = value & flip; if(flag != null){ value = value | flag.getFlag(); } return value; } } static class QualifierBuilder{ private final ResConfig mConfig; private StringBuilder mBuilder; public QualifierBuilder(ResConfig resConfig){ this.mConfig = resConfig; } public String build(){ ResConfig resConfig = this.mConfig; if(resConfig.isDefault()){ return ""; } this.mBuilder = new StringBuilder(); appendPrefixedNumber("mcc", resConfig.getMcc()); appendPrefixedNumber("mnc", resConfig.getMnc()); appendLanguageAndRegion(); appendFlag(resConfig.getOrientation()); appendFlag(resConfig.getTouchscreen()); appendFlag(resConfig.getDensity()); appendFlag(resConfig.getKeyboard()); appendFlag(resConfig.getNavigation()); appendFlag(resConfig.getInputFlagsKeysHidden()); appendFlag(resConfig.getInputFlagsNavHidden()); appendScreenWidthHeight(); appendPrefixedNumber("v", resConfig.getSdkVersion()); // append resConfig.getMinorVersion() appendFlag(resConfig.getScreenLayoutSize()); appendFlag(resConfig.getScreenLayoutLong()); appendFlag(resConfig.getScreenLayoutDir()); appendFlag(resConfig.getUiModeType()); appendFlag(resConfig.getUiModeNight()); appendDp("sw", resConfig.getSmallestScreenWidthDp()); appendDp("w", resConfig.getScreenWidthDp()); appendDp("h", resConfig.getScreenHeightDp()); appendFlag(resConfig.getScreenLayoutRound()); appendFlag(resConfig.getColorModeWide()); appendFlag(resConfig.getColorModeHdr()); appendLocaleNumberingSystem(); return mBuilder.toString(); } private void appendScreenWidthHeight(){ ResConfig resConfig = this.mConfig; int width = resConfig.getScreenWidth(); int height = resConfig.getScreenHeight(); if(width==0 && height==0){ return; } mBuilder.append(width).append('x').append(height); } private void appendLanguageAndRegion(){ ResConfig resConfig = this.mConfig; String language = resConfig.getLanguage(); String region = resConfig.getRegion(); String script = resConfig.getLocaleScript(); String variant = resConfig.getLocaleVariant(); if(language==null && region==null){ return; } StringBuilder builder = this.mBuilder; char separator; if(script != null || variant != null){ builder.append('-'); builder.append('b'); separator = '+'; }else { separator = '-'; } if(language!=null){ builder.append(separator); builder.append(language); } if(region!=null){ builder.append(separator); if(region.length()==2){ builder.append('r'); } builder.append(region); } if(script!=null){ builder.append(separator); builder.append(script); } if(variant!=null){ builder.append(separator); builder.append(variant); } } private void appendLocaleNumberingSystem(){ String numberingSystem = mConfig.getLocaleNumberingSystem(); if(numberingSystem==null){ return; } StringBuilder builder = mBuilder; builder.append("-u+nu+"); builder.append(numberingSystem); } private void appendFlag(ResConfig.Flag flag){ if(flag==null){ return; } mBuilder.append('-').append(flag.toString()); } private void appendDp(String prefix, int number){ if(number == 0){ return; } StringBuilder builder = this.mBuilder; builder.append('-'); if(prefix!=null){ builder.append(prefix); } builder.append(number); builder.append("dp"); } private void appendPrefixedNumber(String prefix, int number){ if(number == 0){ return; } StringBuilder builder = this.mBuilder; builder.append('-'); builder.append(prefix); builder.append(number); } } static class QualifierParser{ private final ResConfig mConfig; private final String[] mQualifiers; private final int mPreferredSize; private boolean mEmpty; private boolean mLanguageRegionParsed; private boolean mParseComplete; public QualifierParser(ResConfig resConfig, String[] qualifiers){ this.mConfig = resConfig; this.mQualifiers = qualifiers; this.mPreferredSize = resConfig.getConfigSize(); } public QualifierParser(ResConfig resConfig, String qualifiers){ this(resConfig, splitQualifiers(qualifiers)); } public void parse(){ if(this.mParseComplete){ return; } if(isEmpty()){ onParseComplete(); return; } ResConfig resConfig = this.mConfig; resConfig.setConfigSize(ResConfig.SIZE_64); parsePrefixedNumber(); parseDp(); parseWidthHeight(); parseLocaleNumberingSystem(); if(isEmpty()){ onParseComplete(); return; } String[] qualifiers = this.mQualifiers; resConfig.setOrientation(ResConfig.Orientation.fromQualifiers(qualifiers)); resConfig.setTouchscreen(ResConfig.Touchscreen.fromQualifiers(qualifiers)); resConfig.setDensity(ResConfig.Density.fromQualifiers(qualifiers)); resConfig.setKeyboard(ResConfig.Keyboard.fromQualifiers(qualifiers)); resConfig.setNavigation(ResConfig.Navigation.fromQualifiers(qualifiers)); if(isEmpty()){ onParseComplete(); return; } resConfig.setInputFlagsKeysHidden(ResConfig.InputFlagsKeysHidden.fromQualifiers(qualifiers)); resConfig.setInputFlagsNavHidden(ResConfig.InputFlagsNavHidden.fromQualifiers(qualifiers)); resConfig.setScreenLayoutSize(ResConfig.ScreenLayoutSize.fromQualifiers(qualifiers)); resConfig.setScreenLayoutLong(ResConfig.ScreenLayoutLong.fromQualifiers(qualifiers)); resConfig.setScreenLayoutDir(ResConfig.ScreenLayoutDir.fromQualifiers(qualifiers)); if(isEmpty()){ onParseComplete(); return; } resConfig.setUiModeType(ResConfig.UiModeType.fromQualifiers(qualifiers)); resConfig.setUiModeNight(ResConfig.UiModeNight.fromQualifiers(qualifiers)); resConfig.setScreenLayoutRound(ResConfig.ScreenLayoutRound.fromQualifiers(qualifiers)); resConfig.setColorModeWide(ResConfig.ColorModeWide.fromQualifiers(qualifiers)); resConfig.setColorModeHdr(ResConfig.ColorModeHdr.fromQualifiers(qualifiers)); if(isEmpty()){ onParseComplete(); return; } parseLocaleScriptVariant(); parseLanguage(); parseRegion(); onParseComplete(); } public String[] getErrors(){ if(!this.mParseComplete){ return null; } String[] qualifiers = this.mQualifiers; if(qualifiers==null || qualifiers.length==0){ return null; } int length = qualifiers.length; String[] tmp = new String[length]; int count = 0; for(int i=0;i