Replace Util.toLowerInvariant() with Ascii.toLowerCase()

Even when fixed to the US locale (and thus avoiding surprising behaviour
in e.g. Turkish locale with "i" and "I") there are unexpected behaviours
when upper and lower casing non-ASCII characters.

For example it's sometimes not symmetric, e.g.:
"ẞ".toLowerCase() -> "ß"
"ß".toUpperCase() -> "SS"

In all the ExoPlayer usages we are either dealing with known-ASCII
strings (e.g. MIME types) or comparing against ASCII constant strings
anyway, so it seems easier to just use Guava's ASCII-only class in these
cases.

This change also includes some null-twiddling, because
Util.toLowerInvariant() is null tolerant, while Ascii.toLowerCase() is
not. Most of the usages were already non-null, and it was easy enough to
change the remaining ones to be so by simple reordering of statements.

I'll make an equivalent change for Util.toUpperInvariant() next.

PiperOrigin-RevId: 368419813
This commit is contained in:
ibaker 2021-04-14 14:44:29 +01:00 committed by Andrew Lewis
parent 40d3e12853
commit c50084e7ba
19 changed files with 55 additions and 51 deletions

View file

@ -35,6 +35,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
@ -546,8 +547,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
@Nullable IOException connectionOpenException = exception; @Nullable IOException connectionOpenException = exception;
if (connectionOpenException != null) { if (connectionOpenException != null) {
@Nullable String message = connectionOpenException.getMessage(); @Nullable String message = connectionOpenException.getMessage();
if (message != null if (message != null && Ascii.toLowerCase(message).contains("err_cleartext_not_permitted")) {
&& Util.toLowerInvariant(message).contains("err_cleartext_not_permitted")) {
throw new CleartextNotPermittedException(connectionOpenException, dataSpec); throw new CleartextNotPermittedException(connectionOpenException, dataSpec);
} }
throw new OpenException(connectionOpenException, dataSpec, getStatus(urlRequest)); throw new OpenException(connectionOpenException, dataSpec, getStatus(urlRequest));

View file

@ -32,6 +32,7 @@ import com.google.android.exoplayer2.upstream.HttpUtil;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import java.io.IOException; import java.io.IOException;
@ -289,7 +290,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
} catch (IOException e) { } catch (IOException e) {
@Nullable String message = e.getMessage(); @Nullable String message = e.getMessage();
if (message != null if (message != null
&& Util.toLowerInvariant(message).matches("cleartext communication.*not permitted.*")) { && Ascii.toLowerCase(message).matches("cleartext communication.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec); throw new CleartextNotPermittedException(e, dataSpec);
} }
throw new HttpDataSourceException( throw new HttpDataSourceException(

View file

@ -24,6 +24,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -539,13 +540,13 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
int mimeTypeEndIndex; int mimeTypeEndIndex;
if (majorVersion == 2) { if (majorVersion == 2) {
mimeTypeEndIndex = 2; mimeTypeEndIndex = 2;
mimeType = "image/" + Util.toLowerInvariant(new String(data, 0, 3, "ISO-8859-1")); mimeType = "image/" + Ascii.toLowerCase(new String(data, 0, 3, "ISO-8859-1"));
if ("image/jpg".equals(mimeType)) { if ("image/jpg".equals(mimeType)) {
mimeType = "image/jpeg"; mimeType = "image/jpeg";
} }
} else { } else {
mimeTypeEndIndex = indexOfZeroByte(data, 0); mimeTypeEndIndex = indexOfZeroByte(data, 0);
mimeType = Util.toLowerInvariant(new String(data, 0, mimeTypeEndIndex, "ISO-8859-1")); mimeType = Ascii.toLowerCase(new String(data, 0, mimeTypeEndIndex, "ISO-8859-1"));
if (mimeType.indexOf('/') == -1) { if (mimeType.indexOf('/') == -1) {
mimeType = "image/" + mimeType; mimeType = "image/" + mimeType;
} }

View file

@ -27,6 +27,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.DataSpec.HttpMethod; import com.google.android.exoplayer2.upstream.DataSpec.HttpMethod;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import java.io.IOException; import java.io.IOException;
@ -339,7 +340,7 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
} catch (IOException e) { } catch (IOException e) {
@Nullable String message = e.getMessage(); @Nullable String message = e.getMessage();
if (message != null if (message != null
&& Util.toLowerInvariant(message).matches("cleartext http traffic.*not permitted.*")) { && Ascii.toLowerCase(message).matches("cleartext http traffic.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec); throw new CleartextNotPermittedException(e, dataSpec);
} }
throw new HttpDataSourceException( throw new HttpDataSourceException(

View file

@ -19,6 +19,7 @@ import android.text.TextUtils;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
@ -182,7 +183,10 @@ public interface HttpDataSource extends DataSource {
/** A {@link Predicate} that rejects content types often used for pay-walls. */ /** A {@link Predicate} that rejects content types often used for pay-walls. */
Predicate<String> REJECT_PAYWALL_TYPES = Predicate<String> REJECT_PAYWALL_TYPES =
contentType -> { contentType -> {
contentType = Util.toLowerInvariant(contentType); if (contentType == null) {
return false;
}
contentType = Ascii.toLowerCase(contentType);
return !TextUtils.isEmpty(contentType) return !TextUtils.isEmpty(contentType)
&& (!contentType.contains("text") || contentType.contains("text/vtt")) && (!contentType.contains("text") || contentType.contains("text/vtt"))
&& !contentType.contains("html") && !contentType.contains("html")

View file

@ -20,6 +20,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.audio.AacUtil; import com.google.android.exoplayer2.audio.AacUtil;
import com.google.common.base.Ascii;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -340,7 +341,7 @@ public final class MimeTypes {
if (codec == null) { if (codec == null) {
return null; return null;
} }
codec = Util.toLowerInvariant(codec.trim()); codec = Ascii.toLowerCase(codec.trim());
if (codec.startsWith("avc1") || codec.startsWith("avc3")) { if (codec.startsWith("avc1") || codec.startsWith("avc3")) {
return MimeTypes.VIDEO_H264; return MimeTypes.VIDEO_H264;
} else if (codec.startsWith("hev1") || codec.startsWith("hvc1")) { } else if (codec.startsWith("hev1") || codec.startsWith("hvc1")) {

View file

@ -674,7 +674,7 @@ public final class Util {
// Tag isn't valid, keep using the original. // Tag isn't valid, keep using the original.
normalizedTag = language; normalizedTag = language;
} }
normalizedTag = Util.toLowerInvariant(normalizedTag); normalizedTag = Ascii.toLowerCase(normalizedTag);
String mainLanguage = Util.splitAtFirst(normalizedTag, "-")[0]; String mainLanguage = Util.splitAtFirst(normalizedTag, "-")[0];
if (languageTagReplacementMap == null) { if (languageTagReplacementMap == null) {
languageTagReplacementMap = createIsoLanguageReplacementMap(); languageTagReplacementMap = createIsoLanguageReplacementMap();
@ -760,16 +760,6 @@ public final class Util {
return c == '\n' || c == '\r'; return c == '\n' || c == '\r';
} }
/**
* Converts text to lower case using {@link Locale#US}.
*
* @param text The text to convert.
* @return The lower case text, or null if {@code text} is null.
*/
public static @PolyNull String toLowerInvariant(@PolyNull String text) {
return text == null ? text : text.toLowerCase(Locale.US);
}
/** /**
* Converts text to upper case using {@link Locale#US}. * Converts text to upper case using {@link Locale#US}.
* *
@ -1784,7 +1774,7 @@ public final class Util {
* @return The derived {@link UUID}, or {@code null} if one could not be derived. * @return The derived {@link UUID}, or {@code null} if one could not be derived.
*/ */
public static @Nullable UUID getDrmUuid(String drmScheme) { public static @Nullable UUID getDrmUuid(String drmScheme) {
switch (toLowerInvariant(drmScheme)) { switch (Ascii.toLowerCase(drmScheme)) {
case "widevine": case "widevine":
return C.WIDEVINE_UUID; return C.WIDEVINE_UUID;
case "playready": case "playready":
@ -1834,7 +1824,7 @@ public final class Util {
*/ */
@ContentType @ContentType
public static int inferContentType(String fileName) { public static int inferContentType(String fileName) {
fileName = toLowerInvariant(fileName); fileName = Ascii.toLowerCase(fileName);
if (fileName.endsWith(".mpd")) { if (fileName.endsWith(".mpd")) {
return C.TYPE_DASH; return C.TYPE_DASH;
} else if (fileName.endsWith(".m3u8")) { } else if (fileName.endsWith(".m3u8")) {
@ -1907,11 +1897,11 @@ public final class Util {
* @return The fixed URI. * @return The fixed URI.
*/ */
public static Uri fixSmoothStreamingIsmManifestUri(Uri uri) { public static Uri fixSmoothStreamingIsmManifestUri(Uri uri) {
@Nullable String path = toLowerInvariant(uri.getPath()); @Nullable String path = uri.getPath();
if (path == null) { if (path == null) {
return uri; return uri;
} }
Matcher ismMatcher = ISM_URL_PATTERN.matcher(path); Matcher ismMatcher = ISM_URL_PATTERN.matcher(Ascii.toLowerCase(path));
if (ismMatcher.matches() && ismMatcher.group(1) == null) { if (ismMatcher.matches() && ismMatcher.group(1) == null) {
// Add missing "Manifest" suffix. // Add missing "Manifest" suffix.
return Uri.withAppendedPath(uri, "Manifest"); return Uri.withAppendedPath(uri, "Manifest");

View file

@ -30,6 +30,7 @@ import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.decoder.CryptoInfo; import com.google.android.exoplayer2.decoder.CryptoInfo;
import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -303,7 +304,7 @@ class AsynchronousMediaCodecBufferEnqueuer {
* buffers (see [Internal: b/149908061]). * buffers (see [Internal: b/149908061]).
*/ */
private static boolean needsSynchronizationWorkaround() { private static boolean needsSynchronizationWorkaround() {
String manufacturer = Util.toLowerInvariant(Util.MANUFACTURER); String manufacturer = Ascii.toLowerCase(Util.MANUFACTURER);
return manufacturer.contains("samsung") || manufacturer.contains("motorola"); return manufacturer.contains("samsung") || manufacturer.contains("motorola");
} }

View file

@ -33,6 +33,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo; import com.google.android.exoplayer2.video.ColorInfo;
import com.google.common.base.Ascii;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -624,7 +625,7 @@ public final class MediaCodecUtil {
if (Util.SDK_INT >= 29) { if (Util.SDK_INT >= 29) {
return isSoftwareOnlyV29(codecInfo); return isSoftwareOnlyV29(codecInfo);
} }
String codecName = Util.toLowerInvariant(codecInfo.getName()); String codecName = Ascii.toLowerCase(codecInfo.getName());
if (codecName.startsWith("arc.")) { // App Runtime for Chrome (ARC) codecs if (codecName.startsWith("arc.")) { // App Runtime for Chrome (ARC) codecs
return false; return false;
} }
@ -650,7 +651,7 @@ public final class MediaCodecUtil {
if (Util.SDK_INT >= 29) { if (Util.SDK_INT >= 29) {
return isVendorV29(codecInfo); return isVendorV29(codecInfo);
} }
String codecName = Util.toLowerInvariant(codecInfo.getName()); String codecName = Ascii.toLowerCase(codecInfo.getName());
return !codecName.startsWith("omx.google.") return !codecName.startsWith("omx.google.")
&& !codecName.startsWith("c2.android.") && !codecName.startsWith("c2.android.")
&& !codecName.startsWith("c2.google."); && !codecName.startsWith("c2.google.");

View file

@ -19,7 +19,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer; import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.metadata.SimpleMetadataDecoder; import com.google.android.exoplayer2.metadata.SimpleMetadataDecoder;
import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException; import java.nio.charset.CharacterCodingException;
@ -57,10 +57,10 @@ public final class IcyDecoder extends SimpleMetadataDecoder {
int index = 0; int index = 0;
Matcher matcher = METADATA_ELEMENT.matcher(icyString); Matcher matcher = METADATA_ELEMENT.matcher(icyString);
while (matcher.find(index)) { while (matcher.find(index)) {
@Nullable String key = Util.toLowerInvariant(matcher.group(1)); @Nullable String key = matcher.group(1);
@Nullable String value = matcher.group(2); @Nullable String value = matcher.group(2);
if (key != null) { if (key != null) {
switch (key) { switch (Ascii.toLowerCase(key)) {
case STREAM_KEY_NAME: case STREAM_KEY_NAME:
name = value; name = value;
break; break;

View file

@ -32,6 +32,7 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -154,7 +155,7 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
if (infoNameAndValue.length != 2) { if (infoNameAndValue.length != 2) {
continue; continue;
} }
switch (Util.toLowerInvariant(infoNameAndValue[0].trim())) { switch (Ascii.toLowerCase(infoNameAndValue[0].trim())) {
case "playresx": case "playresx":
try { try {
screenWidth = Float.parseFloat(infoNameAndValue[1].trim()); screenWidth = Float.parseFloat(infoNameAndValue[1].trim());

View file

@ -22,7 +22,7 @@ import android.text.TextUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii;
/** /**
* Represents a {@code Format:} line from the {@code [Events]} section * Represents a {@code Format:} line from the {@code [Events]} section
@ -61,7 +61,7 @@ import com.google.android.exoplayer2.util.Util;
Assertions.checkArgument(formatLine.startsWith(FORMAT_LINE_PREFIX)); Assertions.checkArgument(formatLine.startsWith(FORMAT_LINE_PREFIX));
String[] keys = TextUtils.split(formatLine.substring(FORMAT_LINE_PREFIX.length()), ","); String[] keys = TextUtils.split(formatLine.substring(FORMAT_LINE_PREFIX.length()), ",");
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
switch (Util.toLowerInvariant(keys[i].trim())) { switch (Ascii.toLowerCase(keys[i].trim())) {
case "start": case "start":
startTimeIndex = i; startTimeIndex = i;
break; break;

View file

@ -31,6 +31,7 @@ import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -284,7 +285,7 @@ import java.util.regex.Pattern;
String[] keys = String[] keys =
TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ","); TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ",");
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
switch (Util.toLowerInvariant(keys[i].trim())) { switch (Ascii.toLowerCase(keys[i].trim())) {
case "name": case "name":
nameIndex = i; nameIndex = i;
break; break;

View file

@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.span.TextAnnotation; import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.text.span.TextEmphasisSpan; import com.google.android.exoplayer2.text.span.TextEmphasisSpan;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -131,7 +132,7 @@ import java.util.regex.Pattern;
return null; return null;
} }
String parsingValue = value.trim(); String parsingValue = Ascii.toLowerCase(value.trim());
if (parsingValue.isEmpty()) { if (parsingValue.isEmpty()) {
return null; return null;
} }

View file

@ -31,6 +31,7 @@ import com.google.android.exoplayer2.util.ColorParser;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.XmlPullParserUtil; import com.google.android.exoplayer2.util.XmlPullParserUtil;
import com.google.common.base.Ascii;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -432,7 +433,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
String displayAlign = String displayAlign =
XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_DISPLAY_ALIGN); XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_DISPLAY_ALIGN);
if (displayAlign != null) { if (displayAlign != null) {
switch (Util.toLowerInvariant(displayAlign)) { switch (Ascii.toLowerCase(displayAlign)) {
case "center": case "center":
lineAnchor = Cue.ANCHOR_TYPE_MIDDLE; lineAnchor = Cue.ANCHOR_TYPE_MIDDLE;
line += height / 2; line += height / 2;
@ -454,7 +455,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
String writingDirection = String writingDirection =
XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_WRITING_MODE); XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_WRITING_MODE);
if (writingDirection != null) { if (writingDirection != null) {
switch (Util.toLowerInvariant(writingDirection)) { switch (Ascii.toLowerCase(writingDirection)) {
// TODO: Support horizontal RTL modes. // TODO: Support horizontal RTL modes.
case TtmlNode.VERTICAL: case TtmlNode.VERTICAL:
case TtmlNode.VERTICAL_LR: case TtmlNode.VERTICAL_LR:
@ -533,7 +534,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
TtmlNode.ITALIC.equalsIgnoreCase(attributeValue)); TtmlNode.ITALIC.equalsIgnoreCase(attributeValue));
break; break;
case TtmlNode.ATTR_TTS_TEXT_ALIGN: case TtmlNode.ATTR_TTS_TEXT_ALIGN:
switch (Util.toLowerInvariant(attributeValue)) { switch (Ascii.toLowerCase(attributeValue)) {
case TtmlNode.LEFT: case TtmlNode.LEFT:
case TtmlNode.START: case TtmlNode.START:
style = createIfNull(style).setTextAlign(Layout.Alignment.ALIGN_NORMAL); style = createIfNull(style).setTextAlign(Layout.Alignment.ALIGN_NORMAL);
@ -551,7 +552,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
break; break;
case TtmlNode.ATTR_TTS_TEXT_COMBINE: case TtmlNode.ATTR_TTS_TEXT_COMBINE:
switch (Util.toLowerInvariant(attributeValue)) { switch (Ascii.toLowerCase(attributeValue)) {
case TtmlNode.COMBINE_NONE: case TtmlNode.COMBINE_NONE:
style = createIfNull(style).setTextCombine(false); style = createIfNull(style).setTextCombine(false);
break; break;
@ -564,7 +565,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
break; break;
case TtmlNode.ATTR_TTS_RUBY: case TtmlNode.ATTR_TTS_RUBY:
switch (Util.toLowerInvariant(attributeValue)) { switch (Ascii.toLowerCase(attributeValue)) {
case TtmlNode.RUBY_CONTAINER: case TtmlNode.RUBY_CONTAINER:
style = createIfNull(style).setRubyType(TtmlStyle.RUBY_TYPE_CONTAINER); style = createIfNull(style).setRubyType(TtmlStyle.RUBY_TYPE_CONTAINER);
break; break;
@ -585,7 +586,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
break; break;
case TtmlNode.ATTR_TTS_RUBY_POSITION: case TtmlNode.ATTR_TTS_RUBY_POSITION:
switch (Util.toLowerInvariant(attributeValue)) { switch (Ascii.toLowerCase(attributeValue)) {
case TtmlNode.ANNOTATION_POSITION_BEFORE: case TtmlNode.ANNOTATION_POSITION_BEFORE:
style = createIfNull(style).setRubyPosition(TextAnnotation.POSITION_BEFORE); style = createIfNull(style).setRubyPosition(TextAnnotation.POSITION_BEFORE);
break; break;
@ -598,7 +599,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
break; break;
case TtmlNode.ATTR_TTS_TEXT_DECORATION: case TtmlNode.ATTR_TTS_TEXT_DECORATION:
switch (Util.toLowerInvariant(attributeValue)) { switch (Ascii.toLowerCase(attributeValue)) {
case TtmlNode.LINETHROUGH: case TtmlNode.LINETHROUGH:
style = createIfNull(style).setLinethrough(true); style = createIfNull(style).setLinethrough(true);
break; break;
@ -614,9 +615,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
} }
break; break;
case TtmlNode.ATTR_TTS_TEXT_EMPHASIS: case TtmlNode.ATTR_TTS_TEXT_EMPHASIS:
style = style = createIfNull(style).setTextEmphasis(TextEmphasis.parse(attributeValue));
createIfNull(style)
.setTextEmphasis(TextEmphasis.parse(Util.toLowerInvariant(attributeValue)));
break; break;
case TtmlNode.ATTR_TTS_SHEAR: case TtmlNode.ATTR_TTS_SHEAR:
style = createIfNull(style).setShearPercentage(parseShear(attributeValue)); style = createIfNull(style).setShearPercentage(parseShear(attributeValue));

View file

@ -21,7 +21,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.text.span.TextAnnotation; import com.google.android.exoplayer2.text.span.TextAnnotation;
import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -216,7 +216,7 @@ public final class WebvttCssStyle {
} }
public WebvttCssStyle setFontFamily(@Nullable String fontFamily) { public WebvttCssStyle setFontFamily(@Nullable String fontFamily) {
this.fontFamily = Util.toLowerInvariant(fontFamily); this.fontFamily = fontFamily == null ? null : Ascii.toLowerCase(fontFamily);
return this; return this;
} }

View file

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.util;
import android.graphics.Color; import android.graphics.Color;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import com.google.common.base.Ascii;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -106,7 +107,7 @@ public final class ColorParser {
} }
} else { } else {
// we use our own color map // we use our own color map
Integer color = COLOR_MAP.get(Util.toLowerInvariant(colorExpression)); Integer color = COLOR_MAP.get(Ascii.toLowerCase(colorExpression));
if (color != null) { if (color != null) {
return color; return color;
} }

View file

@ -549,7 +549,7 @@ public class DashManifestParser extends DefaultHandler
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri"); String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
if (schemeIdUri != null) { if (schemeIdUri != null) {
switch (Util.toLowerInvariant(schemeIdUri)) { switch (Ascii.toLowerCase(schemeIdUri)) {
case "urn:mpeg:dash:mp4protection:2011": case "urn:mpeg:dash:mp4protection:2011":
schemeType = xpp.getAttributeValue(null, "value"); schemeType = xpp.getAttributeValue(null, "value");
String defaultKid = XmlPullParserUtil.getAttributeValueIgnorePrefix(xpp, "default_KID"); String defaultKid = XmlPullParserUtil.getAttributeValueIgnorePrefix(xpp, "default_KID");
@ -1798,11 +1798,11 @@ public class DashManifestParser extends DefaultHandler
* not be parsed. * not be parsed.
*/ */
protected static int parseDolbyChannelConfiguration(XmlPullParser xpp) { protected static int parseDolbyChannelConfiguration(XmlPullParser xpp) {
String value = Util.toLowerInvariant(xpp.getAttributeValue(null, "value")); @Nullable String value = xpp.getAttributeValue(null, "value");
if (value == null) { if (value == null) {
return Format.NO_VALUE; return Format.NO_VALUE;
} }
switch (value) { switch (Ascii.toLowerCase(value)) {
case "4000": case "4000":
return 1; return 1;
case "a000": case "a000":

View file

@ -36,6 +36,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster; import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.UriUtil; import com.google.android.exoplayer2.util.UriUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
@ -540,7 +541,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private static byte[] getEncryptionIvArray(String ivString) { private static byte[] getEncryptionIvArray(String ivString) {
String trimmedIv; String trimmedIv;
if (Util.toLowerInvariant(ivString).startsWith("0x")) { if (Ascii.toLowerCase(ivString).startsWith("0x")) {
trimmedIv = ivString.substring(2); trimmedIv = ivString.substring(2);
} else { } else {
trimmedIv = ivString; trimmedIv = ivString;