Allow non-preferred internet networks

We allow internet networks that're Not using the preferred data profile if

a) the network has capability that the preferred network cannot satisfy

or b) the network type environment changed and we need to update the preferred data profile to align with the environment.

Without this change, above networks will be torn down due to DATA_PROFILE_NOT_PREFERRED upon any network evaluations.

Fix: 248346348
Fix: 273620310
Test: reproduce the issue and confirm the fix
Change-Id: I26ab868e6ac97a4bb089f76085523e030ba039fe
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index b18ba33..c038340 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -556,10 +556,10 @@
         /**
          * Called when internet data network is connected.
          *
-         * @param dataProfiles The data profiles of the connected internet data network. It should
-         * be only one in most of the cases.
+         * @param internetNetworks The connected internet data network. It should be only one in
+         *                         most of the cases.
          */
-        public void onInternetDataNetworkConnected(@NonNull List<DataProfile> dataProfiles) {}
+        public void onInternetDataNetworkConnected(@NonNull List<DataNetwork> internetNetworks) {}
 
         /**
          * Called when data network is connected.
@@ -1828,7 +1828,8 @@
         // If users switch preferred profile in APN editor, we need to tear down network.
         if (dataNetwork.isInternetSupported()
                 && !mDataProfileManager.isDataProfilePreferred(dataProfile)
-                && mDataProfileManager.isAnyPreferredDataProfileExisting()) {
+                && mDataProfileManager.canPreferredDataProfileSatisfy(
+                        dataNetwork.getAttachedNetworkRequestList())) {
             evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_PROFILE_NOT_PREFERRED);
         }
 
@@ -3454,9 +3455,7 @@
                     && mInternetDataNetworkState == TelephonyManager.DATA_DISCONNECTED) {
                 mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
                         () -> callback.onInternetDataNetworkConnected(
-                                allConnectedInternetDataNetworks.stream()
-                                        .map(DataNetwork::getDataProfile)
-                                        .collect(Collectors.toList()))));
+                                allConnectedInternetDataNetworks)));
             } else if (dataNetworkState == TelephonyManager.DATA_DISCONNECTED
                     && mInternetDataNetworkState == TelephonyManager.DATA_CONNECTED) {
                 mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index 2cf1452..37f0de0 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -167,8 +167,8 @@
                 new DataNetworkControllerCallback(this::post) {
                     @Override
                     public void onInternetDataNetworkConnected(
-                            @NonNull List<DataProfile> dataProfiles) {
-                        DataProfileManager.this.onInternetDataNetworkConnected(dataProfiles);
+                            @NonNull List<DataNetwork> internetNetworks) {
+                        DataProfileManager.this.onInternetDataNetworkConnected(internetNetworks);
                     }
                 });
         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
@@ -404,24 +404,37 @@
     /**
      * Called when internet data is connected.
      *
-     * @param dataProfiles The connected internet data networks' profiles.
+     * @param internetNetworks The connected internet data networks.
      */
