Merge "Add support for RAT-based TCP buffer sizes"
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 84ed777..1aba83e 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -440,7 +440,7 @@
         if (mIsPhysicalChannelConfigOn && (nrNsa || nrSa)) {
             // Process NR display network type
             displayNetworkType = getNrDisplayType(nrSa);
-            if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
+            if (displayNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE && !nrSa) {
                 // Use LTE values if 5G values aren't defined
                 displayNetworkType = getLteDisplayType();
             }
@@ -1208,7 +1208,8 @@
 
         // Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum
         // bandwidth requirement and mNrAdvancedThresholdBandwidth is 0.
-        if (IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum()
+        if (mNrAdvancedThresholdBandwidth > 0
+                && IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum()
                 < mNrAdvancedThresholdBandwidth) {
             return false;
         }
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index f3e2d9a..cc0828f 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -5170,7 +5170,15 @@
      * @return A string containing all public non-static local variables of a class
      */
     public static String convertToString(Object o) {
-        if (isPrimitiveOrWrapper(o.getClass()) || o.getClass() == String.class) return o.toString();
+        boolean toStringExists = false;
+        try {
+            toStringExists = o.getClass().getMethod("toString").getDeclaringClass() != Object.class;
+        } catch (NoSuchMethodException e) {
+            loge(e.toString());
+        }
+        if (toStringExists || isPrimitiveOrWrapper(o.getClass()) || o instanceof ArrayList) {
+            return o.toString();
+        }
         if (o.getClass().isArray()) {
             // Special handling for arrays
             StringBuilder sb = new StringBuilder("[");
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index fa5b156..5a7a4e0 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -273,7 +273,9 @@
         /** VoPS is not supported by the network. */
         VOPS_NOT_SUPPORTED(true),
         /** Only one data network is allowed at one time. */
-        ONLY_ALLOWED_SINGLE_NETWORK(true);
+        ONLY_ALLOWED_SINGLE_NETWORK(true),
+        /** Data enabled settings are not ready. */
+        DATA_SETTINGS_NOT_READY(true);
 
         private final boolean mIsHardReason;
 
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 1a3256b..d996667 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1270,9 +1270,13 @@
                     DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK);
         }
 
-        if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
-                networkRequest.getApnTypeNetworkCapability()))) {
-            evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
+        if (mDataSettingsManager.isDataInitialized()) {
+            if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
+                    networkRequest.getApnTypeNetworkCapability()))) {
+                evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
+            }
+        } else {
+            evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_SETTINGS_NOT_READY);
         }
 
         // Check whether to allow data in certain situations if data is disallowed for soft reasons
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index aa54992..35f82d9 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -75,8 +75,8 @@
     private static final int EVENT_PROVISIONED_CHANGED = 9;
     /** Event for provisioning data enabled setting changed. */
     private static final int EVENT_PROVISIONING_DATA_ENABLED_CHANGED = 10;
-    /** Event for registering all events. */
-    private static final int EVENT_REGISTER_ALL_EVENTS = 11;
+    /** Event for initializing DataSettingsManager. */
+    private static final int EVENT_INITIALIZE = 11;
 
     private final Phone mPhone;
     private final ContentResolver mResolver;
@@ -100,7 +100,13 @@
      * Flag indicating whether data is allowed or not for the device.
      * It can be disabled by user, carrier, policy or thermal.
      */
-    private boolean mIsDataEnabled = false;
+    private boolean mIsDataEnabled;
+
+    /**
+     * Used to indicate that the initial value for mIsDataEnabled was set.
+     * Prevent race condition where the initial value might be incorrect.
+     */
+    private boolean mInitialized = false;
 
     /**
      * Data settings manager callback. This should be only used by {@link DataNetworkController}.
@@ -159,12 +165,9 @@
         mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_CARRIER, true);
         mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_THERMAL, true);
 
-        mIsDataEnabled = isDataEnabled(ApnSetting.TYPE_ALL);
-        log("mIsDataEnabled=" + mIsDataEnabled);
-
-        // Instead of calling onRegisterAllEvents directly from the constructor, send the event.
+        // Instead of calling onInitialize directly from the constructor, send the event.
         // The reason is that getImsPhone is null when we are still in the constructor here.
-        sendEmptyMessage(EVENT_REGISTER_ALL_EVENTS);
+        sendEmptyMessage(EVENT_INITIALIZE);
     }
 
     @Override
@@ -255,8 +258,8 @@
                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
                 break;
             }
-            case EVENT_REGISTER_ALL_EVENTS: {
-                onRegisterAllEvents();
+            case EVENT_INITIALIZE: {
+                onInitialize();
                 break;
             }
             default:
@@ -267,7 +270,7 @@
     /**
      * Called when needed to register for all events that data network controller is interested.
      */
-    private void onRegisterAllEvents() {
+    private void onInitialize() {
         mDataConfigManager.registerForConfigUpdate(this, EVENT_DATA_CONFIG_UPDATED);
         mSettingsObserver.observe(Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
                 EVENT_PROVISIONED_CHANGED);
@@ -293,6 +296,7 @@
                         }
                     }
                 }, this::post);
+        updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
     }
 
     /**
@@ -320,7 +324,8 @@
         boolean prevDataEnabled = mIsDataEnabled;
         mIsDataEnabled = isDataEnabled(ApnSetting.TYPE_ALL);
         log("mIsDataEnabled=" + mIsDataEnabled + ", prevDataEnabled=" + prevDataEnabled);
-        if (prevDataEnabled != mIsDataEnabled) {
+        if (!mInitialized || prevDataEnabled != mIsDataEnabled) {
+            if (!mInitialized) mInitialized = true;
             notifyDataEnabledChanged(mIsDataEnabled, reason);
         }
     }
@@ -347,7 +352,8 @@
     }
 
     /**
-     * Check whether the overall data is enabled for the device.
+     * Check whether the overall data is enabled for the device. Note that this value will only
+     * be accurate if {@link #isDataInitialized} is {@code true}.
      * @return {@code true} if the overall data is enabled and {@code false} otherwise.
      */
     public boolean isDataEnabled() {
@@ -355,6 +361,18 @@
     }
 
     /**
+     * Check whether data enabled value has been initialized. If this is {@code false}, then
+     * {@link #isDataEnabled} is not guaranteed to be accurate. Once data is initialized,
+     * {@link DataSettingsManagerCallback#onDataEnabledChanged} will be invoked with reason
+     * {@link TelephonyManager#DATA_ENABLED_REASON_UNKNOWN}.
+     * @return {@code true} if the data enabled value is initialized and {@code false} otherwise.
+     */
+    public boolean isDataInitialized() {
+        // TODO: Create a new DATA_ENABLED_REASON_INITIALIZED for initial value broadcast
+        return mInitialized;
+    }
+
+    /**
      * Check whether the overall data is enabled for the device for the given APN type.
      * @param apnType A single APN type to check data enabled for.
      * @return {@code true} if the overall data is enabled for the APN and {@code false} otherwise.