From 6f89ddfe8ebc71c43f753ddf3328ee773df3ca81 Mon Sep 17 00:00:00 2001 From: ibaker Date: Mon, 17 Apr 2023 10:55:24 +0100 Subject: [PATCH] Rollback of https://github.com/androidx/media/commit/a358ccb046d84c44dc7d54ed39d7563074cd5535 *** Original commit *** Fix double initialisation of createIsoLanguageReplacementMap In the absence of any lock `createIsoLanguageReplacementMap` method was getting called twice due to race condition. Used Suppliers.memoize() which is by default thread safe. *** PiperOrigin-RevId: 524794650 --- .../androidx/media3/common/util/Util.java | 164 +++++++++--------- 1 file changed, 81 insertions(+), 83 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index e3600b0585..91f1183cb4 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -85,9 +85,6 @@ import androidx.media3.common.Player; import androidx.media3.common.Player.Commands; import com.google.common.base.Ascii; import com.google.common.base.Charsets; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -111,7 +108,6 @@ import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.MissingResourceException; import java.util.NoSuchElementException; import java.util.TimeZone; @@ -184,8 +180,7 @@ public final class Util { private static final String ISM_DASH_FORMAT_EXTENSION = "format=mpd-time-csf"; // Replacement map of ISO language codes used for normalization. - private static final Supplier> LANGUAGE_TAG_REPLACEMENT_MAP = - Suppliers.memoize(Util::createIsoLanguageReplacementMap); + @Nullable private static HashMap languageTagReplacementMap; private Util() {} @@ -823,8 +818,10 @@ public final class Util { } normalizedTag = Ascii.toLowerCase(normalizedTag); String mainLanguage = splitAtFirst(normalizedTag, "-")[0]; - - @Nullable String replacedLanguage = LANGUAGE_TAG_REPLACEMENT_MAP.get().get(mainLanguage); + if (languageTagReplacementMap == null) { + languageTagReplacementMap = createIsoLanguageReplacementMap(); + } + @Nullable String replacedLanguage = languageTagReplacementMap.get(mainLanguage); if (replacedLanguage != null) { normalizedTag = replacedLanguage + normalizedTag.substring(/* beginIndex= */ mainLanguage.length()); @@ -2982,12 +2979,11 @@ public final class Util { return locale.toLanguageTag(); } - private static ImmutableMap createIsoLanguageReplacementMap() { + private static HashMap createIsoLanguageReplacementMap() { String[] iso2Languages = Locale.getISOLanguages(); HashMap replacedLanguages = new HashMap<>( - /* initialCapacity= */ iso2Languages.length - + ADDITIONAL_ISO_LANGUAGE_REPLACEMENTS.size()); + /* initialCapacity= */ iso2Languages.length + additionalIsoLanguageReplacements.length); for (String iso2 : iso2Languages) { try { // This returns the ISO 639-2/T code for the language. @@ -3000,9 +2996,11 @@ public final class Util { } } // Add additional replacement mappings. - replacedLanguages.putAll(ADDITIONAL_ISO_LANGUAGE_REPLACEMENTS); - - return ImmutableMap.copyOf(replacedLanguages); + for (int i = 0; i < additionalIsoLanguageReplacements.length; i += 2) { + replacedLanguages.put( + additionalIsoLanguageReplacements[i], additionalIsoLanguageReplacements[i + 1]); + } + return replacedLanguages; } @RequiresApi(api = Build.VERSION_CODES.M) @@ -3024,84 +3022,84 @@ public final class Util { } private static String maybeReplaceLegacyLanguageTags(String languageTag) { - for (Map.Entry legacyTagToModernTag : ISO_LEGACY_TAG_REPLACEMENTS.entrySet()) { - if (languageTag.startsWith(legacyTagToModernTag.getKey())) { - return legacyTagToModernTag.getValue() - + languageTag.substring(/* beginIndex= */ legacyTagToModernTag.getKey().length()); + for (int i = 0; i < isoLegacyTagReplacements.length; i += 2) { + if (languageTag.startsWith(isoLegacyTagReplacements[i])) { + return isoLegacyTagReplacements[i + 1] + + languageTag.substring(/* beginIndex= */ isoLegacyTagReplacements[i].length()); } } - return languageTag; } // Additional mapping from ISO3 to ISO2 language codes. - private static final ImmutableMap ADDITIONAL_ISO_LANGUAGE_REPLACEMENTS = - new ImmutableMap.Builder() - // Bibliographical codes defined in ISO 639-2/B, replaced by terminological code defined - // in ISO 639-2/T. See https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes. - .put("alb", "sq") - .put("arm", "hy") - .put("baq", "eu") - .put("bur", "my") - .put("tib", "bo") - .put("chi", "zh") - .put("cze", "cs") - .put("dut", "nl") - .put("ger", "de") - .put("gre", "el") - .put("fre", "fr") - .put("geo", "ka") - .put("ice", "is") - .put("mac", "mk") - .put("mao", "mi") - .put("may", "ms") - .put("per", "fa") - .put("rum", "ro") - .put("scc", "hbs-srp") - .put("slo", "sk") - .put("wel", "cy") - // Deprecated 2-letter codes, replaced by modern equivalent (including macrolanguage) - // See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes, "ISO 639:1988" - .put("id", "ms-ind") - .put("iw", "he") - .put("heb", "he") - .put("ji", "yi") - // Individual macrolanguage codes mapped back to full macrolanguage code. - // See https://en.wikipedia.org/wiki/ISO_639_macrolanguage - .put("arb", "ar-arb") - .put("in", "ms-ind") - .put("ind", "ms-ind") - .put("nb", "no-nob") - .put("nob", "no-nob") - .put("nn", "no-nno") - .put("nno", "no-nno") - .put("tw", "ak-twi") - .put("twi", "ak-twi") - .put("bs", "hbs-bos") - .put("bos", "hbs-bos") - .put("hr", "hbs-hrv") - .put("hrv", "hbs-hrv") - .put("sr", "hbs-srp") - .put("srp", "hbs-srp") - .put("cmn", "zh-cmn") - .put("hak", "zh-hak") - .put("nan", "zh-nan") - .put("hsn", "zh-hsn") - .buildOrThrow(); + private static final String[] additionalIsoLanguageReplacements = + new String[] { + // Bibliographical codes defined in ISO 639-2/B, replaced by terminological code defined in + // ISO 639-2/T. See https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes. + "alb", "sq", + "arm", "hy", + "baq", "eu", + "bur", "my", + "tib", "bo", + "chi", "zh", + "cze", "cs", + "dut", "nl", + "ger", "de", + "gre", "el", + "fre", "fr", + "geo", "ka", + "ice", "is", + "mac", "mk", + "mao", "mi", + "may", "ms", + "per", "fa", + "rum", "ro", + "scc", "hbs-srp", + "slo", "sk", + "wel", "cy", + // Deprecated 2-letter codes, replaced by modern equivalent (including macrolanguage) + // See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes, "ISO 639:1988" + "id", "ms-ind", + "iw", "he", + "heb", "he", + "ji", "yi", + // Individual macrolanguage codes mapped back to full macrolanguage code. + // See https://en.wikipedia.org/wiki/ISO_639_macrolanguage + "arb", "ar-arb", + "in", "ms-ind", + "ind", "ms-ind", + "nb", "no-nob", + "nob", "no-nob", + "nn", "no-nno", + "nno", "no-nno", + "tw", "ak-twi", + "twi", "ak-twi", + "bs", "hbs-bos", + "bos", "hbs-bos", + "hr", "hbs-hrv", + "hrv", "hbs-hrv", + "sr", "hbs-srp", + "srp", "hbs-srp", + "cmn", "zh-cmn", + "hak", "zh-hak", + "nan", "zh-nan", + "hsn", "zh-hsn" + }; // Legacy tags that have been replaced by modern equivalents (including macrolanguage) // See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry. - private static final ImmutableMap ISO_LEGACY_TAG_REPLACEMENTS = - ImmutableMap.of( - "i-lux", "lb", - "i-hak", "zh-hak", - "i-navajo", "nv", - "no-bok", "no-nob", - "no-nyn", "no-nno", - "zh-guoyu", "zh-cmn", - "zh-hakka", "zh-hak", - "zh-min-nan", "zh-nan", - "zh-xiang", "zh-hsn"); + private static final String[] isoLegacyTagReplacements = + new String[] { + "i-lux", "lb", + "i-hak", "zh-hak", + "i-navajo", "nv", + "no-bok", "no-nob", + "no-nyn", "no-nno", + "zh-guoyu", "zh-cmn", + "zh-hakka", "zh-hak", + "zh-min-nan", "zh-nan", + "zh-xiang", "zh-hsn" + }; /** * Allows the CRC-32 calculation to be done byte by byte instead of bit per bit in the order "most