-    private void onInternetDataNetworkConnected(@NonNull List<DataProfile> dataProfiles) {
-        // Most of the cases there should be only one, but in case there are multiple, choose the
-        // one which has longest life cycle.
-        DataProfile dataProfile = dataProfiles.stream()
-                .max(Comparator.comparingLong(DataProfile::getLastSetupTimestamp).reversed())
-                .orElse(null);
+    private void onInternetDataNetworkConnected(@NonNull List<DataNetwork> internetNetworks) {
+        DataProfile defaultProfile = null;
+        if (internetNetworks.size() == 1) {
+            // Most of the cases there should be only one.
+            defaultProfile = internetNetworks.get(0).getDataProfile();
+        } else if (internetNetworks.size() > 1) {
+            // but in case there are multiple, find the default internet network, and choose the
+            // one which has longest life cycle.
+            logv("onInternetDataNetworkConnected: mPreferredDataProfile=" + mPreferredDataProfile
+                    + " internetNetworks=" + internetNetworks);
+            defaultProfile = internetNetworks.stream()
+                    .filter(network -> mPreferredDataProfile == null
+                            || canPreferredDataProfileSatisfy(
+                            network.getAttachedNetworkRequestList()))
+                    .map(DataNetwork::getDataProfile)
+                    .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
+                    .orElse(null);
+        }
 
         // Update a working internet data profile as a future candidate for preferred data profile
         // after APNs are reset to default
-        mLastInternetDataProfile = dataProfile;
+        mLastInternetDataProfile = defaultProfile;
 
-        // If there is no preferred data profile, then we should use one of the data profiles,
-        // which is good for internet, as the preferred data profile.
-        if (mPreferredDataProfile != null) return;
+        // If the live default internet network is not using the preferred data profile, since
+        // brought up a network means it passed sophisticated checks, update the preferred data
+        // profile so that this network won't be torn down in future network evaluations.
+        if (defaultProfile == null || defaultProfile.equals(mPreferredDataProfile)) return;
         // Save the preferred data profile into database.
-        setPreferredDataProfile(dataProfile);
+        setPreferredDataProfile(defaultProfile);
         updateDataProfiles(ONLY_UPDATE_IA_IF_CHANGED);
     }
 
@@ -475,7 +488,7 @@
      * the preferred data profile from database.
      */
     private void setPreferredDataProfile(@Nullable DataProfile dataProfile) {
-        log("setPreferredDataProfile: " + dataProfile);
+        logl("setPreferredDataProfile: " + dataProfile);
 
         String subId = Long.toString(mPhone.getSubId());
         Uri uri = Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_URI, subId);
@@ -774,6 +787,18 @@
     }
 
     /**
+     * @param networkRequests The required network requests
+     * @return {@code true} if we currently have a preferred data profile that's capable of
+     * satisfying the required network requests; {@code false} if we have no preferred, or the
+     * preferred cannot satisfy the required requests.
+     */
+    public boolean canPreferredDataProfileSatisfy(
+            @NonNull DataNetworkController.NetworkRequestList networkRequests) {
+        return mPreferredDataProfile != null && networkRequests.stream()
+                .allMatch(request -> request.canBeSatisfiedBy(mPreferredDataProfile));
+    }
+
+    /**
      * Check if there is tethering data profile for certain network type.
      *
      * @param networkType The network type
@@ -794,18 +819,6 @@
         return getDataProfileForNetworkRequest(networkRequest, networkType, true) != null;
     }
 
-     /**
-     * Check if any preferred data profile exists.
-     *
-     * @return {@code true} if any preferred data profile exists
-     */
-    public boolean isAnyPreferredDataProfileExisting() {
-        for (DataProfile dataProfile : mAllDataProfiles) {
-            if (dataProfile.isPreferred()) return true;
-        }
-        return false;
-    }
-
     /**
      * Dedupe the similar data profiles.
      */
@@ -1111,6 +1124,7 @@
         pw.println("Preferred data profile from db=" + getPreferredDataProfileFromDb());
         pw.println("Preferred data profile from config=" + getPreferredDataProfileFromConfig());
         pw.println("Preferred data profile set id=" + mPreferredDataProfileSetId);
+        pw.println("Last internet data profile=" + mLastInternetDataProfile);
         pw.println("Initial attach data profile=" + mInitialAttachDataProfile);
         pw.println("isTetheringDataProfileExisting=" + isTetheringDataProfileExisting(
                 TelephonyManager.NETWORK_TYPE_LTE));
diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
index df3ab57..8bf9e55 100644
--- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
@@ -32,7 +32,6 @@
 import android.telephony.CellSignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.data.DataProfile;
 import android.util.IndentingPrintWriter;
 import android.util.LocalLog;
 
@@ -265,7 +264,7 @@
 
                     @Override
                     public void onInternetDataNetworkConnected(
-                            @NonNull List<DataProfile> dataProfiles) {
+                            @NonNull List<DataNetwork> internetNetworks) {
                         mIsInternetNetworkConnected = true;
                         logl("onInternetDataNetworkConnected");
                     }
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index 5b78685..7c63dec 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -30,12 +30,12 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.telephony.data.DataProfile;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.data.DataNetwork;
 import com.android.internal.telephony.data.DataNetworkController;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
 import com.android.internal.telephony.imsphone.ImsPhone;
@@ -93,7 +93,7 @@
     }
 
     /** Updates service state when internet pdn gets connected. */
-    public void onInternetDataNetworkConnected(@NonNull List<DataProfile> dataProfiles) {
+    public void onInternetDataNetworkConnected(@NonNull List<DataNetwork> internetNetworks) {
         onInternetDataNetworkChanged(true);
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 0dded12..6e42260 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -144,6 +144,12 @@
     private static final String FAKE_MMTEL_PACKAGE = "fake.mmtel.package";
     private static final String FAKE_RCS_PACKAGE = "fake.rcs.package";
 
+    // Events
+    private static final int EVENT_SIM_STATE_CHANGED = 9;
+    private static final int EVENT_REEVALUATE_EXISTING_DATA_NETWORKS = 16;
+    private static final int EVENT_VOICE_CALL_ENDED = 18;
+    private static final int EVENT_SUBSCRIPTION_OVERRIDE = 23;
+
     // Mocked classes
     private PhoneSwitcher mMockedPhoneSwitcher;
     protected ISub mMockedIsub;
@@ -230,6 +236,36 @@
             .setPreferred(false)
             .build();
 
+    // Created to test preferred data profiles that apply to different network types
+    private final DataProfile mGeneralPurposeDataProfileAlternative = new DataProfile.Builder()
+            .setApnSetting(new ApnSetting.Builder()
+                    .setId(2161)
+                    .setOperatorNumeric("12345")
+                    .setEntryName("internet_supl_mms_apn")
+                    .setApnName("internet_supl_mms_apn")
+                    .setUser("user")
+                    .setPassword("passwd")
+                    .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL
+                            | ApnSetting.TYPE_MMS)
+                    .setProtocol(ApnSetting.PROTOCOL_IPV6)
+                    .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
+                    .setCarrierEnabled(true)
+                    .setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_NR
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT))
+                    .setLingeringNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
+                            | TelephonyManager.NETWORK_TYPE_BITMASK_NR))
+                    .setProfileId(4321)
+                    .setMaxConns(321)
+                    .setWaitTime(456)
+                    .setMaxConnsTime(789)
+                    .build())
+            .setPreferred(false)
+            .build();
+
     private final DataProfile mImsCellularDataProfile = new DataProfile.Builder()
             .setApnSetting(new ApnSetting.Builder()
                     .setId(2164)
@@ -321,7 +357,7 @@
                     .setApnName("dun_apn")
                     .setUser("user")
                     .setPassword("passwd")
-                    .setApnTypeBitmask(ApnSetting.TYPE_DUN)
+                    .setApnTypeBitmask(ApnSetting.TYPE_DUN | ApnSetting.TYPE_DEFAULT)
                     .setProtocol(ApnSetting.PROTOCOL_IPV6)
                     .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
                     .setCarrierEnabled(true)
@@ -836,7 +872,8 @@
                 linkBandwidthEstimatorCallbackCaptor.capture());
         mLinkBandwidthEstimatorCallback = linkBandwidthEstimatorCallbackCaptor.getValue();
 
-        List<DataProfile> profiles = List.of(mGeneralPurposeDataProfile, mImsCellularDataProfile,
+        List<DataProfile> profiles = List.of(mGeneralPurposeDataProfile,
+                mGeneralPurposeDataProfileAlternative, mImsCellularDataProfile,
                 mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile,
                 mTetheringDataProfile);
 
@@ -889,7 +926,6 @@
 
         doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
                 .getPreferredTransportByNetworkCapability(anyInt());
-        doReturn(true).when(mDataProfileManager).isDataProfilePreferred(any(DataProfile.class));
 
         doAnswer(invocation -> {
             ((Runnable) invocation.getArguments()[0]).run();
@@ -903,7 +939,7 @@
         mDataNetworkControllerUT.registerDataNetworkControllerCallback(
                 mMockedDataNetworkControllerCallback);
 
-        mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SIM_STATE_CHANGED,
                 10/*SIM_STATE_LOADED*/, 0).sendToTarget();
         mDataNetworkControllerUT.obtainMessage(8/*EVENT_DATA_SERVICE_BINDING_CHANGED*/,
                 new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, true, null))
@@ -1259,7 +1295,7 @@
     public void testSimRemovalDataTearDown() throws Exception {
         testSetupDataNetwork();
 
-        mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SIM_STATE_CHANGED,
                 TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
         processAllMessages();
         verifyAllDataDisconnected();
@@ -1273,7 +1309,7 @@
         Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
 
         // Insert the SIM again.
-        mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SIM_STATE_CHANGED,
                 TelephonyManager.SIM_STATE_LOADED, 0).sendToTarget();
         processAllMessages();
 
@@ -1482,7 +1518,7 @@
 
         // Call ended.
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
-        mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
+        mDataNetworkControllerUT.obtainMessage(EVENT_VOICE_CALL_ENDED).sendToTarget();
         processAllMessages();
 
         // It should have no internet setup at the beginning.
@@ -1952,7 +1988,7 @@
 
         // Set 5G unmetered
         congestedNetworkTypes.add(TelephonyManager.NETWORK_TYPE_NR);
-        mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SUBSCRIPTION_OVERRIDE,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED,
                 new int[]{TelephonyManager.NETWORK_TYPE_NR}).sendToTarget();
@@ -1974,7 +2010,7 @@
 
         // Set all network types metered
         congestedNetworkTypes.clear();
-        mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SUBSCRIPTION_OVERRIDE,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED, 0,
                 TelephonyManager.getAllNetworkTypes()).sendToTarget();
         dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
@@ -1994,7 +2030,7 @@
 
         // Set 5G unmetered
         unmeteredNetworkTypes.add(TelephonyManager.NETWORK_TYPE_NR);
-        mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SUBSCRIPTION_OVERRIDE,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED,
                 new int[]{TelephonyManager.NETWORK_TYPE_NR}).sendToTarget();
@@ -2018,7 +2054,7 @@
 
         // Set all network types metered
         unmeteredNetworkTypes.clear();
-        mDataNetworkControllerUT.obtainMessage(23/*EVENT_SUBSCRIPTION_OVERRIDE*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SUBSCRIPTION_OVERRIDE,
                 NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED, 0,
                 TelephonyManager.getAllNetworkTypes()).sendToTarget();
         dataNetwork.sendMessage(16/*EVENT_SUBSCRIPTION_PLAN_OVERRIDE*/);
@@ -2113,7 +2149,7 @@
                 NetworkCapabilities.NET_CAPABILITY_MMTEL);
 
         // Both internet and IMS should be retained after network re-evaluation
-        mDataNetworkControllerUT.obtainMessage(16/*EVENT_REEVALUATE_EXISTING_DATA_NETWORKS*/)
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
                 .sendToTarget();
         processAllMessages();
 
@@ -2133,7 +2169,7 @@
                 NetworkCapabilities.NET_CAPABILITY_MMTEL);
 
         // Both internet and IMS should be retained after network re-evaluation
-        mDataNetworkControllerUT.obtainMessage(16/*EVENT_REEVALUATE_EXISTING_DATA_NETWORKS*/)
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
                 .sendToTarget();
         processAllMessages();
 
@@ -2508,7 +2544,7 @@
 
         // Verify tear down after call ends
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
-        mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
+        mDataNetworkControllerUT.obtainMessage(EVENT_VOICE_CALL_ENDED).sendToTarget();
         processAllFutureMessages();
 
         verify(mMockedWlanDataServiceManager).deactivateDataCall(anyInt(),
@@ -2837,8 +2873,8 @@
         // There should be only one attempt, and no retry should happen because it's a permanent
         // failure.
         verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
-                any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
-                any(), any(), anyBoolean(), any(Message.class));
+                eq(mGeneralPurposeDataProfile), anyBoolean(), anyBoolean(), anyInt(), any(),
+                anyInt(), any(), any(), anyBoolean(), any(Message.class));
 
         Mockito.clearInvocations(mMockedWwanDataServiceManager);
         mDataNetworkControllerUT.addNetworkRequest(
@@ -3171,6 +3207,73 @@
     }
 
     @Test
+    public void testSetPreferredDataProfileMultiInternetDataProfile() throws Exception {
+        // No preferred data profile in the beginning
+        doReturn(false).when(mDataProfileManager).canPreferredDataProfileSatisfy(
+                any(NetworkRequestList.class));
+
+        testSetupDataNetwork();
+
+        // Verify this network still alive after evaluation
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
+                .sendToTarget();
+        processAllMessages();
+
+        verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
+
+        // Network connected, became preferred data profile
+        doAnswer(invocation -> {
+            NetworkRequestList networkRequests =
+                    (NetworkRequestList) invocation.getArguments()[0];
+            return networkRequests.stream()
+                    .allMatch(request -> request.canBeSatisfiedBy(mGeneralPurposeDataProfile));
+        }).when(mDataProfileManager).canPreferredDataProfileSatisfy(
+                any(NetworkRequestList.class));
+        doReturn(true).when(mDataProfileManager)
+                .isDataProfilePreferred(mGeneralPurposeDataProfile);
+
+        // 1. Test DUN | DEFAULT data profile is compatible with preferred default internet
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_DUN));
+        setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 2);
+        processAllMessages();
+
+        // Verify both DUN and preferred default network are alive
+        verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
+        verifyConnectedNetworkHasDataProfile(mTetheringDataProfile);
+
+        // Verify this network still alive after evaluation
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
+                .sendToTarget();
+        processAllMessages();
+
+        verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
+        verifyConnectedNetworkHasDataProfile(mTetheringDataProfile);
+
+        // 2. Test tear down when user changes preferred data profile
+        doAnswer(invocation -> {
+            NetworkRequestList networkRequests =
+                    (NetworkRequestList) invocation.getArguments()[0];
+            return networkRequests.stream()
+                    .allMatch(request -> request.canBeSatisfiedBy(
+                            mGeneralPurposeDataProfileAlternative));
+        }).when(mDataProfileManager).canPreferredDataProfileSatisfy(
+                any(NetworkRequestList.class));
+        doReturn(true).when(mDataProfileManager)
+                .isDataProfilePreferred(mGeneralPurposeDataProfileAlternative);
+        doReturn(false).when(mDataProfileManager)
+                .isDataProfilePreferred(mGeneralPurposeDataProfile);
+
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
+                .sendToTarget();
+        processAllMessages();
+
+        List<DataNetwork> dataNetworks = getDataNetworks();
+        assertThat(dataNetworks).hasSize(1);
+        verifyConnectedNetworkHasDataProfile(mTetheringDataProfile);
+    }
+
+    @Test
     public void testDataDisableNotAllowingBringingUpTetheringNetwork() throws Exception {
         // User data disabled
         mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
@@ -3429,11 +3532,11 @@
         verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
 
         mDataNetworkControllerUT.addNetworkRequest(
-                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
         processAllFutureMessages();
         // Lower priority network should not trump the higher priority network.
         verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
-        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE);
 
         // Now send a higher priority network request
         TelephonyNetworkRequest fotaRequest = createNetworkRequest(
@@ -3684,7 +3787,7 @@
 
         // 2. Normal case (call ended), should tear down
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
-        mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
+        mDataNetworkControllerUT.obtainMessage(EVENT_VOICE_CALL_ENDED).sendToTarget();
         processAllFutureMessages();
 
         // Verify that handover is not performed.
@@ -4061,7 +4164,7 @@
 
         mCarrierConfig.putBoolean(CarrierConfigManager.Ims.KEY_KEEP_PDN_UP_IN_NO_VOPS_BOOL, false);
         carrierConfigChanged();
-        mDataNetworkControllerUT.obtainMessage(16/*EVENT_REEVALUATE_EXISTING_DATA_NETWORKS*/)
+        mDataNetworkControllerUT.obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)
                 .sendToTarget();
         processAllMessages();
 
@@ -4111,7 +4214,7 @@
 
         // Call ends
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
-        mDataNetworkControllerUT.obtainMessage(18/*EVENT_VOICE_CALL_ENDED*/).sendToTarget();
+        mDataNetworkControllerUT.obtainMessage(EVENT_VOICE_CALL_ENDED).sendToTarget();
         processAllMessages();
 
         verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
@@ -4131,7 +4234,7 @@
 
         testSetupDataNetwork();
 
-        mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+        mDataNetworkControllerUT.obtainMessage(EVENT_SIM_STATE_CHANGED,
                 TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
         processAllMessages();
         verifyAllDataDisconnected();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 1fbe386..43f65e2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -75,6 +75,7 @@
 @TestableLooper.RunWithLooper
 public class DataProfileManagerTest extends TelephonyTest {
     private static final String GENERAL_PURPOSE_APN = "GP_APN";
+    private static final String GENERAL_PURPOSE_APN_LEGACY_RAT = "GP_APN_RAT";
     private static final String GENERAL_PURPOSE_APN1 = "GP_APN1";
     private static final String IMS_APN = "IMS_APN";
     private static final String TETHERING_APN = "DUN_APN";
@@ -170,6 +171,41 @@
                         -1,                     // skip_464xlat
                         0                       // always_on
                 },
+                // default internet data profile for RAT CDMA, to test update preferred data profile
+                new Object[]{
+                        9,                      // id
+                        PLMN,                   // numeric
+                        GENERAL_PURPOSE_APN_LEGACY_RAT,    // name
+                        GENERAL_PURPOSE_APN_LEGACY_RAT,    // apn
+                        "",                     // proxy
+                        "",                     // port
+                        "",                     // mmsc
+                        "",                     // mmsproxy
+                        "",                     // mmsport
+                        "",                     // user
+                        "",                     // password
+                        -1,                     // authtype
+                        "default,supl,mms,ia",  // types
+                        "IPV4V6",               // protocol
+                        "IPV4V6",               // roaming_protocol
+                        1,                      // carrier_enabled
+                        0,                      // profile_id
+                        1,                      // modem_cognitive
+                        0,                      // max_conns
+                        0,                      // wait_time
+                        0,                      // max_conns_time
+                        0,                      // mtu
+                        1280,                   // mtu_v4
+                        1280,                   // mtu_v6
+                        "",                     // mvno_type
+                        "",                     // mnvo_match_data
+                        TelephonyManager.NETWORK_TYPE_BITMASK_CDMA, // network_type_bitmask
+                        0,                      // lingering_network_type_bitmask
+                        DEFAULT_APN_SET_ID,     // apn_set_id
+                        -1,                     // carrier_id
+                        -1,                     // skip_464xlat
+                        0                       // always_on
+                },
                 new Object[]{
                         2,                      // id
                         PLMN,                   // numeric
@@ -777,13 +813,51 @@
         assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
         dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
         dataProfile.setPreferred(true);
-        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(dataProfile));
+        DataNetwork internetNetwork = Mockito.mock(DataNetwork.class);
+        doReturn(dataProfile).when(internetNetwork).getDataProfile();
+        doReturn(new DataNetworkController.NetworkRequestList(List.of(tnr)))
+                .when(internetNetwork).getAttachedNetworkRequestList();
+        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(internetNetwork));
         processAllMessages();
 
-        // See if the same one can be returned.
+        // Test See if the same one can be returned.
         dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
                 tnr, TelephonyManager.NETWORK_TYPE_LTE, false);
         assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
+        assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+
+        // Test Another default internet network connected due to RAT changed. Verify the preferred
+        // data profile is updated.
+        DataProfile legacyRatDataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+                tnr, TelephonyManager.NETWORK_TYPE_CDMA, false);
+        DataNetwork legacyRatInternetNetwork = Mockito.mock(DataNetwork.class);
+        doReturn(legacyRatDataProfile).when(legacyRatInternetNetwork).getDataProfile();
+        doReturn(new DataNetworkController.NetworkRequestList(List.of(tnr)))
+                .when(legacyRatInternetNetwork).getAttachedNetworkRequestList();
+        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(
+                // Because internetNetwork is torn down due to network type mismatch
+                legacyRatInternetNetwork));
+        processAllMessages();
+
+        assertThat(mDataProfileManagerUT.isDataProfilePreferred(legacyRatDataProfile)).isTrue();
+
+        // Test Another supl default internet network temporarily connected. Verify preferred
+        // doesn't change.
+        TelephonyNetworkRequest suplTnr = new TelephonyNetworkRequest(
+                new NetworkRequest.Builder()
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
+                        .build(), mPhone);
+        DataProfile suplDataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+                suplTnr, TelephonyManager.NETWORK_TYPE_LTE, false);
+        DataNetwork suplInternetNetwork = Mockito.mock(DataNetwork.class);
+        doReturn(suplDataProfile).when(suplInternetNetwork).getDataProfile();
+        doReturn(new DataNetworkController.NetworkRequestList(List.of(suplTnr)))
+                .when(suplInternetNetwork).getAttachedNetworkRequestList();
+        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(
+                legacyRatInternetNetwork, suplInternetNetwork));
+        processAllMessages();
+
+        assertThat(mDataProfileManagerUT.isDataProfilePreferred(legacyRatDataProfile)).isTrue();
     }
 
     @Test
