Update initial bandwidth estimates.

Also include 5G-NSA estimates and update code to use immutable
structures to prevent external updates by the app.

PiperOrigin-RevId: 325196303
This commit is contained in:
tonihei 2020-08-06 11:17:44 +01:00 committed by kim-vde
parent 8661876960
commit 94fb9adec1

View File

@ -22,7 +22,6 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseArray;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.BandwidthMeter.EventListener.EventDispatcher;
@ -30,10 +29,13 @@ import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.SlidingPercentile;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -49,26 +51,30 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
/**
* Country groups used to determine the default initial bitrate estimate. The group assignment for
* each country is an array of group indices for [Wifi, 2G, 3G, 4G].
* each country is a list for [Wifi, 2G, 3G, 4G, 5G_NSA].
*/
public static final Map<String, int[]> DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS =
createInitialBitrateCountryGroupAssignment();
public static final ImmutableListMultimap<String, Integer>
DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS = createInitialBitrateCountryGroupAssignment();
/** Default initial Wifi bitrate estimate in bits per second. */
public static final long[] DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI =
new long[] {5_800_000, 3_500_000, 1_900_000, 1_000_000, 520_000};
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI =
ImmutableList.of(6_100_000L, 3_800_000L, 2_100_000L, 1_300_000L, 590_000L);
/** Default initial 2G bitrate estimates in bits per second. */
public static final long[] DEFAULT_INITIAL_BITRATE_ESTIMATES_2G =
new long[] {204_000, 154_000, 139_000, 122_000, 102_000};
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_2G =
ImmutableList.of(218_000L, 159_000L, 145_000L, 130_000L, 112_000L);
/** Default initial 3G bitrate estimates in bits per second. */
public static final long[] DEFAULT_INITIAL_BITRATE_ESTIMATES_3G =
new long[] {2_200_000, 1_150_000, 810_000, 640_000, 450_000};
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_3G =
ImmutableList.of(2_200_000L, 1_300_000L, 930_000L, 730_000L, 530_000L);
/** Default initial 4G bitrate estimates in bits per second. */
public static final long[] DEFAULT_INITIAL_BITRATE_ESTIMATES_4G =
new long[] {4_900_000, 2_300_000, 1_500_000, 970_000, 540_000};
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_4G =
ImmutableList.of(4_800_000L, 2_700_000L, 1_800_000L, 1_200_000L, 630_000L);
/** Default initial 5G-NSA bitrate estimates in bits per second. */
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA =
ImmutableList.of(12_000_000L, 8_800_000L, 5_900_000L, 3_500_000L, 1_800_000L);
/**
* Default initial bitrate estimate used when the device is offline or the network type cannot be
@ -87,6 +93,8 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
private static final int COUNTRY_GROUP_INDEX_3G = 2;
/** Index for the 4G group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
private static final int COUNTRY_GROUP_INDEX_4G = 3;
/** Index for the 5G-NSA group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
private static final int COUNTRY_GROUP_INDEX_5G_NSA = 4;
@Nullable private static DefaultBandwidthMeter singletonInstance;
@ -95,7 +103,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
@Nullable private final Context context;
private SparseArray<Long> initialBitrateEstimates;
private Map<Integer, Long> initialBitrateEstimates;
private int slidingWindowMaxWeight;
private Clock clock;
private boolean resetOnNetworkTypeChange;
@ -133,8 +141,8 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
* @return This builder.
*/
public Builder setInitialBitrateEstimate(long initialBitrateEstimate) {
for (int i = 0; i < initialBitrateEstimates.size(); i++) {
initialBitrateEstimates.setValueAt(i, initialBitrateEstimate);
for (Integer networkType : initialBitrateEstimates.keySet()) {
setInitialBitrateEstimate(networkType, initialBitrateEstimate);
}
return this;
}
@ -204,37 +212,37 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
resetOnNetworkTypeChange);
}
private static SparseArray<Long> getInitialBitrateEstimatesForCountry(String countryCode) {
int[] groupIndices = getCountryGroupIndices(countryCode);
SparseArray<Long> result = new SparseArray<>(/* initialCapacity= */ 6);
result.append(C.NETWORK_TYPE_UNKNOWN, DEFAULT_INITIAL_BITRATE_ESTIMATE);
result.append(
private static Map<Integer, Long> getInitialBitrateEstimatesForCountry(String countryCode) {
List<Integer> groupIndices = getCountryGroupIndices(countryCode);
Map<Integer, Long> result = new HashMap<>(/* initialCapacity= */ 6);
result.put(C.NETWORK_TYPE_UNKNOWN, DEFAULT_INITIAL_BITRATE_ESTIMATE);
result.put(
C.NETWORK_TYPE_WIFI,
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI[groupIndices[COUNTRY_GROUP_INDEX_WIFI]]);
result.append(
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices.get(COUNTRY_GROUP_INDEX_WIFI)));
result.put(
C.NETWORK_TYPE_2G,
DEFAULT_INITIAL_BITRATE_ESTIMATES_2G[groupIndices[COUNTRY_GROUP_INDEX_2G]]);
result.append(
DEFAULT_INITIAL_BITRATE_ESTIMATES_2G.get(groupIndices.get(COUNTRY_GROUP_INDEX_2G)));
result.put(
C.NETWORK_TYPE_3G,
DEFAULT_INITIAL_BITRATE_ESTIMATES_3G[groupIndices[COUNTRY_GROUP_INDEX_3G]]);
result.append(
DEFAULT_INITIAL_BITRATE_ESTIMATES_3G.get(groupIndices.get(COUNTRY_GROUP_INDEX_3G)));
result.put(
C.NETWORK_TYPE_4G,
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G[groupIndices[COUNTRY_GROUP_INDEX_4G]]);
// Assume default Wifi and 4G bitrate for Ethernet and 5G, respectively, to prevent using the
// slower fallback.
result.append(
C.NETWORK_TYPE_ETHERNET,
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI[groupIndices[COUNTRY_GROUP_INDEX_WIFI]]);
result.append(
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G.get(groupIndices.get(COUNTRY_GROUP_INDEX_4G)));
result.put(
C.NETWORK_TYPE_5G,
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G[groupIndices[COUNTRY_GROUP_INDEX_4G]]);
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA.get(
groupIndices.get(COUNTRY_GROUP_INDEX_5G_NSA)));
// Assume default Wifi speed for Ethernet to prevent using the slower fallback.
result.put(
C.NETWORK_TYPE_ETHERNET,
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices.get(COUNTRY_GROUP_INDEX_WIFI)));
return result;
}
private static int[] getCountryGroupIndices(String countryCode) {
@Nullable int[] groupIndices = DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS.get(countryCode);
private static ImmutableList<Integer> getCountryGroupIndices(String countryCode) {
ImmutableList<Integer> groupIndices = DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS.get(countryCode);
// Assume median group if not found.
return groupIndices == null ? new int[] {2, 2, 2, 2} : groupIndices;
return groupIndices.isEmpty() ? ImmutableList.of(2, 2, 2, 2, 2) : groupIndices;
}
}
@ -255,7 +263,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
private static final int BYTES_TRANSFERRED_FOR_ESTIMATE = 512 * 1024;
@Nullable private final Context context;
private final SparseArray<Long> initialBitrateEstimates;
private final ImmutableMap<Integer, Long> initialBitrateEstimates;
private final EventDispatcher eventDispatcher;
private final SlidingPercentile slidingPercentile;
private final Clock clock;
@ -278,7 +286,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
public DefaultBandwidthMeter() {
this(
/* context= */ null,
/* initialBitrateEstimates= */ new SparseArray<>(),
/* initialBitrateEstimates= */ ImmutableMap.of(),
DEFAULT_SLIDING_WINDOW_MAX_WEIGHT,
Clock.DEFAULT,
/* resetOnNetworkTypeChange= */ false);
@ -286,12 +294,12 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
private DefaultBandwidthMeter(
@Nullable Context context,
SparseArray<Long> initialBitrateEstimates,
Map<Integer, Long> initialBitrateEstimates,
int maxWeight,
Clock clock,
boolean resetOnNetworkTypeChange) {
this.context = context == null ? null : context.getApplicationContext();
this.initialBitrateEstimates = initialBitrateEstimates;
this.initialBitrateEstimates = ImmutableMap.copyOf(initialBitrateEstimates);
this.eventDispatcher = new EventDispatcher();
this.slidingPercentile = new SlidingPercentile(maxWeight);
this.clock = clock;
@ -511,247 +519,248 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
}
}
private static Map<String, int[]> createInitialBitrateCountryGroupAssignment() {
HashMap<String, int[]> countryGroupAssignment = new HashMap<>();
countryGroupAssignment.put("AD", new int[] {0, 2, 0, 0});
countryGroupAssignment.put("AE", new int[] {2, 4, 4, 4});
countryGroupAssignment.put("AF", new int[] {4, 4, 3, 3});
countryGroupAssignment.put("AG", new int[] {4, 2, 2, 3});
countryGroupAssignment.put("AI", new int[] {0, 3, 2, 4});
countryGroupAssignment.put("AL", new int[] {1, 2, 0, 1});
countryGroupAssignment.put("AM", new int[] {2, 2, 1, 2});
countryGroupAssignment.put("AO", new int[] {3, 4, 3, 1});
countryGroupAssignment.put("AQ", new int[] {4, 2, 2, 2});
countryGroupAssignment.put("AR", new int[] {2, 3, 1, 2});
countryGroupAssignment.put("AS", new int[] {2, 2, 4, 2});
countryGroupAssignment.put("AT", new int[] {0, 3, 0, 0});
countryGroupAssignment.put("AU", new int[] {0, 2, 0, 1});
countryGroupAssignment.put("AW", new int[] {1, 1, 2, 4});
countryGroupAssignment.put("AX", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("AZ", new int[] {3, 3, 3, 3});
countryGroupAssignment.put("BA", new int[] {1, 1, 0, 1});
countryGroupAssignment.put("BB", new int[] {0, 3, 0, 0});
countryGroupAssignment.put("BD", new int[] {2, 0, 4, 3});
countryGroupAssignment.put("BE", new int[] {0, 1, 2, 3});
countryGroupAssignment.put("BF", new int[] {4, 4, 4, 1});
countryGroupAssignment.put("BG", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("BH", new int[] {1, 0, 3, 4});
countryGroupAssignment.put("BI", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("BJ", new int[] {4, 4, 3, 4});
countryGroupAssignment.put("BL", new int[] {1, 0, 4, 3});
countryGroupAssignment.put("BM", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("BN", new int[] {4, 0, 2, 4});
countryGroupAssignment.put("BO", new int[] {1, 3, 3, 3});
countryGroupAssignment.put("BQ", new int[] {1, 0, 1, 0});
countryGroupAssignment.put("BR", new int[] {2, 4, 3, 1});
countryGroupAssignment.put("BS", new int[] {3, 1, 1, 3});
countryGroupAssignment.put("BT", new int[] {3, 0, 3, 1});
countryGroupAssignment.put("BW", new int[] {3, 4, 3, 3});
countryGroupAssignment.put("BY", new int[] {0, 1, 1, 1});
countryGroupAssignment.put("BZ", new int[] {1, 3, 2, 1});
countryGroupAssignment.put("CA", new int[] {0, 3, 2, 2});
countryGroupAssignment.put("CD", new int[] {3, 4, 2, 2});
countryGroupAssignment.put("CF", new int[] {4, 3, 2, 2});
countryGroupAssignment.put("CG", new int[] {3, 4, 1, 1});
countryGroupAssignment.put("CH", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("CI", new int[] {3, 4, 3, 3});
countryGroupAssignment.put("CK", new int[] {2, 0, 1, 0});
countryGroupAssignment.put("CL", new int[] {1, 2, 2, 3});
countryGroupAssignment.put("CM", new int[] {3, 4, 3, 2});
countryGroupAssignment.put("CN", new int[] {1, 0, 1, 1});
countryGroupAssignment.put("CO", new int[] {2, 3, 3, 2});
countryGroupAssignment.put("CR", new int[] {2, 2, 4, 4});
countryGroupAssignment.put("CU", new int[] {4, 4, 2, 1});
countryGroupAssignment.put("CV", new int[] {2, 3, 3, 2});
countryGroupAssignment.put("CW", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("CY", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("CZ", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("DE", new int[] {0, 1, 2, 3});
countryGroupAssignment.put("DJ", new int[] {4, 2, 4, 4});
countryGroupAssignment.put("DK", new int[] {0, 0, 1, 0});
countryGroupAssignment.put("DM", new int[] {1, 1, 0, 2});
countryGroupAssignment.put("DO", new int[] {3, 3, 4, 4});
countryGroupAssignment.put("DZ", new int[] {3, 3, 4, 4});
countryGroupAssignment.put("EC", new int[] {2, 3, 4, 2});
countryGroupAssignment.put("EE", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("EG", new int[] {3, 4, 2, 1});
countryGroupAssignment.put("EH", new int[] {2, 0, 3, 1});
countryGroupAssignment.put("ER", new int[] {4, 2, 4, 4});
countryGroupAssignment.put("ES", new int[] {0, 1, 1, 1});
countryGroupAssignment.put("ET", new int[] {4, 4, 4, 1});
countryGroupAssignment.put("FI", new int[] {0, 0, 1, 0});
countryGroupAssignment.put("FJ", new int[] {3, 0, 4, 4});
countryGroupAssignment.put("FK", new int[] {2, 2, 2, 1});
countryGroupAssignment.put("FM", new int[] {3, 2, 4, 1});
countryGroupAssignment.put("FO", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("FR", new int[] {1, 1, 1, 1});
countryGroupAssignment.put("GA", new int[] {3, 2, 2, 2});
countryGroupAssignment.put("GB", new int[] {0, 1, 1, 1});
countryGroupAssignment.put("GD", new int[] {1, 1, 3, 1});
countryGroupAssignment.put("GE", new int[] {1, 0, 1, 4});
countryGroupAssignment.put("GF", new int[] {2, 0, 1, 3});
countryGroupAssignment.put("GG", new int[] {1, 0, 0, 0});
countryGroupAssignment.put("GH", new int[] {3, 3, 3, 3});
countryGroupAssignment.put("GI", new int[] {4, 4, 0, 0});
countryGroupAssignment.put("GL", new int[] {2, 1, 1, 2});
countryGroupAssignment.put("GM", new int[] {4, 3, 2, 4});
countryGroupAssignment.put("GN", new int[] {3, 4, 4, 2});
countryGroupAssignment.put("GP", new int[] {2, 1, 3, 4});
countryGroupAssignment.put("GQ", new int[] {4, 4, 4, 0});
countryGroupAssignment.put("GR", new int[] {1, 1, 0, 1});
countryGroupAssignment.put("GT", new int[] {3, 2, 2, 2});
countryGroupAssignment.put("GU", new int[] {1, 0, 2, 2});
countryGroupAssignment.put("GW", new int[] {3, 4, 4, 3});
countryGroupAssignment.put("GY", new int[] {3, 2, 1, 1});
countryGroupAssignment.put("HK", new int[] {0, 2, 3, 4});
countryGroupAssignment.put("HN", new int[] {3, 1, 3, 3});
countryGroupAssignment.put("HR", new int[] {1, 1, 0, 1});
countryGroupAssignment.put("HT", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("HU", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("ID", new int[] {2, 2, 2, 3});
countryGroupAssignment.put("IE", new int[] {1, 0, 1, 1});
countryGroupAssignment.put("IL", new int[] {1, 0, 2, 3});
countryGroupAssignment.put("IM", new int[] {0, 0, 0, 1});
countryGroupAssignment.put("IN", new int[] {2, 2, 4, 3});
countryGroupAssignment.put("IO", new int[] {4, 4, 2, 3});
countryGroupAssignment.put("IQ", new int[] {3, 3, 4, 2});
countryGroupAssignment.put("IR", new int[] {3, 0, 2, 1});
countryGroupAssignment.put("IS", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("IT", new int[] {1, 1, 1, 2});
countryGroupAssignment.put("JE", new int[] {1, 0, 0, 1});
countryGroupAssignment.put("JM", new int[] {3, 3, 3, 4});
countryGroupAssignment.put("JO", new int[] {1, 2, 1, 1});
countryGroupAssignment.put("JP", new int[] {0, 2, 0, 0});
countryGroupAssignment.put("KE", new int[] {3, 4, 3, 3});
countryGroupAssignment.put("KG", new int[] {2, 0, 2, 2});
countryGroupAssignment.put("KH", new int[] {1, 0, 4, 3});
countryGroupAssignment.put("KI", new int[] {4, 4, 4, 0});
countryGroupAssignment.put("KM", new int[] {4, 3, 2, 4});
countryGroupAssignment.put("KN", new int[] {1, 0, 2, 4});
countryGroupAssignment.put("KP", new int[] {4, 2, 0, 2});
countryGroupAssignment.put("KR", new int[] {0, 1, 0, 1});
countryGroupAssignment.put("KW", new int[] {2, 3, 1, 2});
countryGroupAssignment.put("KY", new int[] {3, 1, 2, 3});
countryGroupAssignment.put("KZ", new int[] {1, 2, 2, 2});
countryGroupAssignment.put("LA", new int[] {2, 2, 1, 1});
countryGroupAssignment.put("LB", new int[] {3, 2, 0, 0});
countryGroupAssignment.put("LC", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("LI", new int[] {0, 0, 1, 1});
countryGroupAssignment.put("LK", new int[] {2, 0, 2, 3});
countryGroupAssignment.put("LR", new int[] {3, 4, 4, 2});
countryGroupAssignment.put("LS", new int[] {3, 3, 2, 2});
countryGroupAssignment.put("LT", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("LU", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("LV", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("LY", new int[] {3, 3, 4, 3});
countryGroupAssignment.put("MA", new int[] {3, 2, 3, 2});
countryGroupAssignment.put("MC", new int[] {0, 4, 0, 0});
countryGroupAssignment.put("MD", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("ME", new int[] {1, 3, 1, 2});
countryGroupAssignment.put("MF", new int[] {2, 3, 1, 1});
countryGroupAssignment.put("MG", new int[] {3, 4, 2, 3});
countryGroupAssignment.put("MH", new int[] {4, 0, 2, 4});
countryGroupAssignment.put("MK", new int[] {1, 0, 0, 0});
countryGroupAssignment.put("ML", new int[] {4, 4, 2, 0});
countryGroupAssignment.put("MM", new int[] {3, 3, 2, 2});
countryGroupAssignment.put("MN", new int[] {2, 3, 1, 1});
countryGroupAssignment.put("MO", new int[] {0, 0, 4, 4});
countryGroupAssignment.put("MP", new int[] {0, 2, 1, 2});
countryGroupAssignment.put("MQ", new int[] {2, 1, 1, 3});
countryGroupAssignment.put("MR", new int[] {4, 2, 4, 4});
countryGroupAssignment.put("MS", new int[] {1, 4, 3, 4});
countryGroupAssignment.put("MT", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("MU", new int[] {2, 2, 4, 4});
countryGroupAssignment.put("MV", new int[] {4, 3, 2, 4});
countryGroupAssignment.put("MW", new int[] {3, 1, 1, 1});
countryGroupAssignment.put("MX", new int[] {2, 4, 3, 3});
countryGroupAssignment.put("MY", new int[] {2, 1, 3, 3});
countryGroupAssignment.put("MZ", new int[] {3, 3, 3, 3});
countryGroupAssignment.put("NA", new int[] {4, 3, 3, 3});
countryGroupAssignment.put("NC", new int[] {2, 0, 4, 4});
countryGroupAssignment.put("NE", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("NF", new int[] {1, 2, 2, 0});
countryGroupAssignment.put("NG", new int[] {3, 3, 2, 2});
countryGroupAssignment.put("NI", new int[] {3, 2, 4, 3});
countryGroupAssignment.put("NL", new int[] {0, 2, 3, 2});
countryGroupAssignment.put("NO", new int[] {0, 2, 1, 0});
countryGroupAssignment.put("NP", new int[] {2, 2, 2, 2});
countryGroupAssignment.put("NR", new int[] {4, 0, 3, 2});
countryGroupAssignment.put("NZ", new int[] {0, 0, 1, 2});
countryGroupAssignment.put("OM", new int[] {2, 3, 0, 2});
countryGroupAssignment.put("PA", new int[] {1, 3, 3, 3});
countryGroupAssignment.put("PE", new int[] {2, 4, 4, 4});
countryGroupAssignment.put("PF", new int[] {2, 1, 1, 1});
countryGroupAssignment.put("PG", new int[] {4, 3, 3, 2});
countryGroupAssignment.put("PH", new int[] {3, 0, 3, 4});
countryGroupAssignment.put("PK", new int[] {3, 2, 3, 2});
countryGroupAssignment.put("PL", new int[] {1, 0, 1, 2});
countryGroupAssignment.put("PM", new int[] {0, 2, 2, 0});
countryGroupAssignment.put("PR", new int[] {2, 2, 2, 2});
countryGroupAssignment.put("PS", new int[] {3, 3, 1, 4});
countryGroupAssignment.put("PT", new int[] {1, 1, 0, 0});
countryGroupAssignment.put("PW", new int[] {1, 1, 3, 0});
countryGroupAssignment.put("PY", new int[] {2, 0, 3, 3});
countryGroupAssignment.put("QA", new int[] {2, 3, 1, 1});
countryGroupAssignment.put("RE", new int[] {1, 0, 2, 2});
countryGroupAssignment.put("RO", new int[] {0, 1, 1, 2});
countryGroupAssignment.put("RS", new int[] {1, 2, 0, 0});
countryGroupAssignment.put("RU", new int[] {0, 1, 0, 1});
countryGroupAssignment.put("RW", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("SA", new int[] {2, 2, 2, 1});
countryGroupAssignment.put("SB", new int[] {4, 4, 4, 1});
countryGroupAssignment.put("SC", new int[] {4, 2, 0, 1});
countryGroupAssignment.put("SD", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("SE", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("SG", new int[] {1, 0, 3, 3});
countryGroupAssignment.put("SH", new int[] {4, 2, 2, 2});
countryGroupAssignment.put("SI", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("SJ", new int[] {2, 2, 2, 4});
countryGroupAssignment.put("SK", new int[] {0, 1, 0, 0});
countryGroupAssignment.put("SL", new int[] {4, 3, 3, 1});
countryGroupAssignment.put("SM", new int[] {0, 0, 1, 2});
countryGroupAssignment.put("SN", new int[] {4, 4, 4, 3});
countryGroupAssignment.put("SO", new int[] {3, 4, 3, 4});
countryGroupAssignment.put("SR", new int[] {2, 2, 2, 1});
countryGroupAssignment.put("SS", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("ST", new int[] {2, 3, 1, 2});
countryGroupAssignment.put("SV", new int[] {2, 2, 4, 4});
countryGroupAssignment.put("SX", new int[] {2, 4, 1, 0});
countryGroupAssignment.put("SY", new int[] {4, 3, 1, 1});
countryGroupAssignment.put("SZ", new int[] {4, 4, 3, 4});
countryGroupAssignment.put("TC", new int[] {1, 2, 1, 0});
countryGroupAssignment.put("TD", new int[] {4, 4, 4, 3});
countryGroupAssignment.put("TG", new int[] {3, 2, 1, 0});
countryGroupAssignment.put("TH", new int[] {1, 3, 3, 3});
countryGroupAssignment.put("TJ", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("TL", new int[] {4, 2, 4, 4});
countryGroupAssignment.put("TM", new int[] {4, 2, 2, 2});
countryGroupAssignment.put("TN", new int[] {2, 1, 1, 1});
countryGroupAssignment.put("TO", new int[] {4, 3, 4, 4});
countryGroupAssignment.put("TR", new int[] {1, 2, 1, 1});
countryGroupAssignment.put("TT", new int[] {1, 3, 2, 4});
countryGroupAssignment.put("TV", new int[] {4, 2, 3, 4});
countryGroupAssignment.put("TW", new int[] {0, 0, 0, 0});
countryGroupAssignment.put("TZ", new int[] {3, 4, 3, 3});
countryGroupAssignment.put("UA", new int[] {0, 3, 1, 1});
countryGroupAssignment.put("UG", new int[] {3, 2, 2, 3});
countryGroupAssignment.put("US", new int[] {0, 1, 2, 2});
countryGroupAssignment.put("UY", new int[] {2, 1, 2, 2});
countryGroupAssignment.put("UZ", new int[] {2, 2, 3, 2});
countryGroupAssignment.put("VA", new int[] {0, 2, 2, 2});
countryGroupAssignment.put("VC", new int[] {2, 3, 0, 2});
countryGroupAssignment.put("VE", new int[] {4, 4, 4, 4});
countryGroupAssignment.put("VG", new int[] {3, 1, 2, 4});
countryGroupAssignment.put("VI", new int[] {1, 4, 4, 3});
countryGroupAssignment.put("VN", new int[] {0, 1, 3, 4});
countryGroupAssignment.put("VU", new int[] {4, 0, 3, 3});
countryGroupAssignment.put("WS", new int[] {3, 2, 4, 3});
countryGroupAssignment.put("XK", new int[] {1, 2, 1, 0});
countryGroupAssignment.put("YE", new int[] {4, 4, 4, 3});
countryGroupAssignment.put("YT", new int[] {2, 2, 2, 3});
countryGroupAssignment.put("ZA", new int[] {2, 3, 2, 2});
countryGroupAssignment.put("ZM", new int[] {3, 2, 3, 3});
countryGroupAssignment.put("ZW", new int[] {3, 3, 2, 3});
return Collections.unmodifiableMap(countryGroupAssignment);
private static ImmutableListMultimap<String, Integer>
createInitialBitrateCountryGroupAssignment() {
ImmutableListMultimap.Builder<String, Integer> countryGroupAssignment =
ImmutableListMultimap.builder();
countryGroupAssignment.putAll("AD", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("AE", 1, 4, 4, 4, 1);
countryGroupAssignment.putAll("AF", 4, 4, 3, 4, 2);
countryGroupAssignment.putAll("AG", 2, 2, 1, 1, 2);
countryGroupAssignment.putAll("AI", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("AL", 1, 1, 0, 1, 2);
countryGroupAssignment.putAll("AM", 2, 2, 1, 2, 2);
countryGroupAssignment.putAll("AO", 3, 4, 4, 2, 2);
countryGroupAssignment.putAll("AR", 2, 4, 2, 2, 2);
countryGroupAssignment.putAll("AS", 2, 2, 4, 3, 2);
countryGroupAssignment.putAll("AT", 0, 3, 0, 0, 2);
countryGroupAssignment.putAll("AU", 0, 2, 0, 1, 1);
countryGroupAssignment.putAll("AW", 1, 2, 0, 4, 2);
countryGroupAssignment.putAll("AX", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("AZ", 3, 3, 3, 4, 2);
countryGroupAssignment.putAll("BA", 1, 1, 0, 1, 2);
countryGroupAssignment.putAll("BB", 0, 2, 0, 0, 2);
countryGroupAssignment.putAll("BD", 2, 0, 3, 3, 2);
countryGroupAssignment.putAll("BE", 0, 1, 2, 3, 2);
countryGroupAssignment.putAll("BF", 4, 4, 4, 2, 2);
countryGroupAssignment.putAll("BG", 0, 1, 0, 0, 2);
countryGroupAssignment.putAll("BH", 1, 0, 2, 4, 2);
countryGroupAssignment.putAll("BI", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("BJ", 4, 4, 3, 4, 2);
countryGroupAssignment.putAll("BL", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("BM", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("BN", 4, 0, 1, 1, 2);
countryGroupAssignment.putAll("BO", 2, 3, 3, 2, 2);
countryGroupAssignment.putAll("BQ", 1, 2, 1, 2, 2);
countryGroupAssignment.putAll("BR", 2, 4, 2, 1, 2);
countryGroupAssignment.putAll("BS", 3, 2, 2, 3, 2);
countryGroupAssignment.putAll("BT", 3, 0, 3, 2, 2);
countryGroupAssignment.putAll("BW", 3, 4, 2, 2, 2);
countryGroupAssignment.putAll("BY", 1, 0, 2, 1, 2);
countryGroupAssignment.putAll("BZ", 2, 2, 2, 1, 2);
countryGroupAssignment.putAll("CA", 0, 3, 1, 2, 3);
countryGroupAssignment.putAll("CD", 4, 3, 2, 2, 2);
countryGroupAssignment.putAll("CF", 4, 2, 2, 2, 2);
countryGroupAssignment.putAll("CG", 3, 4, 1, 1, 2);
countryGroupAssignment.putAll("CH", 0, 1, 0, 0, 0);
countryGroupAssignment.putAll("CI", 3, 3, 3, 3, 2);
countryGroupAssignment.putAll("CK", 3, 2, 1, 0, 2);
countryGroupAssignment.putAll("CL", 1, 1, 2, 3, 2);
countryGroupAssignment.putAll("CM", 3, 4, 3, 2, 2);
countryGroupAssignment.putAll("CN", 2, 2, 2, 1, 3);
countryGroupAssignment.putAll("CO", 2, 4, 3, 2, 2);
countryGroupAssignment.putAll("CR", 2, 3, 4, 4, 2);
countryGroupAssignment.putAll("CU", 4, 4, 2, 1, 2);
countryGroupAssignment.putAll("CV", 2, 3, 3, 3, 2);
countryGroupAssignment.putAll("CW", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("CY", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("CZ", 0, 1, 0, 0, 2);
countryGroupAssignment.putAll("DE", 0, 1, 1, 2, 0);
countryGroupAssignment.putAll("DJ", 4, 1, 4, 4, 2);
countryGroupAssignment.putAll("DK", 0, 0, 1, 0, 2);
countryGroupAssignment.putAll("DM", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("DO", 3, 4, 4, 4, 2);
countryGroupAssignment.putAll("DZ", 3, 2, 4, 4, 2);
countryGroupAssignment.putAll("EC", 2, 4, 3, 2, 2);
countryGroupAssignment.putAll("EE", 0, 0, 0, 0, 2);
countryGroupAssignment.putAll("EG", 3, 4, 2, 1, 2);
countryGroupAssignment.putAll("EH", 2, 2, 2, 2, 2);
countryGroupAssignment.putAll("ER", 4, 2, 2, 2, 2);
countryGroupAssignment.putAll("ES", 0, 1, 2, 1, 2);
countryGroupAssignment.putAll("ET", 4, 4, 4, 1, 2);
countryGroupAssignment.putAll("FI", 0, 0, 1, 0, 0);
countryGroupAssignment.putAll("FJ", 3, 0, 3, 3, 2);
countryGroupAssignment.putAll("FK", 2, 2, 2, 2, 2);
countryGroupAssignment.putAll("FM", 4, 2, 4, 3, 2);
countryGroupAssignment.putAll("FO", 0, 2, 0, 0, 2);
countryGroupAssignment.putAll("FR", 1, 0, 2, 1, 2);
countryGroupAssignment.putAll("GA", 3, 3, 1, 0, 2);
countryGroupAssignment.putAll("GB", 0, 0, 1, 2, 2);
countryGroupAssignment.putAll("GD", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("GE", 1, 0, 1, 3, 2);
countryGroupAssignment.putAll("GF", 2, 2, 2, 4, 2);
countryGroupAssignment.putAll("GG", 0, 2, 0, 0, 2);
countryGroupAssignment.putAll("GH", 3, 2, 3, 2, 2);
countryGroupAssignment.putAll("GI", 0, 2, 0, 0, 2);
countryGroupAssignment.putAll("GL", 1, 2, 2, 1, 2);
countryGroupAssignment.putAll("GM", 4, 3, 2, 4, 2);
countryGroupAssignment.putAll("GN", 4, 3, 4, 2, 2);
countryGroupAssignment.putAll("GP", 2, 2, 3, 4, 2);
countryGroupAssignment.putAll("GQ", 4, 2, 3, 4, 2);
countryGroupAssignment.putAll("GR", 1, 1, 0, 1, 2);
countryGroupAssignment.putAll("GT", 3, 2, 3, 2, 2);
countryGroupAssignment.putAll("GU", 1, 2, 4, 4, 2);
countryGroupAssignment.putAll("GW", 3, 4, 4, 3, 2);
countryGroupAssignment.putAll("GY", 3, 3, 1, 0, 2);
countryGroupAssignment.putAll("HK", 0, 2, 3, 4, 2);
countryGroupAssignment.putAll("HN", 3, 0, 3, 3, 2);
countryGroupAssignment.putAll("HR", 1, 1, 0, 1, 2);
countryGroupAssignment.putAll("HT", 4, 3, 4, 4, 2);
countryGroupAssignment.putAll("HU", 0, 1, 0, 0, 2);
countryGroupAssignment.putAll("ID", 3, 2, 2, 3, 2);
countryGroupAssignment.putAll("IE", 0, 0, 1, 1, 2);
countryGroupAssignment.putAll("IL", 1, 0, 2, 3, 2);
countryGroupAssignment.putAll("IM", 0, 2, 0, 1, 2);
countryGroupAssignment.putAll("IN", 2, 1, 3, 3, 2);
countryGroupAssignment.putAll("IO", 4, 2, 2, 4, 2);
countryGroupAssignment.putAll("IQ", 3, 2, 4, 3, 2);
countryGroupAssignment.putAll("IR", 4, 2, 3, 4, 2);
countryGroupAssignment.putAll("IS", 0, 2, 0, 0, 2);
countryGroupAssignment.putAll("IT", 0, 0, 1, 1, 2);
countryGroupAssignment.putAll("JE", 2, 2, 0, 2, 2);
countryGroupAssignment.putAll("JM", 3, 3, 4, 4, 2);
countryGroupAssignment.putAll("JO", 1, 2, 1, 1, 2);
countryGroupAssignment.putAll("JP", 0, 2, 0, 1, 3);
countryGroupAssignment.putAll("KE", 3, 4, 2, 2, 2);
countryGroupAssignment.putAll("KG", 1, 0, 2, 2, 2);
countryGroupAssignment.putAll("KH", 2, 0, 4, 3, 2);
countryGroupAssignment.putAll("KI", 4, 2, 3, 1, 2);
countryGroupAssignment.putAll("KM", 4, 2, 2, 3, 2);
countryGroupAssignment.putAll("KN", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("KP", 4, 2, 2, 2, 2);
countryGroupAssignment.putAll("KR", 0, 2, 1, 1, 1);
countryGroupAssignment.putAll("KW", 2, 3, 1, 1, 1);
countryGroupAssignment.putAll("KY", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("KZ", 1, 2, 2, 3, 2);
countryGroupAssignment.putAll("LA", 2, 2, 1, 1, 2);
countryGroupAssignment.putAll("LB", 3, 2, 0, 0, 2);
countryGroupAssignment.putAll("LC", 1, 1, 0, 0, 2);
countryGroupAssignment.putAll("LI", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("LK", 2, 0, 2, 3, 2);
countryGroupAssignment.putAll("LR", 3, 4, 3, 2, 2);
countryGroupAssignment.putAll("LS", 3, 3, 2, 3, 2);
countryGroupAssignment.putAll("LT", 0, 0, 0, 0, 2);
countryGroupAssignment.putAll("LU", 0, 0, 0, 0, 2);
countryGroupAssignment.putAll("LV", 0, 0, 0, 0, 2);
countryGroupAssignment.putAll("LY", 4, 2, 4, 3, 2);
countryGroupAssignment.putAll("MA", 2, 1, 2, 1, 2);
countryGroupAssignment.putAll("MC", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("MD", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("ME", 1, 2, 1, 2, 2);
countryGroupAssignment.putAll("MF", 1, 2, 1, 0, 2);
countryGroupAssignment.putAll("MG", 3, 4, 3, 3, 2);
countryGroupAssignment.putAll("MH", 4, 2, 2, 4, 2);
countryGroupAssignment.putAll("MK", 1, 0, 0, 0, 2);
countryGroupAssignment.putAll("ML", 4, 4, 1, 1, 2);
countryGroupAssignment.putAll("MM", 2, 3, 2, 2, 2);
countryGroupAssignment.putAll("MN", 2, 4, 1, 1, 2);
countryGroupAssignment.putAll("MO", 0, 2, 4, 4, 2);
countryGroupAssignment.putAll("MP", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("MQ", 2, 2, 2, 3, 2);
countryGroupAssignment.putAll("MR", 3, 0, 4, 2, 2);
countryGroupAssignment.putAll("MS", 1, 2, 2, 2, 2);
countryGroupAssignment.putAll("MT", 0, 2, 0, 1, 2);
countryGroupAssignment.putAll("MU", 3, 1, 2, 3, 2);
countryGroupAssignment.putAll("MV", 4, 3, 1, 4, 2);
countryGroupAssignment.putAll("MW", 4, 1, 1, 0, 2);
countryGroupAssignment.putAll("MX", 2, 4, 3, 3, 2);
countryGroupAssignment.putAll("MY", 2, 0, 3, 3, 2);
countryGroupAssignment.putAll("MZ", 3, 3, 2, 3, 2);
countryGroupAssignment.putAll("NA", 4, 3, 2, 2, 2);
countryGroupAssignment.putAll("NC", 2, 0, 4, 4, 2);
countryGroupAssignment.putAll("NE", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("NF", 2, 2, 2, 2, 2);
countryGroupAssignment.putAll("NG", 3, 3, 2, 2, 2);
countryGroupAssignment.putAll("NI", 3, 1, 4, 4, 2);
countryGroupAssignment.putAll("NL", 0, 2, 4, 2, 0);
countryGroupAssignment.putAll("NO", 0, 1, 1, 0, 2);
countryGroupAssignment.putAll("NP", 2, 0, 4, 3, 2);
countryGroupAssignment.putAll("NR", 4, 2, 3, 1, 2);
countryGroupAssignment.putAll("NU", 4, 2, 2, 2, 2);
countryGroupAssignment.putAll("NZ", 0, 2, 1, 2, 4);
countryGroupAssignment.putAll("OM", 2, 2, 0, 2, 2);
countryGroupAssignment.putAll("PA", 1, 3, 3, 4, 2);
countryGroupAssignment.putAll("PE", 2, 4, 4, 4, 2);
countryGroupAssignment.putAll("PF", 2, 2, 1, 1, 2);
countryGroupAssignment.putAll("PG", 4, 3, 3, 2, 2);
countryGroupAssignment.putAll("PH", 3, 0, 3, 4, 4);
countryGroupAssignment.putAll("PK", 3, 2, 3, 3, 2);
countryGroupAssignment.putAll("PL", 1, 0, 2, 2, 2);
countryGroupAssignment.putAll("PM", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("PR", 1, 2, 2, 3, 4);
countryGroupAssignment.putAll("PS", 3, 3, 2, 2, 2);
countryGroupAssignment.putAll("PT", 1, 1, 0, 0, 2);
countryGroupAssignment.putAll("PW", 1, 2, 3, 0, 2);
countryGroupAssignment.putAll("PY", 2, 0, 3, 3, 2);
countryGroupAssignment.putAll("QA", 2, 3, 1, 2, 2);
countryGroupAssignment.putAll("RE", 1, 0, 2, 1, 2);
countryGroupAssignment.putAll("RO", 1, 1, 1, 2, 2);
countryGroupAssignment.putAll("RS", 1, 2, 0, 0, 2);
countryGroupAssignment.putAll("RU", 0, 1, 0, 1, 2);
countryGroupAssignment.putAll("RW", 4, 3, 3, 4, 2);
countryGroupAssignment.putAll("SA", 2, 2, 2, 1, 2);
countryGroupAssignment.putAll("SB", 4, 2, 4, 2, 2);
countryGroupAssignment.putAll("SC", 4, 2, 0, 1, 2);
countryGroupAssignment.putAll("SD", 4, 4, 4, 3, 2);
countryGroupAssignment.putAll("SE", 0, 0, 0, 0, 2);
countryGroupAssignment.putAll("SG", 0, 0, 3, 3, 4);
countryGroupAssignment.putAll("SH", 4, 2, 2, 2, 2);
countryGroupAssignment.putAll("SI", 0, 1, 0, 0, 2);
countryGroupAssignment.putAll("SJ", 2, 2, 2, 2, 2);
countryGroupAssignment.putAll("SK", 0, 1, 0, 0, 2);
countryGroupAssignment.putAll("SL", 4, 3, 3, 1, 2);
countryGroupAssignment.putAll("SM", 0, 2, 2, 2, 2);
countryGroupAssignment.putAll("SN", 4, 4, 4, 3, 2);
countryGroupAssignment.putAll("SO", 3, 4, 4, 4, 2);
countryGroupAssignment.putAll("SR", 3, 2, 3, 1, 2);
countryGroupAssignment.putAll("SS", 4, 1, 4, 2, 2);
countryGroupAssignment.putAll("ST", 2, 2, 1, 2, 2);
countryGroupAssignment.putAll("SV", 2, 1, 4, 4, 2);
countryGroupAssignment.putAll("SX", 2, 2, 1, 0, 2);
countryGroupAssignment.putAll("SY", 4, 3, 2, 2, 2);
countryGroupAssignment.putAll("SZ", 3, 4, 3, 4, 2);
countryGroupAssignment.putAll("TC", 1, 2, 1, 0, 2);
countryGroupAssignment.putAll("TD", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("TG", 3, 2, 1, 0, 2);
countryGroupAssignment.putAll("TH", 1, 3, 4, 3, 0);
countryGroupAssignment.putAll("TJ", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("TL", 4, 1, 4, 4, 2);
countryGroupAssignment.putAll("TM", 4, 2, 1, 2, 2);
countryGroupAssignment.putAll("TN", 2, 1, 1, 1, 2);
countryGroupAssignment.putAll("TO", 3, 3, 4, 2, 2);
countryGroupAssignment.putAll("TR", 1, 2, 1, 1, 2);
countryGroupAssignment.putAll("TT", 1, 3, 1, 3, 2);
countryGroupAssignment.putAll("TV", 3, 2, 2, 4, 2);
countryGroupAssignment.putAll("TW", 0, 0, 0, 0, 1);
countryGroupAssignment.putAll("TZ", 3, 3, 3, 2, 2);
countryGroupAssignment.putAll("UA", 0, 3, 0, 0, 2);
countryGroupAssignment.putAll("UG", 3, 2, 2, 3, 2);
countryGroupAssignment.putAll("US", 0, 1, 3, 3, 3);
countryGroupAssignment.putAll("UY", 2, 1, 1, 1, 2);
countryGroupAssignment.putAll("UZ", 2, 0, 3, 2, 2);
countryGroupAssignment.putAll("VC", 2, 2, 2, 2, 2);
countryGroupAssignment.putAll("VE", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("VG", 2, 2, 1, 2, 2);
countryGroupAssignment.putAll("VI", 1, 2, 2, 4, 2);
countryGroupAssignment.putAll("VN", 0, 1, 4, 4, 2);
countryGroupAssignment.putAll("VU", 4, 1, 3, 1, 2);
countryGroupAssignment.putAll("WS", 3, 1, 4, 2, 2);
countryGroupAssignment.putAll("XK", 1, 1, 1, 0, 2);
countryGroupAssignment.putAll("YE", 4, 4, 4, 4, 2);
countryGroupAssignment.putAll("YT", 3, 2, 1, 3, 2);
countryGroupAssignment.putAll("ZA", 2, 3, 2, 2, 2);
countryGroupAssignment.putAll("ZM", 3, 2, 2, 3, 2);
countryGroupAssignment.putAll("ZW", 3, 3, 3, 3, 2);
return countryGroupAssignment.build();
}
}