Merge "Move onDataCallDisconnected to DcInactiveState so we can indicate failureCause"
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index f855f34..1e41b38 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -4043,13 +4043,19 @@
     }
 
     @Override
-    public void setSignalStrengthReportingCriteria(
-            int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
+    public void setSignalStrengthReportingCriteria(int signalStrengthMeasure,
+            int[] systemThresholds, int ran, boolean isEnabledForSystem) {
         int[] consolidatedThresholds = mSST.getConsolidatedSignalThresholds(
                 ran,
                 signalStrengthMeasure,
-                mSST.shouldHonorSystemThresholds() ? thresholds : new int[]{},
+                isEnabledForSystem && mSST.shouldHonorSystemThresholds() ? systemThresholds
+                        : new int[]{},
                 REPORTING_HYSTERESIS_DB);
+        boolean isEnabledForAppRequest = mSST.shouldEnableSignalThresholdForAppRequest(
+                ran,
+                signalStrengthMeasure,
+                getSubId(),
+                isDeviceIdle());
         mCi.setSignalStrengthReportingCriteria(
                 new SignalThresholdInfo.Builder()
                         .setRadioAccessNetworkType(ran)
@@ -4057,7 +4063,7 @@
                         .setHysteresisMs(REPORTING_HYSTERESIS_MILLIS)
                         .setHysteresisDb(REPORTING_HYSTERESIS_DB)
                         .setThresholds(consolidatedThresholds, true /*isSystem*/)
-                        .setIsEnabled(isEnabled)
+                        .setIsEnabled(isEnabledForSystem || isEnabledForAppRequest)
                         .build(),
                 ran, null);
     }
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index dc32ba5..949feee 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -82,6 +82,8 @@
     private static final int EVENT_DEFAULT_DATA_SUBSCRIPTION_CHANGED = 6;
     private static final int EVENT_CARRIER_CONFIG_CHANGED            = 7;
     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED          = 8;
+    @VisibleForTesting
+    public static final int EVENT_RADIO_STATE_CHANGED                = 9;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"PRIMARY_SUB_"},
@@ -294,6 +296,16 @@
             case EVENT_MULTI_SIM_CONFIG_CHANGED:
                 int activeModems = (int) ((AsyncResult) msg.obj).result;
                 onMultiSimConfigChanged(activeModems);
+                break;
+            case EVENT_RADIO_STATE_CHANGED:
+                for (Phone phone : PhoneFactory.getPhones()) {
+                    if (phone.mCi.getRadioState() == TelephonyManager.RADIO_POWER_UNAVAILABLE) {
+                        if (DBG) log("Radio unavailable. Clearing sub info initialized flag.");
+                        mSubInfoInitialized = false;
+                        break;
+                    }
+                }
+                break;
         }
     }
 
@@ -335,6 +347,9 @@
     private void onAllSubscriptionsLoaded() {
         if (DBG) log("onAllSubscriptionsLoaded");
         mSubInfoInitialized = true;
+        for (Phone phone : PhoneFactory.getPhones()) {
+            phone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+        }
         reEvaluateAll();
     }
 
@@ -424,6 +439,9 @@
         for (int phoneId = activeModems; phoneId < mCarrierConfigLoadedSubIds.length; phoneId++) {
             mCarrierConfigLoadedSubIds[phoneId] = INVALID_SUBSCRIPTION_ID;
         }
+        for (Phone phone : PhoneFactory.getPhones()) {
+            phone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+        }
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 2155c4a..8fea92f 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -187,7 +187,8 @@
     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
     protected static final int EVENT_NV_READY                       = 23;
     private static final int EVENT_SET_ENHANCED_VP                  = 24;
-    protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
+    @VisibleForTesting
+    public static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
     // other
@@ -1844,6 +1845,17 @@
     }
 
     /**
+     * Check whether the radio is off for thermal reason.
+     *
+     * @return {@code true} only if thermal mitigation is one of the reason for which radio is off.
+     */
+    public boolean isRadioOffForThermalMitigation() {
+        ServiceStateTracker sst = getServiceStateTracker();
+        return sst != null && sst.getRadioPowerOffReasons()
+                .contains(Phone.RADIO_POWER_REASON_THERMAL);
+    }
+
+    /**
      * Retrieves the EmergencyNumberTracker of the phone instance.
      */
     public EmergencyNumberTracker getEmergencyNumberTracker() {
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index 598e8db..19c6021 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -433,8 +433,7 @@
         NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
                 builder.build(), this);
         // we want to see all requests
