From 1e2e225c010f921a678be08a6bbc02d0b0e88b3e Mon Sep 17 00:00:00 2001 From: rohks Date: Fri, 11 Aug 2023 12:27:08 +0000 Subject: [PATCH] Refactor CMCD headers construction for efficiency and readability Optimises the construction of Common Media Client Data (CMCD) headers by eliminating the use of trailing commas. Instead of appending values directly to a StringBuilder, it now adds values to a list and joins them using a comma separator. While the primary focus is on enhancing readability and robustness, it's worth noting that in certain instances, removing usages of `formatInvariant`, there are also performance improvements. PiperOrigin-RevId: 555911498 --- .../upstream/CmcdHeadersFactory.java | 110 +++++++----------- 1 file changed, 45 insertions(+), 65 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/CmcdHeadersFactory.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/CmcdHeadersFactory.java index b29bf5c4c3..d09f52983f 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/CmcdHeadersFactory.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/upstream/CmcdHeadersFactory.java @@ -29,12 +29,14 @@ import androidx.media3.common.TrackGroup; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.exoplayer.trackselection.ExoTrackSelection; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; /** * This class serves as a factory for generating Common Media Client Data (CMCD) HTTP request @@ -47,6 +49,8 @@ import java.lang.annotation.Target; @UnstableApi public final class CmcdHeadersFactory { + private static final Joiner COMMA_JOINER = Joiner.on(","); + /** * Retrieves the object type value from the given {@link ExoTrackSelection}. * @@ -426,34 +430,27 @@ public final class CmcdHeadersFactory { */ public void populateHttpRequestHeaders( ImmutableMap.Builder<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders) { - StringBuilder headerValue = new StringBuilder(); + ArrayList headerValueList = new ArrayList<>(); if (bitrateKbps != C.RATE_UNSET_INT) { - headerValue.append( - Util.formatInvariant("%s=%d,", CmcdConfiguration.KEY_BITRATE, bitrateKbps)); + headerValueList.add(CmcdConfiguration.KEY_BITRATE + "=" + bitrateKbps); } if (topBitrateKbps != C.RATE_UNSET_INT) { - headerValue.append( - Util.formatInvariant("%s=%d,", CmcdConfiguration.KEY_TOP_BITRATE, topBitrateKbps)); + headerValueList.add(CmcdConfiguration.KEY_TOP_BITRATE + "=" + topBitrateKbps); } if (objectDurationMs != C.TIME_UNSET) { - headerValue.append( - Util.formatInvariant( - "%s=%d,", CmcdConfiguration.KEY_OBJECT_DURATION, objectDurationMs)); + headerValueList.add(CmcdConfiguration.KEY_OBJECT_DURATION + "=" + objectDurationMs); } if (!TextUtils.isEmpty(objectType)) { - headerValue.append( - Util.formatInvariant("%s=%s,", CmcdConfiguration.KEY_OBJECT_TYPE, objectType)); + headerValueList.add(CmcdConfiguration.KEY_OBJECT_TYPE + "=" + objectType); } if (!TextUtils.isEmpty(customData)) { - headerValue.append(Util.formatInvariant("%s,", customData)); + headerValueList.add(customData); } - if (headerValue.length() == 0) { - return; + if (!headerValueList.isEmpty()) { + httpRequestHeaders.put( + CmcdConfiguration.KEY_CMCD_OBJECT, COMMA_JOINER.join(headerValueList)); } - // Remove the trailing comma as headerValue is not empty - headerValue.setLength(headerValue.length() - 1); - httpRequestHeaders.put(CmcdConfiguration.KEY_CMCD_OBJECT, headerValue.toString()); } } @@ -606,36 +603,28 @@ public final class CmcdHeadersFactory { */ public void populateHttpRequestHeaders( ImmutableMap.Builder<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders) { - StringBuilder headerValue = new StringBuilder(); + ArrayList headerValueList = new ArrayList<>(); if (bufferLengthMs != C.TIME_UNSET) { - headerValue.append( - Util.formatInvariant("%s=%d,", CmcdConfiguration.KEY_BUFFER_LENGTH, bufferLengthMs)); + headerValueList.add(CmcdConfiguration.KEY_BUFFER_LENGTH + "=" + bufferLengthMs); } if (measuredThroughputInKbps != Long.MIN_VALUE) { - headerValue.append( - Util.formatInvariant( - "%s=%d,", CmcdConfiguration.KEY_MEASURED_THROUGHPUT, measuredThroughputInKbps)); + headerValueList.add( + CmcdConfiguration.KEY_MEASURED_THROUGHPUT + "=" + measuredThroughputInKbps); } if (deadlineMs != C.TIME_UNSET) { - headerValue - .append(CmcdConfiguration.KEY_DEADLINE) - .append("=") - .append(deadlineMs) - .append(","); + headerValueList.add(CmcdConfiguration.KEY_DEADLINE + "=" + deadlineMs); } if (startup) { - headerValue.append(CmcdConfiguration.KEY_STARTUP).append(","); + headerValueList.add(CmcdConfiguration.KEY_STARTUP); } if (!TextUtils.isEmpty(customData)) { - headerValue.append(Util.formatInvariant("%s,", customData)); + headerValueList.add(customData); } - if (headerValue.length() == 0) { - return; + if (!headerValueList.isEmpty()) { + httpRequestHeaders.put( + CmcdConfiguration.KEY_CMCD_REQUEST, COMMA_JOINER.join(headerValueList)); } - // Remove the trailing comma as headerValue is not empty - headerValue.setLength(headerValue.length() - 1); - httpRequestHeaders.put(CmcdConfiguration.KEY_CMCD_REQUEST, headerValue.toString()); } } @@ -788,41 +777,36 @@ public final class CmcdHeadersFactory { */ public void populateHttpRequestHeaders( ImmutableMap.Builder<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders) { - StringBuilder headerValue = new StringBuilder(); + ArrayList headerValueList = new ArrayList<>(); if (!TextUtils.isEmpty(this.contentId)) { - headerValue.append( - Util.formatInvariant("%s=\"%s\",", CmcdConfiguration.KEY_CONTENT_ID, contentId)); + headerValueList.add( + Util.formatInvariant("%s=\"%s\"", CmcdConfiguration.KEY_CONTENT_ID, contentId)); } if (!TextUtils.isEmpty(this.sessionId)) { - headerValue.append( - Util.formatInvariant("%s=\"%s\",", CmcdConfiguration.KEY_SESSION_ID, sessionId)); + headerValueList.add( + Util.formatInvariant("%s=\"%s\"", CmcdConfiguration.KEY_SESSION_ID, sessionId)); } if (!TextUtils.isEmpty(this.streamingFormat)) { - headerValue.append( - Util.formatInvariant( - "%s=%s,", CmcdConfiguration.KEY_STREAMING_FORMAT, streamingFormat)); + headerValueList.add(CmcdConfiguration.KEY_STREAMING_FORMAT + "=" + streamingFormat); } if (!TextUtils.isEmpty(this.streamType)) { - headerValue.append( - Util.formatInvariant("%s=%s,", CmcdConfiguration.KEY_STREAM_TYPE, streamType)); + headerValueList.add(CmcdConfiguration.KEY_STREAM_TYPE + "=" + streamType); } if (playbackRate != C.RATE_UNSET && playbackRate != 1.0f) { - headerValue.append( - Util.formatInvariant("%s=%.2f,", CmcdConfiguration.KEY_PLAYBACK_RATE, playbackRate)); + headerValueList.add( + Util.formatInvariant("%s=%.2f", CmcdConfiguration.KEY_PLAYBACK_RATE, playbackRate)); } if (VERSION != 1) { - headerValue.append(Util.formatInvariant("%s=%d,", CmcdConfiguration.KEY_VERSION, VERSION)); + headerValueList.add(CmcdConfiguration.KEY_VERSION + "=" + VERSION); } if (!TextUtils.isEmpty(customData)) { - headerValue.append(Util.formatInvariant("%s,", customData)); + headerValueList.add(customData); } - if (headerValue.length() == 0) { - return; + if (!headerValueList.isEmpty()) { + httpRequestHeaders.put( + CmcdConfiguration.KEY_CMCD_SESSION, COMMA_JOINER.join(headerValueList)); } - // Remove the trailing comma as headerValue is not empty - headerValue.setLength(headerValue.length() - 1); - httpRequestHeaders.put(CmcdConfiguration.KEY_CMCD_SESSION, headerValue.toString()); } } @@ -920,26 +904,22 @@ public final class CmcdHeadersFactory { */ public void populateHttpRequestHeaders( ImmutableMap.Builder<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders) { - StringBuilder headerValue = new StringBuilder(); + ArrayList headerValueList = new ArrayList<>(); if (maximumRequestedThroughputKbps != C.RATE_UNSET_INT) { - headerValue.append( - Util.formatInvariant( - "%s=%d,", - CmcdConfiguration.KEY_MAXIMUM_REQUESTED_BITRATE, maximumRequestedThroughputKbps)); + headerValueList.add( + CmcdConfiguration.KEY_MAXIMUM_REQUESTED_BITRATE + "=" + maximumRequestedThroughputKbps); } if (bufferStarvation) { - headerValue.append(CmcdConfiguration.KEY_BUFFER_STARVATION).append(","); + headerValueList.add(CmcdConfiguration.KEY_BUFFER_STARVATION); } if (!TextUtils.isEmpty(customData)) { - headerValue.append(Util.formatInvariant("%s,", customData)); + headerValueList.add(customData); } - if (headerValue.length() == 0) { - return; + if (!headerValueList.isEmpty()) { + httpRequestHeaders.put( + CmcdConfiguration.KEY_CMCD_STATUS, COMMA_JOINER.join(headerValueList)); } - // Remove the trailing comma as headerValue is not empty - headerValue.setLength(headerValue.length() - 1); - httpRequestHeaders.put(CmcdConfiguration.KEY_CMCD_STATUS, headerValue.toString()); } } }