Merge "Add support for RAT-based TCP buffer sizes"
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index d6e263b..1a8b29a 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -217,6 +217,9 @@
     /** A map of network types to the downlink and uplink bandwidth values for that network type */
     private @NonNull final @DataConfigNetworkType Map<String, DataNetwork.NetworkBandwidth>
             mBandwidthMap = new ConcurrentHashMap<>();
+    /** A map of network types to the TCP buffer sizes for that network type */
+    private @NonNull final @DataConfigNetworkType Map<String, String> mTcpBufferSizeMap =
+            new ConcurrentHashMap<>();
     /** Rules for handover between IWLAN and cellular network. */
     private @NonNull final List<HandoverRule> mHandoverRuleList = new ArrayList<>();
 
@@ -293,6 +296,7 @@
         updateSingleDataNetworkTypeList();
         updateUnmeteredNetworkTypes();
         updateBandwidths();
+        updateTcpBuffers();
         updateHandoverRules();
 
         log("Data config updated. Config is " + (isConfigCarrierSpecific() ? "" : "not ")
@@ -626,17 +630,56 @@
     }
 
     /**
+     * Update the TCP buffer sizes from the resource overlays.
+     */
+    private void updateTcpBuffers() {
+        synchronized (this) {
+            mTcpBufferSizeMap.clear();
+            String[] configs = mResources.getStringArray(
+                    com.android.internal.R.array.config_network_type_tcp_buffers);
+            if (configs != null) {
+                for (String config : configs) {
+                    // split[0] = network type as string
+                    // split[1] = rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max
+                    String[] split = config.split(":");
+                    if (split.length != 2) {
+                        loge("Invalid TCP buffer sizes entry: " + config);
+                        continue;
+                    }
+                    if (split[1].split(",").length != 6) {
+                        loge("Invalid TCP buffer sizes for " + split[0] + ": " + split[1]);
+                        continue;
+                    }
+                    mTcpBufferSizeMap.put(split[0], split[1]);
+                }
+            }
+        }
+    }
+
+    /**
      * Get the TCP config string, used by {@link LinkProperties#setTcpBufferSizes(String)}.
      * The config string will have the following form, with values in bytes:
      * "read_min,read_default,read_max,write_min,write_default,write_max"
      *
-     * Note that starting from Android 13, the TCP buffer size is fixed after boot up, and should
-     * never be changed based on carriers or the network types. The value should be configured
-     * appropriately based on the device's memory and performance.
-     *
-     * @return The TCP configuration string.
+     * @param networkType The network type. Note that {@link TelephonyManager#NETWORK_TYPE_LTE_CA}
+     *                    can be used for LTE CA even though it's not a radio access technology.
+     * @param serviceState The service state, used to determine NR state.
+     * @return The TCP configuration string for the given network type or the default value from
+     *         config_tcp_buffers if unavailable.
      */
-    public @NonNull String getTcpConfigString() {
+    public @NonNull String getTcpConfigString(@NetworkType int networkType,
+            @NonNull ServiceState serviceState) {
+        String config = mTcpBufferSizeMap.get(getDataConfigNetworkType(networkType, serviceState));
+        if (TextUtils.isEmpty(config)) {
+            config = getDefaultTcpConfigString();
+        }
+        return config;
+    }
+
+    /**
+     * @return The fixed TCP buffer size configured based on the device's memory and performance.
+     */
+    public @NonNull String getDefaultTcpConfigString() {
         return mResources.getString(com.android.internal.R.string.config_tcp_buffers);
     }
 
@@ -932,7 +975,11 @@
                 + shouldResetDataThrottlingWhenTacChanges());
         pw.println("Data service package name=" + getDataServicePackageName());
         pw.println("Default MTU=" + getDefaultMtu());
-        pw.println("TCP buffer sizes:" + getTcpConfigString());
+        pw.println("TCP buffer sizes by RAT:");
+        pw.increaseIndent();
+        mTcpBufferSizeMap.forEach((key, value) -> pw.println(key + ":" + value));
+        pw.decreaseIndent();
+        pw.println("Default TCP buffer sizes=" + getDefaultTcpConfigString());
         pw.println("getImsDeregistrationDelay=" + getImsDeregistrationDelay());
         pw.println("shouldPersistIwlanDataNetworksWhenDataServiceRestarted="
                 + shouldPersistIwlanDataNetworksWhenDataServiceRestarted());
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index a6920bf..2f3b4f3 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -515,6 +515,9 @@
     /** The network bandwidth. */
     private @NonNull NetworkBandwidth mNetworkBandwidth = new NetworkBandwidth(14, 14);
 