-        networkFactory.setScoreFilter(101);
-        networkFactory.register();
+        networkFactory.registerIgnoringScore();
 
         updateHalCommandToUse();
 
diff --git a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
index 99ffe36..de62c70 100644
--- a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
+++ b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
@@ -123,6 +123,10 @@
                     if (ar.exception != null) {
                         loge("setupRadioInterfaceCapabilities: " + ar.exception);
                     }
+                    if (ar.result == null) {
+                        loge("setupRadioInterfaceCapabilities: ar.result is null");
+                        return;
+                    }
                     log("setupRadioInterfaceCapabilities: "
                             + "mRadioInterfaceCapabilities now setup");
                     mRadioInterfaceCapabilities =
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 9835f8a..d036721 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1083,8 +1083,7 @@
     /**
      * @return the current reasons for which the radio is off.
      */
-    @VisibleForTesting
-    public Set<Integer> getRadioPowerOffReasonsForTest() {
+    public Set<Integer> getRadioPowerOffReasons() {
         return sRadioPowerOffReasons;
     }
 
@@ -6243,8 +6242,7 @@
                 continue;
             }
             for (SignalThresholdInfo info : record.mRequest.getSignalThresholdInfos()) {
-                if (ran == info.getRadioAccessNetworkType()
-                        && measurement == info.getSignalMeasurementType()) {
+                if (isRanAndSignalMeasurementTypeMatch(ran, measurement, info)) {
                     for (int appThreshold : info.getThresholds()) {
                         target.add(appThreshold);
                     }
@@ -6275,12 +6273,44 @@
         sendMessage(obtainMessage(EVENT_ON_DEVICE_IDLE_STATE_CHANGED, isDeviceIdle));
     }
 
+    boolean shouldEnableSignalThresholdForAppRequest(
+            @AccessNetworkConstants.RadioAccessNetworkType int ran,
+            @SignalThresholdInfo.SignalMeasurementType int measurement,
+            int subId,
+            boolean isDeviceIdle) {
+        for (SignalRequestRecord record : mSignalRequestRecords) {
+            if (subId != record.mSubId) {
+                continue;
+            }
+            for (SignalThresholdInfo info : record.mRequest.getSignalThresholdInfos()) {
+                if (isRanAndSignalMeasurementTypeMatch(ran, measurement, info)
+                        && (!isDeviceIdle || isSignalReportRequestedWhileIdle(record.mRequest))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean isRanAndSignalMeasurementTypeMatch(
+            @AccessNetworkConstants.RadioAccessNetworkType int ran,
+            @SignalThresholdInfo.SignalMeasurementType int measurement,
+            SignalThresholdInfo info) {
+        return ran == info.getRadioAccessNetworkType()
+                && measurement == info.getSignalMeasurementType();
+    }
+
+    private static boolean isSignalReportRequestedWhileIdle(SignalStrengthUpdateRequest request) {
+        return request.isSystemThresholdReportingRequestedWhileIdle()
+                || request.isReportingRequestedWhileIdle();
+    }
+
     private class SignalRequestRecord implements IBinder.DeathRecipient {
         final int mSubId; // subId the request originally applied to
         final int mCallingUid;
         final SignalStrengthUpdateRequest mRequest;
 
-        SignalRequestRecord(int subId, int uid, SignalStrengthUpdateRequest request) {
+        SignalRequestRecord(int subId, int uid, @NonNull SignalStrengthUpdateRequest request) {
             this.mCallingUid = uid;
             this.mSubId = subId;
             this.mRequest = request;
@@ -6295,8 +6325,7 @@
     private void updateAlwaysReportSignalStrength() {
         final int curSubId = mPhone.getSubId();
         boolean alwaysReport = mSignalRequestRecords.stream().anyMatch(
-                srr -> srr.mSubId == curSubId && (srr.mRequest.isReportingRequestedWhileIdle()
-                        || srr.mRequest.isSystemThresholdReportingRequestedWhileIdle()));
+                srr -> srr.mSubId == curSubId && isSignalReportRequestedWhileIdle(srr.mRequest));
 
         // TODO(b/177924721): TM#setAlwaysReportSignalStrength will be removed and we will not
         // worry about unset flag which was set by other client.
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java b/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
index 0ded77e..6d6d0ea 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierConfigEfData.java
@@ -33,49 +33,52 @@
 /** Ef data from carrier config. */
 public final class CarrierConfigEfData implements EfData {
     private static final String TAG = "CarrierConfigEfData";
-    private final PersistableBundle mConfig;
+
+    private final String mSpn;
+    private final int mSpnDisplayCondition;
+    private final String[] mSpdi;
+    private final String[] mEhplmn;
+    private final String[] mPnn;
+    private final String[] mOpl;
 
     public CarrierConfigEfData(@NonNull PersistableBundle config) {
-        mConfig = config;
+        // Save only the relevant keys of the config.
+        mSpn = config.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
+        mSpnDisplayCondition = config.getInt(
+                CarrierConfigManager.KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT,
+                IccRecords.INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK);
+        mSpdi = config.getStringArray(CarrierConfigManager.KEY_SPDI_OVERRIDE_STRING_ARRAY);
+        mEhplmn = config.getStringArray(CarrierConfigManager.KEY_EHPLMN_OVERRIDE_STRING_ARRAY);
+        mPnn = config.getStringArray(CarrierConfigManager.KEY_PNN_OVERRIDE_STRING_ARRAY);
+        mOpl = config.getStringArray(CarrierConfigManager.KEY_OPL_OVERRIDE_STRING_ARRAY);
     }
 
     @Override
     public String getServiceProviderName() {
-        String spn = mConfig.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
-        if (TextUtils.isEmpty(spn)) return null;
-        return spn;
+        return TextUtils.isEmpty(mSpn) ? null : mSpn;
     }
 
     @Override
     public int getServiceProviderNameDisplayCondition(boolean isRoaming) {
-        int condition = mConfig.getInt(
-                CarrierConfigManager.KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT,
-                IccRecords.INVALID_CARRIER_NAME_DISPLAY_CONDITION_BITMASK);
-        return condition;
+        return mSpnDisplayCondition;
     }
 
     @Override
     public List<String> getServiceProviderDisplayInformation() {
-        String[] spdi = mConfig.getStringArray(
-                CarrierConfigManager.KEY_SPDI_OVERRIDE_STRING_ARRAY);
-        return spdi != null ? Arrays.asList(spdi) : null;
+        return mSpdi != null ? Arrays.asList(mSpdi) : null;
     }
 
     @Override
     public List<String> getEhplmnList() {
-        String[] ehplmn = mConfig.getStringArray(
-                CarrierConfigManager.KEY_EHPLMN_OVERRIDE_STRING_ARRAY);
-        return ehplmn != null ? Arrays.asList(ehplmn) : null;
+        return mEhplmn != null ? Arrays.asList(mEhplmn) : null;
     }
 
     @Override
     public List<PlmnNetworkName> getPlmnNetworkNameList() {
-        String[] pnn = mConfig.getStringArray(
-                CarrierConfigManager.KEY_PNN_OVERRIDE_STRING_ARRAY);
         List<PlmnNetworkName> pnnList = null;
-        if (pnn != null) {
-            pnnList = new ArrayList<>(pnn.length);
-            for (String pnnStr : pnn) {
+        if (mPnn != null) {
+            pnnList = new ArrayList<>(mPnn.length);
+            for (String pnnStr : mPnn) {
                 try {
                     String[] names = pnnStr.split("\\s*,\\s*");
                     String alphal = names[0];
@@ -91,13 +94,10 @@
 
     @Override
     public List<OperatorPlmnInfo> getOperatorPlmnList() {
-        // OPL
-        String[] opl = mConfig.getStringArray(
-                CarrierConfigManager.KEY_OPL_OVERRIDE_STRING_ARRAY);
         List<OperatorPlmnInfo> oplList = null;
-        if (opl != null) {
-            oplList = new ArrayList<>(opl.length);
-            for (String oplStr : opl) {
+        if (mOpl != null) {
+            oplList = new ArrayList<>(mOpl.length);
+            for (String oplStr : mOpl) {
                 try {
                     String[] info = oplStr.split("\\s*,\\s*");
                     oplList.add(new OperatorPlmnInfo(
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index d2fa226..4d4ca81 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -1593,8 +1593,7 @@
             }
 
             // Check if it fails because of the existing data is still disconnecting.
-            if (dataConnectionReasons.containsOnly(
-                    DataDisallowedReasonType.DATA_IS_DISCONNECTING)
+            if (dataConnectionReasons.contains(DataDisallowedReasonType.DATA_IS_DISCONNECTING)
                     && isHandoverPending(apnContext.getApnTypeBitmask())) {
                 // Normally we don't retry when isDataAllow() returns false, because that's consider
                 // pre-condition not met, for example, data not enabled by the user, or airplane
diff --git a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
index 4081cd6..df3f0f1 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
@@ -130,7 +130,15 @@
         return makeNetworkFilter(subscriptionId);
     }
 
-    private NetworkCapabilities makeNetworkFilter(int subscriptionId) {
+    /**
+     * Build the network request filter used by this factory.
+     * @param subscriptionId the subscription ID to listen to
+     * @return the filter to send to the system server
+     */
+    // This is used by the test to simulate the behavior of the system server, which is to
+    // send requests that match the network filter.
+    @VisibleForTesting
+    public NetworkCapabilities makeNetworkFilter(int subscriptionId) {
         final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
diff --git a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
index 280176f..a81e93f 100644
--- a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
@@ -277,14 +277,17 @@
     @Test
     @SmallTest
     public void testIsRcsVolteSingleRegistrationSupported() {
-        String[] vals = new String[]{"0", "1", "false", "true"};
-        boolean[] expectedRes = new boolean[]{false, true, false, true};
+        String[] vals = new String[]{"0", "1", "2"};
+        boolean[] expectedResHome = new boolean[]{false, true, true};
+        boolean[] expectedResRoaming = new boolean[]{false, true, false};
         for (int i = 0; i < vals.length; i++) {
             String xml = "\t\t\t\t<characteristic type=\"GSMA\">\n"
                     + "\t\t\t\t\t<parm name=\"rcsVolteSingleRegistration\" value=\""
                     + vals[i] + "\"/>\n" + "\t\t\t\t</characteristic>\n";
             RcsConfig config = new RcsConfig(xml.getBytes());
-            assertEquals(config.isRcsVolteSingleRegistrationSupported(), expectedRes[i]);
+            assertEquals(config.isRcsVolteSingleRegistrationSupported(false), expectedResHome[i]);
+            assertEquals(config.isRcsVolteSingleRegistrationSupported(true),
+                    expectedResRoaming[i]);
         }
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index c93de7d..9058a44 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -50,6 +50,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+
 import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.telephony.dataconnection.DataEnabledSettings;
@@ -62,6 +63,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
@@ -132,6 +134,8 @@
         doReturn(true).when(mSubControllerMock).isOpportunistic(5);
         doReturn(1).when(mPhoneMock1).getSubId();
         doReturn(2).when(mPhoneMock2).getSubId();
+        mPhoneMock1.mCi = mSimulatedCommands;
+        mPhoneMock2.mCi = mSimulatedCommands;
         List<SubscriptionInfo> infoList = Arrays.asList(mSubInfo1, mSubInfo2);
         doReturn(infoList).when(mSubControllerMock)
                 .getActiveSubscriptionInfoList(anyString(), nullable(String.class));
@@ -163,7 +167,7 @@
 
     @Test
     @SmallTest
-    public void testTestSubInfoChangeBeforeAllSubReady() throws Exception {
+    public void testSubInfoChangeBeforeAllSubReady() throws Exception {
         doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubControllerMock)
                 .getDefaultDataSubId();
         doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubControllerMock)
@@ -199,6 +203,50 @@
     }
 
     @Test
+    public void testSubInfoChangeAfterRadioUnavailable() throws Exception {
+        mMultiSimSettingControllerUT.notifyAllSubscriptionLoaded();
+        mMultiSimSettingControllerUT.notifyCarrierConfigChanged(0, 1);
+        mMultiSimSettingControllerUT.notifyCarrierConfigChanged(1, 2);
+        processAllMessages();
+
+        // Notify radio unavailable.
+        replaceInstance(BaseCommands.class, "mState", mSimulatedCommands,
+                TelephonyManager.RADIO_POWER_UNAVAILABLE);
+        mMultiSimSettingControllerUT.obtainMessage(
+                MultiSimSettingController.EVENT_RADIO_STATE_CHANGED).sendToTarget();
+
+        // Mark all subs as inactive.
+        doReturn(false).when(mSubControllerMock).isActiveSubId(1);
+        doReturn(false).when(mSubControllerMock).isActiveSubId(2);
+        doReturn(SubscriptionManager.INVALID_PHONE_INDEX).when(mSubControllerMock).getPhoneId(1);
+        doReturn(SubscriptionManager.INVALID_PHONE_INDEX).when(mSubControllerMock).getPhoneId(2);
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mPhoneMock1).getSubId();
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mPhoneMock2).getSubId();
+        List<SubscriptionInfo> infoList = new ArrayList<>();
+        doReturn(infoList).when(mSubControllerMock).getActiveSubscriptionInfoList(anyString(),
+                nullable(String.class));
+        doReturn(new int[]{}).when(mSubControllerMock).getActiveSubIdList(anyBoolean());
+        clearInvocations(mSubControllerMock);
+
+        // The below sub info change should be ignored.
+        mMultiSimSettingControllerUT.notifySubscriptionInfoChanged();
+        processAllMessages();
+        verify(mSubControllerMock, never()).setDefaultDataSubId(anyInt());
+        verify(mSubControllerMock, never()).setDefaultVoiceSubId(anyInt());
+        verify(mSubControllerMock, never()).setDefaultSmsSubId(anyInt());
+
+        // Send all sub ready notification
+        mMultiSimSettingControllerUT.notifyAllSubscriptionLoaded();
+        processAllMessages();
+
+        // Everything should be set to invalid since nothing is active.
+        verify(mSubControllerMock).setDefaultDataSubId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        verify(mSubControllerMock)
+                .setDefaultVoiceSubId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        verify(mSubControllerMock).setDefaultSmsSubId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    @Test
     @SmallTest
     public void testSingleActiveDsds() throws Exception {
         doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID).when(mSubControllerMock)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 067454f..54ac7a3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -269,11 +269,6 @@
         waitUntilReady();
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
 
-        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
-        intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
-        mContext.sendBroadcast(intent);
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-
         // Override SPN related resource
         mContextFixture.putResource(
                 com.android.internal.R.string.lockscreen_carrier_default,
@@ -334,6 +329,12 @@
                     15, /* SIGNAL_STRENGTH_GOOD */
                     30  /* SIGNAL_STRENGTH_GREAT */
                 });
+
+        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
+        mContext.sendBroadcast(intent);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+
         logd("ServiceStateTrackerTest -Setup!");
     }
 
@@ -404,33 +405,33 @@
     public void testSetRadioPowerForReason() {
         // Radio does not turn on if off for other reason and not emergency call.
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().isEmpty());
+        assertTrue(sst.getRadioPowerOffReasons().isEmpty());
         sst.setRadioPowerForReason(false, false, false, false, Phone.RADIO_POWER_REASON_THERMAL);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().contains(Phone.RADIO_POWER_REASON_THERMAL));
-        assertTrue(sst.getRadioPowerOffReasonsForTest().size() == 1);
+        assertTrue(sst.getRadioPowerOffReasons().contains(Phone.RADIO_POWER_REASON_THERMAL));
+        assertTrue(sst.getRadioPowerOffReasons().size() == 1);
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
         sst.setRadioPowerForReason(true, false, false, false, Phone.RADIO_POWER_REASON_USER);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().contains(Phone.RADIO_POWER_REASON_THERMAL));
-        assertTrue(sst.getRadioPowerOffReasonsForTest().size() == 1);
+        assertTrue(sst.getRadioPowerOffReasons().contains(Phone.RADIO_POWER_REASON_THERMAL));
+        assertTrue(sst.getRadioPowerOffReasons().size() == 1);
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
 
         // Radio power state reason is removed and radio turns on if turned on for same reason it
         // had been turned off for.
         sst.setRadioPowerForReason(true, false, false, false, Phone.RADIO_POWER_REASON_THERMAL);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().isEmpty());
+        assertTrue(sst.getRadioPowerOffReasons().isEmpty());
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
 
         // Turn radio off, then successfully turn radio on for emergency call.
         sst.setRadioPowerForReason(false, false, false, false, Phone.RADIO_POWER_REASON_THERMAL);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().contains(Phone.RADIO_POWER_REASON_THERMAL));
-        assertTrue(sst.getRadioPowerOffReasonsForTest().size() == 1);
+        assertTrue(sst.getRadioPowerOffReasons().contains(Phone.RADIO_POWER_REASON_THERMAL));
+        assertTrue(sst.getRadioPowerOffReasons().size() == 1);
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
         sst.setRadioPower(true, true, true, false);
-        assertTrue(sst.getRadioPowerOffReasonsForTest().isEmpty());
+        assertTrue(sst.getRadioPowerOffReasons().isEmpty());
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index ce5dc21..c0b8d9a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -2829,6 +2829,7 @@
         doReturn(mApnContext).when(apnContextsByType).get(eq(ApnSetting.TYPE_IMS));
         doReturn(mApnContext).when(apnContexts).get(eq(ApnSetting.TYPE_IMS_STRING));
         doReturn(false).when(mApnContext).isConnectable();
+        doReturn(false).when(mDataEnabledSettings).isDataEnabled(anyInt());
         doReturn(DctConstants.State.DISCONNECTING).when(mApnContext).getState();
         replaceInstance(DcTracker.class, "mApnContextsByType", mDct, apnContextsByType);
         replaceInstance(DcTracker.class, "mApnContexts", mDct, apnContexts);
@@ -2850,6 +2851,7 @@
         doReturn(DctConstants.State.RETRYING).when(mApnContext).getState();
         // Data now is disconnected
         doReturn(true).when(mApnContext).isConnectable();
+        doReturn(true).when(mDataEnabledSettings).isDataEnabled(anyInt());
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE,
                 new AsyncResult(Pair.create(mApnContext, 0), null, null)));
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
index 0aa2a4d..7dd65c2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
@@ -32,6 +32,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
 import android.net.NetworkRequest;
 import android.net.TelephonyNetworkSpecifier;
 import android.os.AsyncResult;
@@ -42,6 +43,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.util.ArraySet;
 
 import androidx.test.filters.FlakyTest;
 
@@ -56,6 +58,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 
@@ -77,6 +80,9 @@
 
     private String mTestName = "";
 
+    // List of all requests filed by a test
+    private final ArraySet<NetworkRequest> mAllNetworkRequestSet = new ArraySet<>();
+    // List of requests active in DcTracker
     private final ArrayList<NetworkRequest> mNetworkRequestList = new ArrayList<>();
 
     private TelephonyNetworkFactory mTelephonyNetworkFactoryUT;
@@ -155,7 +161,9 @@
                         "mobile_ia,14,0,2,-1,true", "mobile_emergency,15,0,2,-1,true"});
 
         doAnswer(invocation -> {
-            mNetworkRequestList.add((NetworkRequest) invocation.getArguments()[0]);
+            final NetworkRequest req = (NetworkRequest) invocation.getArguments()[0];
+            mNetworkRequestList.add(req);
+            mAllNetworkRequestSet.add(req);
             return null;
         }).when(mDcTracker).requestNetwork(any(), anyInt(), any());
 
@@ -174,8 +182,36 @@
         replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mPhoneSwitcher);
 
         mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(Looper.myLooper(), mPhone);
-        verify(mConnectivityManager).registerNetworkProvider(any());
+        final ArgumentCaptor<NetworkProvider> providerCaptor =
+                ArgumentCaptor.forClass(NetworkProvider.class);
+        verify(mConnectivityManager).registerNetworkProvider(providerCaptor.capture());
+        // For NetworkFactory to function as expected, the provider ID must be set to some
+        // number > 0.
+        providerCaptor.getValue().setProviderId(1);
         verify(mPhoneSwitcher).registerForActivePhoneSwitch(any(), anyInt(), any());
+
+        // Simulate the behavior of the system server. When offerNetwork is called, it will
+        // update the factory about all requests that pass the registered filter, by calling
+        // NetworkProvider#onNetworkNeeded or onNetworkUnneeded.
+        // Note that this simulation is a little bit incomplete, as the system server will
+        // *update* only for those requests for which the status has changed, but this
+        // simulation will send REQUEST_NETWORK or CANCEL_REQUEST for all registered requests.
+        // At this time it makes no difference in this test.
+        // Also, this test reads from mAllNetworkRequestSet, which is not really the list of
+        // requests sent to the system server as the test doesn't instrument that. Instead, it's
+        // the list of requests ever sent to the factory. This also makes no difference in this
+        // test at this time.
+        doAnswer(invocation -> {
+            final NetworkCapabilities capabilitiesFilter =
+                    mTelephonyNetworkFactoryUT.makeNetworkFilter(
+                            mSubscriptionController.getSubIdUsingPhoneId(0));
+            for (final NetworkRequest request : mAllNetworkRequestSet) {
+                final int message = request.canBeSatisfiedBy(capabilitiesFilter)
+                        ? CMD_REQUEST_NETWORK : CMD_CANCEL_REQUEST;
+                mTelephonyNetworkFactoryUT.obtainMessage(message, 0, 0, request).sendToTarget();
+            }
+            return null;
+        }).when(mConnectivityManager).offerNetwork(anyInt(), any(), any(), any());
     }
 
     /**