Skip handling validation status for non default data connections

The non default data connections doesn't go through network validation
procedure but connectivity service report validation success always.
DcTracker incorrectly noted this as a good signal and later triggered
a recovery when bad network is reported for default data connection.
This causes unnecessary data stall recovery and causes lab test failure.

This CL adds a check to handle network validation events only from
data connections that goes through network validation.

Bug: 135292998
Test: atest com.android.internal.telephony.dataconnection.DcTrackerTest
Change-Id: Iebe429f24fb16fd2748ac63adf6f875c4b398d7d
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 9d4e39a..adfbca3 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -1279,6 +1279,16 @@
         return result;
     }
 
+    /** @return {@code true} if validation is required, {@code false} otherwise. */
+    public boolean isValidationRequired() {
+        final NetworkCapabilities nc = getNetworkCapabilities();
+        return nc != null
+                && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+                && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+    }
+
     /**
      * @return {@code True} if 464xlat should be skipped.
      */
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index b36a490..6775dab 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -170,7 +170,7 @@
         DcTracker dct = mPhone.getDcTracker(mTransportType);
         if (dct != null) {
             Message msg = dct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                    status, 0, redirectUrl);
+                    status, mDataConnection.getCid(), redirectUrl);
             msg.sendToTarget();
         }
     }
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 66c8e00..86dbef1 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -2919,10 +2919,11 @@
      *
      * @param status One of {@code NetworkAgent.VALID_NETWORK} or
      * {@code NetworkAgent.INVALID_NETWORK}.
+     * @param cid context id {@code cid}
      * @param redirectUrl If the Internet probe was redirected, this
      * is the destination it was redirected to, otherwise {@code null}
      */
-    private void onNetworkStatusChanged(int status, String redirectUrl) {
+    private void onNetworkStatusChanged(int status, int cid, String redirectUrl) {
         if (!TextUtils.isEmpty(redirectUrl)) {
             Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
             intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, redirectUrl);
@@ -2930,6 +2931,7 @@
             log("Notify carrier signal receivers with redirectUrl: " + redirectUrl);
         } else {
             final boolean isValid = status == NetworkAgent.VALID_NETWORK;
+            final DataConnection dc = getDataConnectionByContextId(cid);
             if (!mDsRecoveryHandler.isRecoveryOnBadNetworkEnabled()) {
                 if (DBG) log("Skip data stall recovery on network status change with in threshold");
                 return;
@@ -2938,7 +2940,9 @@
                 if (DBG) log("Skip data stall recovery on non WWAN");
                 return;
             }
-            mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+            if (dc != null && dc.isValidationRequired()) {
+                mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+            }
         }
     }
 
@@ -3588,8 +3592,9 @@
 
             case DctConstants.EVENT_NETWORK_STATUS_CHANGED:
                 int status = msg.arg1;
+                int cid = msg.arg2;
                 String url = (String) msg.obj;
-                onNetworkStatusChanged(status, url);
+                onNetworkStatusChanged(status, cid, url);
                 break;
 
             case DctConstants.EVENT_RADIO_AVAILABLE:
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 0cdcb49..7b87d71 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -46,6 +46,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
 import android.telephony.emergency.EmergencyNumber;
@@ -1174,6 +1175,14 @@
             }
         }
 
+        // Store different cids to simulate concurrent IMS and default data calls
+        if ((dataProfile.getSupportedApnTypesBitmask() & ApnSetting.TYPE_IMS)
+            == ApnSetting.TYPE_IMS) {
+            mSetupDataCallResult.cid = 0;
+        } else {
+            mSetupDataCallResult.cid = 1;
+        }
+
         DataCallResponse response = RIL.convertDataCallResult(mSetupDataCallResult);
         if (mDcSuccess) {
             resultSuccess(result, response);
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 4009704..89cedfe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -1571,16 +1571,17 @@
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
+        waitForMs(200);
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.VALID_NETWORK, 0, null));
+                NetworkAgent.VALID_NETWORK, 1, null));
         waitForMs(200);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.INVALID_NETWORK, 0, null));
+                NetworkAgent.INVALID_NETWORK, 1, null));
         waitForMs(200);
 
         // Verify that its no-op when the new data stall detection feature is disabled
@@ -1612,16 +1613,17 @@
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
+        waitForMs(200);
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.VALID_NETWORK, 0, null));
+                NetworkAgent.VALID_NETWORK, 1, null));
         waitForMs(200);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.INVALID_NETWORK, 0, null));
+                NetworkAgent.INVALID_NETWORK, 1, null));
         waitForMs(200);
 
         verify(mSimulatedCommandsVerifier, times(1)).getDataCallList(any(Message.class));
@@ -1654,11 +1656,12 @@
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                 any(Message.class));
+        waitForMs(200);
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.INVALID_NETWORK, 0, null));
+                NetworkAgent.INVALID_NETWORK, 1, null));
         waitForMs(200);
 
         // expected tear down all DataConnections
@@ -1698,7 +1701,7 @@
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.INVALID_NETWORK, 0, null));
+                NetworkAgent.INVALID_NETWORK, 1, null));
         waitForMs(200);
 
         // expected to get preferred network type
@@ -1735,7 +1738,7 @@
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
         mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
-                NetworkAgent.INVALID_NETWORK, 0, null));
+                NetworkAgent.INVALID_NETWORK, 1, null));
         waitForMs(200);
 
         // expected to get preferred network type