Keep ping request

Currently, if ping test fails, network validator revokes the ping
request from the target phone. However, this revoke is unnecessary if
ping is not required to pass - in which case the revoke causes
unnecessary disconnect and reconnect of internet.

Therefore, this change keeps the ping request if ping test is not
required.

Fix: 366318732
Test: manual voice call + data browsing
Flag: com.android.internal.telephony.flags.keep_ping_request

Change-Id: Ie412316ef1711978ff5d46ef76f820f7576ddb28
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 90fce4a..8c77ed8 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1,6 +1,17 @@
 package: "com.android.internal.telephony.flags"
 container: "system"
 
+# OWNER=linggm TARGET=25Q2
+flag {
+  name: "keep_ping_request"
+  namespace: "telephony"
+  description: "If ping test is not required to pass, keep the ping request to avoid deactivate followed by reactivate"
+  bug: "366318732"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
 # OWNER=linggm TARGET=24Q4
 flag {
   name: "keep_empty_requests_network"
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 136ac25..ed14822 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -268,7 +268,7 @@
                             SimultaneousCallingTracker.init(sContext, featureFlags);
                 }
 
-                sCellularNetworkValidator = CellularNetworkValidator.make(sContext);
+                sCellularNetworkValidator = CellularNetworkValidator.make(sContext, sFeatureFlags);
 
                 int maxActivePhones = sPhoneConfigurationManager
                         .getNumberOfModemsWithSimultaneousDataConnections();
diff --git a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
index ad1a8aa..99578cf 100644
--- a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
+++ b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
@@ -41,6 +41,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
@@ -77,7 +78,7 @@
 
     private int mState = STATE_IDLE;
     private int mSubId;
-    private boolean mReleaseAfterValidation;
+    private boolean mRequireTestPass;
 
     private ValidationCallback mValidationCallback;
     private final Context mContext;
@@ -88,6 +89,8 @@
     public ConnectivityNetworkCallback mNetworkCallback;
     private final ValidatedNetworkCache mValidatedNetworkCache = new ValidatedNetworkCache();
 
+    @NonNull
+    private final FeatureFlags mFlags;
     private class ValidatedNetworkCache {
         // A cache with fixed size. It remembers 10 most recently successfully validated networks.
         private static final int VALIDATED_NETWORK_CACHE_SIZE = 10;
@@ -206,11 +209,12 @@
     /**
      * Create instance.
      */
-    public static CellularNetworkValidator make(Context context) {
+    public static CellularNetworkValidator make(Context context,
+            @NonNull FeatureFlags featureFlags) {
         if (sInstance != null) {
             logd("createCellularNetworkValidator failed. Instance already exists.");
         } else {
-            sInstance = new CellularNetworkValidator(context);
+            sInstance = new CellularNetworkValidator(context, featureFlags);
         }
 
         return sInstance;
@@ -232,8 +236,9 @@
     }
 
     @VisibleForTesting
-    public CellularNetworkValidator(Context context) {
+    public CellularNetworkValidator(Context context, @NonNull FeatureFlags featureFlags) {
         mContext = context;
+        mFlags = featureFlags;
         mConnectivityManager = (ConnectivityManager)
                 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
@@ -242,7 +247,7 @@
      * API to start a validation
      */
     public synchronized void validate(int subId, long timeoutInMs,
-            boolean releaseAfterValidation, ValidationCallback callback) {
+            boolean requireTestPass, ValidationCallback callback) {
         // If it's already validating the same subscription, do nothing.
         if (subId == mSubId) return;
 
@@ -261,10 +266,10 @@
         mState = STATE_VALIDATING;
         mSubId = subId;
         mValidationCallback = callback;
-        mReleaseAfterValidation = releaseAfterValidation;
+        mRequireTestPass = requireTestPass;
 
         logd("Start validating subId " + mSubId + " timeoutInMs " + timeoutInMs
-                + " mReleaseAfterValidation " + mReleaseAfterValidation);
+                + " mRequireTestPass " + mRequireTestPass);
 
         mNetworkCallback = new ConnectivityNetworkCallback(subId);
 
@@ -329,8 +334,10 @@
         if (mState == STATE_VALIDATING) {
             mValidationCallback.onValidationDone(passed, mSubId);
             mState = STATE_VALIDATED;
+            boolean keepRequest = mFlags.keepPingRequest()
+                    ? (passed || !mRequireTestPass) : (!mRequireTestPass && passed);
             // If validation passed and per request to NOT release after validation, delay cleanup.
-            if (!mReleaseAfterValidation && passed) {
+            if (keepRequest) {
                 mHandler.postDelayed(this::stopValidation, 500);
             } else {
                 stopValidation();
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 3d42d35..66c2572 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -1617,7 +1617,8 @@
         mPendingSwitchNeedValidation = needValidation;
         mSetOpptSubCallback = callback;
         long validationTimeout = getValidationTimeout(subIdToValidate, needValidation);
-        mValidator.validate(subIdToValidate, validationTimeout, false, mValidationCallback);
+        mValidator.validate(subIdToValidate, validationTimeout,
+                mFlags.keepPingRequest() && mPendingSwitchNeedValidation, mValidationCallback);
     }
 
     private long getValidationTimeout(int subId, boolean needValidation) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
index bbfd7a9..9226f47 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
@@ -77,7 +77,7 @@
 
         doReturn(CAPABILITY_WITH_VALIDATION_SUPPORTED).when(mPhoneConfigurationManager)
                 .getCurrentPhoneCapability();
-        mValidatorUT = new CellularNetworkValidator(mContext);
+        mValidatorUT = new CellularNetworkValidator(mContext, mFeatureFlags);
         doReturn(new SubscriptionInfoInternal.Builder().setSimSlotIndex(0).setId(1).build())
                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
         processAllMessages();