@@ -1065,11 +1139,12 @@
                 tnr, TelephonyManager.NETWORK_TYPE_LTE, false);
         assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
         dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
-        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(dataProfile));
+        DataNetwork internetNetwork = Mockito.mock(DataNetwork.class);
+        doReturn(dataProfile).when(internetNetwork).getDataProfile();
+        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(internetNetwork));
         processAllMessages();
 
         // After internet connected, preferred APN should be set
-        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isTrue();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
 
         // APN reset
@@ -1078,7 +1153,6 @@
         processAllMessages();
 
         // preferred APN should set to be the last data profile that succeeded for internet setup
-        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isTrue();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
 
         // Test user selected a bad data profile, expects to adopt the last data profile that
@@ -1088,7 +1162,6 @@
         mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
         processAllMessages();
 
-        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isTrue();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isFalse();
 
         // APN reset, preferred APN should set to be the last data profile that succeeded for
@@ -1097,11 +1170,10 @@
         mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
         processAllMessages();
 
-        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isTrue();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
 
         // Test removed data profile(user created after reset) shouldn't show up
-        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(dataProfile));
+        mDataNetworkControllerCallback.onInternetDataNetworkConnected(List.of(internetNetwork));
         processAllMessages();
         //APN reset and removed GENERAL_PURPOSE_APN from APN DB
         mPreferredApnId = -1;
@@ -1110,7 +1182,6 @@
         processAllMessages();
 
         // There should be no preferred APN after APN reset because last working profile is removed
-        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isFalse();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isFalse();
 
         // restore mApnSettingContentProvider
@@ -1194,7 +1265,7 @@
     }
 
     @Test
-    public void testDataProfileCompatibility() throws Exception {
+    public void testDataProfileCompatibility() {
         DataProfile enterpriseDataProfile = new DataProfile.Builder()
                 .setTrafficDescriptor(new TrafficDescriptor(null,
                         new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
index 2528441..6781ce3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
@@ -29,7 +29,6 @@
 import android.net.NetworkAgent;
 import android.telephony.Annotation.ValidationStatus;
 import android.telephony.CarrierConfigManager;
-import android.telephony.data.DataProfile;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -117,7 +116,7 @@
                 dataNetworkControllerCallbackCaptor.getValue();
 
         if (isConnected) {
-            List<DataProfile> dataprofile = new ArrayList<DataProfile>();
+            List<DataNetwork> dataprofile = new ArrayList<>();
             dataNetworkControllerCallback.onInternetDataNetworkConnected(dataprofile);
         } else {
             dataNetworkControllerCallback.onInternetDataNetworkDisconnected();