+    /** The TCP buffer sizes config. */
+    private @NonNull String mTcpBufferSizes;
+
     /** Whether {@link NetworkCapabilities#NET_CAPABILITY_TEMPORARILY_NOT_METERED} is supported. */
     private boolean mTempNotMeteredSupported = false;
 
@@ -767,6 +770,7 @@
         mAttachedNetworkRequestList.addAll(networkRequestList);
         mCid.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, INVALID_CID);
         mCid.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, INVALID_CID);
+        mTcpBufferSizes = mDataConfigManager.getDefaultTcpConfigString();
 
         for (TelephonyNetworkRequest networkRequest : networkRequestList) {
             networkRequest.setAttachedNetwork(DataNetwork.this);
@@ -873,6 +877,7 @@
                     // TODO: Should update suspend state when CSS indicator changes.
                     // TODO: Should update suspend state when call started/ended.
                     updateSuspendState();
+                    updateTcpBufferSizes();
                     updateBandwidthFromDataConfig();
                     break;
                 }
@@ -1824,7 +1829,7 @@
             linkProperties.setHttpProxy(proxy);
         }
 
-        linkProperties.setTcpBufferSizes(mDataConfigManager.getTcpConfigString());
+        linkProperties.setTcpBufferSizes(mTcpBufferSizes);
 
         mNetworkSliceInfo = response.getSliceInfo();
 
@@ -1857,6 +1862,28 @@
     }
 
     /**
+     * Get the TCP buffer sizes config string.
+     *
+     * @return The TCP buffer sizes config used in {@link LinkProperties#setTcpBufferSizes(String)}.
+     */
+    private @Nullable String getTcpConfig() {
+        ServiceState ss = mPhone.getServiceState();
+        NetworkRegistrationInfo nrs = ss.getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, mTransport);
+        int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        if (nrs != null) {
+            networkType = nrs.getAccessNetworkTechnology();
+            if (networkType == TelephonyManager.NETWORK_TYPE_LTE
+                    && nrs.isUsingCarrierAggregation()) {
+                // Although LTE_CA is not a real RAT, but since LTE CA generally has higher speed
+                // we use LTE_CA to get a different TCP config for LTE CA.
+                networkType = TelephonyManager.NETWORK_TYPE_LTE_CA;
+            }
+        }
+        return mDataConfigManager.getTcpConfigString(networkType, ss);
+    }
+
+    /**
      * Called when receiving setup data network response from the data service.
      *
      * @param resultCode The result code.
@@ -2045,6 +2072,7 @@
         log("onDataConfigUpdated");
 
         updateBandwidthFromDataConfig();
+        updateTcpBufferSizes();
         updateMeteredAndCongested();
     }
 
@@ -2110,6 +2138,7 @@
      */
     private void onDisplayInfoChanged() {
         updateBandwidthFromDataConfig();
+        updateTcpBufferSizes();
         updateMeteredAndCongested();
     }
 
@@ -2128,6 +2157,21 @@
     }
 
     /**
+     * Update the TCP buffer sizes from resource overlays.
+     */
+    private void updateTcpBufferSizes() {
+        log("updateTcpBufferSizes");
+        mTcpBufferSizes = getTcpConfig();
+        LinkProperties linkProperties = new LinkProperties(mLinkProperties);
+        linkProperties.setTcpBufferSizes(mTcpBufferSizes);
+        if (!linkProperties.equals(mLinkProperties)) {
+            mLinkProperties = linkProperties;
+            log("sendLinkProperties " + mLinkProperties);
+            mNetworkAgent.sendLinkProperties(mLinkProperties);
+        }
+    }
+
+    /**
      * Update the metered and congested values from carrier configs and subscription overrides
      */
     private void updateMeteredAndCongested() {
@@ -2762,6 +2806,7 @@
         pw.println("mLinkProperties=" + mLinkProperties);
         pw.println("mNetworkSliceInfo=" + mNetworkSliceInfo);
         pw.println("mNetworkBandwidth=" + mNetworkBandwidth);
+        pw.println("mTcpBufferSizes=" + mTcpBufferSizes);
         pw.println("mTempNotMeteredSupported=" + mTempNotMeteredSupported);
         pw.println("mTempNotMetered=" + mTempNotMetered);
         pw.println("mCongested=" + mCongested);