All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.res.android.ConfigDescription Maven / Gradle / Ivy

There is a newer version: 4.14.1
Show newest version
package org.robolectric.res.android;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.robolectric.res.android.Util.isTruthy;

import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * transliterated from
 * https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/tools/aapt2/ConfigDescription.cpp
 */
public class ConfigDescription {
  public static final int SDK_CUPCAKE = 3;
  public static final int SDK_DONUT = 4;
  public static final int SDK_ECLAIR = 5;
  public static final int SDK_ECLAIR_0_1 = 6;
  public static final int SDK_ECLAIR_MR1 = 7;
  public static final int SDK_FROYO = 8;
  public static final int SDK_GINGERBREAD = 9;
  public static final int SDK_GINGERBREAD_MR1 = 10;
  public static final int SDK_HONEYCOMB = 11;
  public static final int SDK_HONEYCOMB_MR1 = 12;
  public static final int SDK_HONEYCOMB_MR2 = 13;
  public static final int SDK_ICE_CREAM_SANDWICH = 14;
  public static final int SDK_ICE_CREAM_SANDWICH_MR1 = 15;
  public static final int SDK_JELLY_BEAN = 16;
  public static final int SDK_JELLY_BEAN_MR1 = 17;
  public static final int SDK_JELLY_BEAN_MR2 = 18;
  public static final int SDK_KITKAT = 19;
  public static final int SDK_KITKAT_WATCH = 20;
  public static final int SDK_LOLLIPOP = 21;
  public static final int SDK_LOLLIPOP_MR1 = 22;
  public static final int SDK_MNC = 23;
  public static final int SDK_NOUGAT = 24;
  public static final int SDK_NOUGAT_MR1 = 25;
  public static final int SDK_O = 26;

  /**
   * Constant used to to represent MNC (Mobile Network Code) zero.
   * 0 cannot be used, since it is used to represent an undefined MNC.
   */
  private static final int ACONFIGURATION_MNC_ZERO = 0xffff;

  private static final String kWildcardName = "any";

  private static final Pattern MCC_PATTERN = Pattern.compile("mcc([\\d]+)");
  private static final Pattern MNC_PATTERN = Pattern.compile("mnc([\\d]+)");
  private static final Pattern SMALLEST_SCREEN_WIDTH_PATTERN = Pattern.compile("^sw([0-9]+)dp");
  private static final Pattern SCREEN_WIDTH_PATTERN = Pattern.compile("^w([0-9]+)dp");
  private static final Pattern SCREEN_HEIGHT_PATTERN = Pattern.compile("^h([0-9]+)dp");
  private static final Pattern DENSITY_PATTERN = Pattern.compile("^([0-9]+)dpi");
  private static final Pattern HEIGHT_WIDTH_PATTERN = Pattern.compile("^([0-9]+)x([0-9]+)");
  private static final Pattern VERSION_QUALIFIER_PATTERN = Pattern.compile("v([0-9]+)$");

  public static class LocaleValue {

    String language;
    String region;
    String script;
    String variant;

    void set_language(String language_chars) {
      language = language_chars.trim().toLowerCase();
    }

    void set_region(String region_chars) {
      region = region_chars.trim().toUpperCase();
    }

    void set_script(String script_chars) {
      script = String.valueOf(Character.toUpperCase(script_chars.charAt(0))) +
          script_chars.substring(1).toLowerCase();
    }

    void set_variant(String variant_chars) {
      variant = variant_chars.trim();
    }


    static boolean is_alpha(final String str) {
      for (int i = 0; i < str.length(); i++) {
        if (!Character.isAlphabetic(str.charAt(i))) {
          return false;
        }
      }

      return true;
    }

    int initFromParts(PeekingIterator iter) {

      String part = iter.peek();
      if (part.startsWith("b+")) {
        // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags,
        // except that the separator is "+" and not "-".
        String[] subtags = part.substring(2).toLowerCase().split("\\+", 0);
        if (subtags.length == 1) {
          set_language(subtags[0]);
        } else if (subtags.length == 2) {
          set_language(subtags[0]);

          // The second tag can either be a region, a variant or a script.
          switch (subtags[1].length()) {
            case 2:
            case 3:
              set_region(subtags[1]);
              break;
            case 4:
              if ('0' <= subtags[1].charAt(0) && subtags[1].charAt(0) <= '9') {
                // This is a variant: fall through
              } else {
                set_script(subtags[1]);
                break;
              }
              // fall through
            case 5:
            case 6:
            case 7:
            case 8:
              set_variant(subtags[1]);
              break;
            default:
              return -1;
          }
        } else if (subtags.length == 3) {
          // The language is always the first subtag.
          set_language(subtags[0]);

          // The second subtag can either be a script or a region code.
          // If its size is 4, it's a script code, else it's a region code.
          if (subtags[1].length() == 4) {
            set_script(subtags[1]);
          } else if (subtags[1].length() == 2 || subtags[1].length() == 3) {
            set_region(subtags[1]);
          } else {
            return -1;
          }

          // The third tag can either be a region code (if the second tag was
          // a script), else a variant code.
          if (subtags[2].length() >= 4) {
            set_variant(subtags[2]);
          } else {
            set_region(subtags[2]);
          }
        } else if (subtags.length == 4) {
          set_language(subtags[0]);
          set_script(subtags[1]);
          set_region(subtags[2]);
          set_variant(subtags[3]);
        } else {
          return -1;
        }

        iter.next();

      } else {
        if ((part.length() == 2 || part.length() == 3) && is_alpha(part) &&
            !Objects.equals(part, "car")) {
          set_language(part);
          iter.next();

          if (iter.hasNext()) {
            final String region_part = iter.peek();
            if (region_part.charAt(0) == 'r' && region_part.length() == 3) {
              set_region(region_part.substring(1));
              iter.next();
            }
          }
        }
      }

      return 0;
    }

    public void writeTo(ResTable_config out) {
      out.packLanguage(language);
      out.packRegion(region);

      Arrays.fill(out.localeScript, (byte) 0);
      byte[] scriptBytes = script == null ? new byte[4] : script.getBytes(UTF_8);
      System.arraycopy(scriptBytes, 0, out.localeScript, 0, scriptBytes.length);

      Arrays.fill(out.localeVariant, (byte) 0);
      byte[] variantBytes = variant == null ? new byte[8] : variant.getBytes(UTF_8);
      System.arraycopy(variantBytes, 0, out.localeVariant, 0, variantBytes.length);
    }
  }

  public static boolean parse(final String str, ResTable_config out) {
    return parse(str, out, true);
  }

  public static boolean parse(final String str, ResTable_config out, boolean applyVersionForCompat) {
    PeekingIterator part_iter = Iterators
        .peekingIterator(Arrays.asList(str.toLowerCase().split("-")).iterator());

    LocaleValue locale = new LocaleValue();

    boolean success = !part_iter.hasNext();
    if (part_iter.hasNext() && parseMcc(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseMnc(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext()) {
      // Locale spans a few '-' separators, so we let it
      // control the index.
      int parts_consumed = locale.initFromParts(part_iter);
      if (parts_consumed < 0) {
        return false;
      } else {
        locale.writeTo(out);
        if (!part_iter.hasNext()) {
          success = !part_iter.hasNext();
        }
      }
    }

    if (part_iter.hasNext() && parseLayoutDirection(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseSmallestScreenWidthDp(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenWidthDp(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenHeightDp(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenLayoutSize(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenLayoutLong(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenRound(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseWideColorGamut(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseHdr(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseOrientation(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseUiModeType(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseUiModeNight(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseDensity(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseTouchscreen(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseKeysHidden(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseKeyboard(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseNavHidden(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseNavigation(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseScreenSize(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (part_iter.hasNext() && parseVersion(part_iter.peek(), out)) {
      part_iter.next();
      if (!part_iter.hasNext()) {
        success = !part_iter.hasNext();
      }
    }

    if (!success) {
      // Unrecognized.
      return false;
    }

    if (out != null && applyVersionForCompat) {
      applyVersionForCompatibility(out);
    }
    return true;
  }

  private static boolean parseLayoutDirection(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_LAYOUTDIR) |
                ResTable_config.LAYOUTDIR_ANY;
      }
      return true;
    } else if (Objects.equals(name, "ldltr")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_LAYOUTDIR) |
                ResTable_config.LAYOUTDIR_LTR;
      }
      return true;
    } else if (Objects.equals(name, "ldrtl")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_LAYOUTDIR) |
                ResTable_config.LAYOUTDIR_RTL;
      }
      return true;
    }

    return false;
  }

  private static boolean parseSmallestScreenWidthDp(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.smallestScreenWidthDp = ResTable_config.SCREENWIDTH_ANY;
      }
      return true;
    }

    Matcher matcher = SMALLEST_SCREEN_WIDTH_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.smallestScreenWidthDp = Integer.parseInt(matcher.group(1));
      return true;
    }
    return false;
  }

  private static boolean parseScreenWidthDp(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenWidthDp = ResTable_config.SCREENWIDTH_ANY;
      }
      return true;
    }

    Matcher matcher = SCREEN_WIDTH_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.screenWidthDp = Integer.parseInt(matcher.group(1));
      return true;
    }
    return false;
  }

  private static boolean parseScreenHeightDp(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenHeightDp = ResTable_config.SCREENWIDTH_ANY;
      }
      return true;
    }

    Matcher matcher = SCREEN_HEIGHT_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.screenHeightDp = Integer.parseInt(matcher.group(1));
      return true;
    }
    return false;
  }

  private static boolean parseScreenLayoutSize(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_SCREENSIZE) |
                ResTable_config.SCREENSIZE_ANY;
      }
      return true;
    } else if (Objects.equals(name, "small")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_SCREENSIZE) |
                ResTable_config.SCREENSIZE_SMALL;
      }
      return true;
    } else if (Objects.equals(name, "normal")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_SCREENSIZE) |
                ResTable_config.SCREENSIZE_NORMAL;
      }
      return true;
    } else if (Objects.equals(name, "large")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_SCREENSIZE) |
                ResTable_config.SCREENSIZE_LARGE;
      }
      return true;
    } else if (Objects.equals(name, "xlarge")) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout & ~ResTable_config.MASK_SCREENSIZE) |
                ResTable_config.SCREENSIZE_XLARGE;
      }
      return true;
    }

    return false;
  }

  static boolean parseScreenLayoutLong(final String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenLayout =
            (out.screenLayout&~ResTable_config.MASK_SCREENLONG)
                | ResTable_config.SCREENLONG_ANY;
      }
      return true;
    } else if (Objects.equals(name, "long")) {
      if (out != null) out.screenLayout =
          (out.screenLayout&~ResTable_config.MASK_SCREENLONG)
              | ResTable_config.SCREENLONG_YES;
      return true;
    } else if (Objects.equals(name, "notlong")) {
      if (out != null) out.screenLayout =
          (out.screenLayout&~ResTable_config.MASK_SCREENLONG)
              | ResTable_config.SCREENLONG_NO;
      return true;
    }
    return false;
  }

  private static boolean parseScreenRound(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenLayout2 =
            (byte) ((out.screenLayout2 & ~ResTable_config.MASK_SCREENROUND) |
                            ResTable_config.SCREENROUND_ANY);
      }
      return true;
    } else if (Objects.equals(name, "round")) {
      if (out != null) {
        out.screenLayout2 =
            (byte) ((out.screenLayout2 & ~ResTable_config.MASK_SCREENROUND) |
                            ResTable_config.SCREENROUND_YES);
      }
      return true;
    } else if (Objects.equals(name, "notround")) {
      if (out != null) {
        out.screenLayout2 =
            (byte) ((out.screenLayout2 & ~ResTable_config.MASK_SCREENROUND) |
                ResTable_config.SCREENROUND_NO);
      }
      return true;
    }
    return false;
  }

  private static boolean parseWideColorGamut(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) |
                            ResTable_config.WIDE_COLOR_GAMUT_ANY);
      return true;
    } else if (Objects.equals(name, "widecg")) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) |
                            ResTable_config.WIDE_COLOR_GAMUT_YES);
      return true;
    } else if (Objects.equals(name, "nowidecg")) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_WIDE_COLOR_GAMUT) |
                            ResTable_config.WIDE_COLOR_GAMUT_NO);
      return true;
    }
    return false;
  }

  private static boolean parseHdr(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) |
                            ResTable_config.HDR_ANY);
      return true;
    } else if (Objects.equals(name, "highdr")) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) |
                            ResTable_config.HDR_YES);
      return true;
    } else if (Objects.equals(name, "lowdr")) {
      if (out != null)
        out.colorMode =
            (byte) ((out.colorMode & ~ResTable_config.MASK_HDR) |
                            ResTable_config.HDR_NO);
      return true;
    }
    return false;
  }

  private static boolean parseOrientation(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.orientation = ResTable_config.ORIENTATION_ANY;
      }
      return true;
    } else if (Objects.equals(name, "port")) {
      if (out != null) {
        out.orientation = ResTable_config.ORIENTATION_PORT;
      }
      return true;
    } else if (Objects.equals(name, "land")) {
      if (out != null) {
        out.orientation = ResTable_config.ORIENTATION_LAND;
      }
      return true;
    } else if (Objects.equals(name, "square")) {
      if (out != null) {
        out.orientation = ResTable_config.ORIENTATION_SQUARE;
      }
      return true;
    }

    return false;
  }

  private static boolean parseUiModeType(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_ANY;
      }
      return true;
    } else if (Objects.equals(name, "desk")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_DESK;
      }
      return true;
    } else if (Objects.equals(name, "car")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_CAR;
      }
      return true;
    } else if (Objects.equals(name, "television")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_TELEVISION;
      }
      return true;
    } else if (Objects.equals(name, "appliance")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_APPLIANCE;
      }
      return true;
    } else if (Objects.equals(name, "watch")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_WATCH;
      }
      return true;
    } else if (Objects.equals(name, "vrheadset")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_TYPE) |
            ResTable_config.UI_MODE_TYPE_VR_HEADSET;
      }
      return true;
    }

    return false;
  }

  private static boolean parseUiModeNight(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_NIGHT) |
            ResTable_config.UI_MODE_NIGHT_ANY;
      }
      return true;
    } else if (Objects.equals(name, "night")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_NIGHT) |
            ResTable_config.UI_MODE_NIGHT_YES;
      }
      return true;
    } else if (Objects.equals(name, "notnight")) {
      if (out != null) {
        out.uiMode = (out.uiMode & ~ResTable_config.MASK_UI_MODE_NIGHT) |
            ResTable_config.UI_MODE_NIGHT_NO;
      }
      return true;
    }

    return false;
  }

  private static boolean parseDensity(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_DEFAULT;
      }
      return true;
    }

    if (Objects.equals(name, "anydpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_ANY;
      }
      return true;
    }

    if (Objects.equals(name, "nodpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_NONE;
      }
      return true;
    }

    if (Objects.equals(name, "ldpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_LOW;
      }
      return true;
    }

    if (Objects.equals(name, "mdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_MEDIUM;
      }
      return true;
    }

    if (Objects.equals(name, "tvdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_TV;
      }
      return true;
    }

    if (Objects.equals(name, "hdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_HIGH;
      }
      return true;
    }

    if (Objects.equals(name, "xhdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_XHIGH;
      }
      return true;
    }

    if (Objects.equals(name, "xxhdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_XXHIGH;
      }
      return true;
    }

    if (Objects.equals(name, "xxxhdpi")) {
      if (out != null) {
        out.density = ResTable_config.DENSITY_XXXHIGH;
      }
      return true;
    }

    // check that we have 'dpi' after the last digit.
    Matcher matcher = DENSITY_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.density = Integer.parseInt(matcher.group(1));
      return true;
    }
    return false;
  }

  private static boolean parseTouchscreen(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.touchscreen = ResTable_config.TOUCHSCREEN_ANY;
      }
      return true;
    } else if (Objects.equals(name, "notouch")) {
      if (out != null) {
        out.touchscreen = ResTable_config.TOUCHSCREEN_NOTOUCH;
      }
      return true;
    } else if (Objects.equals(name, "stylus")) {
      if (out != null) {
        out.touchscreen = ResTable_config.TOUCHSCREEN_STYLUS;
      }
      return true;
    } else if (Objects.equals(name, "finger")) {
      if (out != null) {
        out.touchscreen = ResTable_config.TOUCHSCREEN_FINGER;
      }
      return true;
    }

    return false;
  }

  private static boolean parseKeysHidden(String name, ResTable_config out) {
    byte mask = 0;
    byte value = 0;
    if (Objects.equals(name, kWildcardName)) {
      mask = ResTable_config.MASK_KEYSHIDDEN;
      value = ResTable_config.KEYSHIDDEN_ANY;
    } else if (Objects.equals(name, "keysexposed")) {
      mask = ResTable_config.MASK_KEYSHIDDEN;
      value = ResTable_config.KEYSHIDDEN_NO;
    } else if (Objects.equals(name, "keyshidden")) {
      mask = ResTable_config.MASK_KEYSHIDDEN;
      value = ResTable_config.KEYSHIDDEN_YES;
    } else if (Objects.equals(name, "keyssoft")) {
      mask = ResTable_config.MASK_KEYSHIDDEN;
      value = ResTable_config.KEYSHIDDEN_SOFT;
    }

    if (mask != 0) {
      if (out != null) {
        out.inputFlags = (out.inputFlags & ~mask) | value;
      }
      return true;
    }

    return false;
  }

  private static boolean parseKeyboard(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.keyboard = ResTable_config.KEYBOARD_ANY;
      }
      return true;
    } else if (Objects.equals(name, "nokeys")) {
      if (out != null) {
        out.keyboard = ResTable_config.KEYBOARD_NOKEYS;
      }
      return true;
    } else if (Objects.equals(name, "qwerty")) {
      if (out != null) {
        out.keyboard = ResTable_config.KEYBOARD_QWERTY;
      }
      return true;
    } else if (Objects.equals(name, "12key")) {
      if (out != null) {
        out.keyboard = ResTable_config.KEYBOARD_12KEY;
      }
      return true;
    }

    return false;
  }

  private static boolean parseNavHidden(String name, ResTable_config out) {
    byte mask = 0;
    byte value = 0;
    if (Objects.equals(name, kWildcardName)) {
      mask = ResTable_config.MASK_NAVHIDDEN;
      value = ResTable_config.NAVHIDDEN_ANY;
    } else if (Objects.equals(name, "navexposed")) {
      mask = ResTable_config.MASK_NAVHIDDEN;
      value = ResTable_config.NAVHIDDEN_NO;
    } else if (Objects.equals(name, "navhidden")) {
      mask = ResTable_config.MASK_NAVHIDDEN;
      value = ResTable_config.NAVHIDDEN_YES;
    }

    if (mask != 0) {
      if (out != null) {
        out.inputFlags = (out.inputFlags & ~mask) | value;
      }
      return true;
    }

    return false;
  }

  private static boolean parseNavigation(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.navigation = ResTable_config.NAVIGATION_ANY;
      }
      return true;
    } else if (Objects.equals(name, "nonav")) {
      if (out != null) {
        out.navigation = ResTable_config.NAVIGATION_NONAV;
      }
      return true;
    } else if (Objects.equals(name, "dpad")) {
      if (out != null) {
        out.navigation = ResTable_config.NAVIGATION_DPAD;
      }
      return true;
    } else if (Objects.equals(name, "trackball")) {
      if (out != null) {
        out.navigation = ResTable_config.NAVIGATION_TRACKBALL;
      }
      return true;
    } else if (Objects.equals(name, "wheel")) {
      if (out != null) {
        out.navigation = ResTable_config.NAVIGATION_WHEEL;
      }
      return true;
    }

    return false;
  }

  private static boolean parseScreenSize(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.screenWidth = ResTable_config.SCREENWIDTH_ANY;
        out.screenHeight = ResTable_config.SCREENHEIGHT_ANY;
      }
      return true;
    }

    Matcher matcher = HEIGHT_WIDTH_PATTERN.matcher(name);
    if (matcher.matches()) {
      int w = Integer.parseInt(matcher.group(1));
      int h = Integer.parseInt(matcher.group(2));
      if (w < h) {
        return false;
      }
      out.screenWidth = w;
      out.screenHeight = h;
      return true;
    }
    return false;
  }

  private static boolean parseVersion(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.sdkVersion = ResTable_config.SDKVERSION_ANY;
        out.minorVersion = ResTable_config.MINORVERSION_ANY;
      }
      return true;
    }

    Matcher matcher = VERSION_QUALIFIER_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.sdkVersion = Integer.parseInt(matcher.group(1));
      out.minorVersion = 0;
      return true;
    }
    return false;
  }

  private static boolean parseMnc(String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.mnc = 0;
      }
      return true;
    }

    Matcher matcher = MNC_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.mnc = Integer.parseInt(matcher.group(1));
      if (out.mnc == 0) {
        out.mnc = ACONFIGURATION_MNC_ZERO;
      }
      return true;
    }
    return false;
  }

  private static boolean parseMcc(final String name, ResTable_config out) {
    if (Objects.equals(name, kWildcardName)) {
      if (out != null) {
        out.mcc = 0;
      }
      return true;
    }

    Matcher matcher = MCC_PATTERN.matcher(name);
    if (matcher.matches()) {
      out.mcc = Integer.parseInt(matcher.group(1));
      return true;
    }
    return false;
  }

  // transliterated from https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r12/tools/aapt/AaptConfig.cpp
  private static void applyVersionForCompatibility(ResTable_config config) {
    if (config == null) {
      return;
    }
    int min_sdk = 0;
    if (((config.uiMode & ResTable_config.MASK_UI_MODE_TYPE)
        == ResTable_config.UI_MODE_TYPE_VR_HEADSET) ||
        (config.colorMode & ResTable_config.MASK_WIDE_COLOR_GAMUT) != 0 ||
            (config.colorMode & ResTable_config.MASK_HDR) != 0) {
      min_sdk = SDK_O;
    } else if (isTruthy(config.screenLayout2 & ResTable_config.MASK_SCREENROUND)) {
      min_sdk = SDK_MNC;
    } else if (config.density == ResTable_config.DENSITY_ANY) {
      min_sdk = SDK_LOLLIPOP;
    } else if (config.smallestScreenWidthDp != ResTable_config.SCREENWIDTH_ANY
        || config.screenWidthDp != ResTable_config.SCREENWIDTH_ANY
        || config.screenHeightDp != ResTable_config.SCREENHEIGHT_ANY) {
      min_sdk = SDK_HONEYCOMB_MR2;
    } else if ((config.uiMode & ResTable_config.MASK_UI_MODE_TYPE)
        != ResTable_config.UI_MODE_TYPE_ANY
        ||  (config.uiMode & ResTable_config.MASK_UI_MODE_NIGHT)
        != ResTable_config.UI_MODE_NIGHT_ANY) {
      min_sdk = SDK_FROYO;
    } else if ((config.screenLayout & ResTable_config.MASK_SCREENSIZE)
        != ResTable_config.SCREENSIZE_ANY
        ||  (config.screenLayout & ResTable_config.MASK_SCREENLONG)
        != ResTable_config.SCREENLONG_ANY
        || config.density != ResTable_config.DENSITY_DEFAULT) {
      min_sdk = SDK_DONUT;
    }
    if (min_sdk > config.sdkVersion) {
      config.sdkVersion = min_sdk;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy