Merge "Revaluate request after initial network capability" into 24D1-dev
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index bd98403..7ca504b 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -124,6 +124,7 @@
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -1001,23 +1002,36 @@
                 && transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
         mDataAllowedReason = dataAllowedReason;
         dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
-        mAttachedNetworkRequestList.addAll(networkRequestList);
         for (int transportType : mAccessNetworksManager.getAvailableTransports()) {
             mCid.put(transportType, INVALID_CID);
         }
         mTelephonyDisplayInfo = mPhone.getDisplayInfoController().getTelephonyDisplayInfo();
         mTcpBufferSizes = mDataConfigManager.getTcpConfigString(mTelephonyDisplayInfo);
 
-        for (TelephonyNetworkRequest networkRequest : networkRequestList) {
-            networkRequest.setAttachedNetwork(DataNetwork.this);
-            networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
-        }
-
+        // network capabilities infer connectivity transport and MMTEL from the requested
+        // capabilities.
+        // TODO: Ideally we shouldn't infer network capabilities base on the requested capabilities,
+        // but currently there are 2 hacks associated with getForcedCellularTransportCapabilities
+        // and IMS service requesting IMS|MMTEL that need to support. When we stop supporting these
+        // cases, we shouldn't consider the requests when determining the network capabilities.
+        mAttachedNetworkRequestList.addAll(networkRequestList);
         // Update the capabilities in the constructor is to make sure the data network has initial
         // capability immediately after created. Doing this connecting state creates the window that
         // DataNetworkController might check if existing data network's capability can satisfy the
         // next network request within this window.
         updateNetworkCapabilities();
+
+        // Remove the requests that can't use the initial capabilities
+        ListIterator<TelephonyNetworkRequest> iter = mAttachedNetworkRequestList.listIterator();
+        while (iter.hasNext()) {
+            TelephonyNetworkRequest request = iter.next();
+            if (request.canBeSatisfiedBy(mNetworkCapabilities)) {
+                request.setAttachedNetwork(DataNetwork.this);
+                request.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
+            } else {
+                iter.remove();
+            }
+        }
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 12c94df..5a688ca 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -2122,6 +2122,13 @@
      */
     private boolean canConnectivityTransportSatisfyNetworkRequest(
             @NonNull TelephonyNetworkRequest networkRequest, @TransportType int transport) {
+        // Check if this is a IWLAN network request.
+        if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+            // If the request would result in bringing up network on IWLAN, then no
+            // need to check if the device is using satellite network.
+            return true;
+        }
+
         // When the device is on satellite, only restricted network request can request network.
         if (mServiceState.isUsingNonTerrestrialNetwork()
                 && networkRequest.hasCapability(
@@ -2136,14 +2143,6 @@
             return true;
         }
 
-        // Check if this is a IWLAN network request.
-        if (networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
-                && transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
-            // If the cellular request would result in bringing up network on IWLAN, then no
-            // need to check if the device is using satellite network.
-            return true;
-        }
-
         // As a short term solution, allowing some networks to be always marked as cellular
         // transport if certain capabilities are in the network request.
         if (networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && Arrays.stream(
@@ -3061,8 +3060,18 @@
             List<NetworkRequestList> groupRequestLists = getGroupedUnsatisfiedNetworkRequests();
             dataSetupRetryEntry.networkRequestList.stream()
                     .filter(request -> groupRequestLists.stream()
-                            .anyMatch(groupRequestList -> groupRequestList
-                                    .get(request.getCapabilities()) != null))
+                            .anyMatch(groupRequestList -> {
+                                // The unsatisfied request has all the requested capabilities.
+                                if (groupRequestList.get(request.getCapabilities()) == null) {
+                                    return false;
+                                }
+                                TelephonyNetworkRequest leading = groupRequestList.getFirst();
+                                // The unsatisfied request covers all the requested transports.
+                                return leading.getTransportTypes().length == 0
+                                        || request.getTransportTypes().length == 0
+                                        || Arrays.stream(request.getTransportTypes())
+                                        .allMatch(leading::hasTransport);
+                            }))
                     .forEach(requestList::add);
         }
         if (requestList.isEmpty()) {
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 d11b730..7f42ad0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -138,6 +138,8 @@
 import java.util.Set;
 import java.util.concurrent.Executor;
 
+import javax.annotation.Nullable;
+
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class DataNetworkControllerTest extends TelephonyTest {
@@ -1138,18 +1140,23 @@
     }
 
     private @NonNull TelephonyNetworkRequest createNetworkRequest(Integer... capabilities) {
-        return createNetworkRequest(false, capabilities);
+        return createNetworkRequest(null, capabilities);
     }
 
-    private @NonNull TelephonyNetworkRequest createNetworkRequest(boolean restricted,
+    private @NonNull TelephonyNetworkRequest createNetworkRequest(@Nullable Boolean restricted,
                                                                   Integer... capabilities) {
         NetworkCapabilities netCaps = new NetworkCapabilities();
         for (int networkCapability : capabilities) {
             netCaps.addCapability(networkCapability);
         }
 
-        if (restricted) {
-            netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+        if (restricted != null) {
+            if (restricted) {
+                netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+            }
+        } else {
+            // Data Network uses the same to define its own capabilities.
+            netCaps.maybeMarkCapabilitiesRestricted();
         }
 
         NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
@@ -1741,6 +1748,14 @@
         verify(mMockedDataNetworkControllerCallback, never())
                 .onConnectedInternetDataNetworksChanged(any());
 
+        // However, WLAN network setup shouldn't be affected
+        doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
+                .getPreferredTransportByNetworkCapability(anyInt());
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+        verify(mMockedDataNetworkControllerCallback).onConnectedInternetDataNetworksChanged(any());
+
         mIsNonTerrestrialNetwork = false;
     }
 
@@ -3319,12 +3334,20 @@
                 NetworkCapabilities.NET_CAPABILITY_IMS);
         TelephonyNetworkRequest secondTnr = createNetworkRequest(
                 NetworkCapabilities.NET_CAPABILITY_IMS);
+        TelephonyNetworkRequest thirdTnr = new TelephonyNetworkRequest(
+                new NetworkRequest((new NetworkCapabilities.Builder())
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+                        .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
+                        .build(),
+                        ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+                        NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
 
         mDataNetworkControllerUT.addNetworkRequest(firstTnr);
         processAllMessages();
 
         mDataNetworkControllerUT.removeNetworkRequest(firstTnr);
         mDataNetworkControllerUT.addNetworkRequest(secondTnr);
+        mDataNetworkControllerUT.addNetworkRequest(thirdTnr);
         processAllFutureMessages();
 
         verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
@@ -4157,6 +4180,7 @@
 
         NetworkCapabilities netCaps = new NetworkCapabilities();
         netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+        netCaps.maybeMarkCapabilitiesRestricted();
         netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
 
         NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
@@ -4209,6 +4233,7 @@
         // setup emergency data network.
         NetworkCapabilities netCaps = new NetworkCapabilities();
         netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
+        netCaps.maybeMarkCapabilitiesRestricted();
         netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
 
         NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
@@ -5097,7 +5122,8 @@
         serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
                 NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
         mDataNetworkControllerUT.addNetworkRequest(
-                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+                createNetworkRequest(true/*restricted*/,
+                        NetworkCapabilities.NET_CAPABILITY_INTERNET));
         processAllMessages();
         verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile);
 
@@ -5108,13 +5134,6 @@
                 .get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
         processAllMessages();
         verifyConnectedNetworkHasDataProfile(mEsimBootstrapImsProfile);
-
-        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
-                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
-        mDataNetworkControllerUT.addNetworkRequest(
-                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_RCS));
-        processAllMessages();
-        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
     }
 
     @Test
@@ -5153,7 +5172,7 @@
         serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
                 NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
         mDataNetworkControllerUT.addNetworkRequest(
-                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+                createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
         processAllMessages();
         // With allowed data limit unlimited, connection is allowed
         verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile);