Add new warning dialogue when user is Resetting mobile network settings.

If the user is reseting mobile network settings and have all these
conditions:
- No Wi-fi
- Has check to delete all eSIMs
- Has a least one RAC sim carrier
Then show the warning dialogue.

Test: make, manually test, atest SubSettingLauncherTest, atest ResetNetworkTest,  atest SubscriptionUtilTest
Bug: 328649510
Merged-In: I47d9b868b649b259d5e4008ec742317d2cb7cf51
Change-Id: I47d9b868b649b259d5e4008ec742317d2cb7cf51
(cherry picked from commit 147cc19b532fd52f918afd644140327d3d3d8904)
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index c33a4f8..05c8598 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -49,6 +49,7 @@
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.network.ResetNetworkRestrictionViewBuilder;
 import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settings.password.ConfirmLockPattern;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
@@ -121,6 +122,8 @@
     @VisibleForTesting
     void showFinalConfirmation() {
         Bundle args = new Bundle();
+        Context context = getContext();
+        boolean resetSims = false;
 
         // TODO(b/317276437) Simplify the logic once flag is released
         int resetOptions = ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER
@@ -142,18 +145,25 @@
             }
         }
         if (mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked()) {
-            request.setResetEsim(getContext().getPackageName())
-                   .writeIntoBundle(args);
+            resetSims = true;
+            request.setResetEsim(context.getPackageName()).writeIntoBundle(args);
         } else {
             request.writeIntoBundle(args);
         }
 
-        new SubSettingLauncher(getContext())
-                .setDestination(ResetNetworkConfirm.class.getName())
-                .setArguments(args)
-                .setTitleRes(R.string.reset_mobile_network_settings_confirm_title)
-                .setSourceMetricsCategory(getMetricsCategory())
-                .launch();
+        SubSettingLauncher launcher =
+                new SubSettingLauncher(context)
+                        .setDestination(ResetNetworkConfirm.class.getName())
+                        .setArguments(args)
+                        .setTitleRes(R.string.reset_mobile_network_settings_confirm_title)
+                        .setSourceMetricsCategory(getMetricsCategory());
+
+        if (resetSims && SubscriptionUtil.shouldShowRacDialog(context)) {
+            context.startActivity(
+                    EuiccRacConnectivityDialogActivity.getIntent(context, launcher.toIntent()));
+        } else {
+            launcher.launch();
+        }
     }
 
     /**
diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java
index e8c4219..2f1f7d2 100644
--- a/src/com/android/settings/core/SubSettingLauncher.java
+++ b/src/com/android/settings/core/SubSettingLauncher.java
@@ -17,12 +17,14 @@
 package com.android.settings.core;
 
 import android.annotation.StringRes;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 
@@ -129,14 +131,22 @@
     }
 
     public void launch() {
+        launchWithIntent(toIntent());
+    }
+
+    /**
+     * Launch sub settings activity with an intent.
+     *
+     * @param intent the settings intent we want to launch
+     */
+    public void launchWithIntent(@NonNull Intent intent) {
+        verifyIntent(intent);
         if (mLaunched) {
             throw new IllegalStateException(
                     "This launcher has already been executed. Do not reuse");
         }
         mLaunched = true;
 
-        final Intent intent = toIntent();
-
         boolean launchAsUser = mLaunchRequest.mUserHandle != null
                 && mLaunchRequest.mUserHandle.getIdentifier() != UserHandle.myUserId();
         boolean launchForResult = mLaunchRequest.mResultListener != null;
@@ -152,6 +162,28 @@
         }
     }
 
+    /**
+     * Verify intent is correctly constructed.
+     *
+     * @param intent the intent to verify
+     */
+    @VisibleForTesting
+    public void verifyIntent(@NonNull Intent intent) {
+        String className = SubSettings.class.getName();
+        ComponentName componentName = intent.getComponent();
+        String destinationName = intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT);
+        int sourceMetricsCategory =
+                intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1);
+
+        if (componentName != null && !TextUtils.equals(className, componentName.getClassName())) {
+            throw new IllegalArgumentException(String.format("Class must be: %s", className));
+        } else if (TextUtils.isEmpty(destinationName)) {
+            throw new IllegalArgumentException("Destination fragment must be set");
+        } else if (sourceMetricsCategory < 0) {
+            throw new IllegalArgumentException("Source metrics category must be set");
+        }
+    }
+
     public Intent toIntent() {
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         copyExtras(intent);
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index 782ab7d..4e89da0 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -50,8 +50,7 @@
         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             return false;
         }
-        if (SubscriptionUtil.hasSubscriptionWithRacCarrier(mContext)
-                && !SubscriptionUtil.isConnectedToWifi(mContext)) {
+        if (SubscriptionUtil.shouldShowRacDialog(mContext)) {
             EuiccRacConnectivityDialogFragment.show(mHostFragment);
         } else {
             EraseEuiccDataDialogFragment.show(mHostFragment);
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index fbe6c1f..3632ca3 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -80,6 +80,7 @@
 
     private static List<SubscriptionInfo> sAvailableResultsForTesting;
     private static List<SubscriptionInfo> sActiveResultsForTesting;
+    @Nullable private static Boolean sEnableRacDialogForTesting;
 
     @VisibleForTesting
     public static void setAvailableSubscriptionsForTesting(List<SubscriptionInfo> results) {
@@ -91,6 +92,11 @@
         sActiveResultsForTesting = results;
     }
 
+    @VisibleForTesting
+    public static void setEnableRacDialogForTesting(boolean enableRacDialog) {
+        sEnableRacDialogForTesting = enableRacDialog;
+    }
+
     public static List<SubscriptionInfo> getActiveSubscriptions(SubscriptionManager manager) {
         //TODO (b/315499317) : Refactor the subscription utils.
 
@@ -909,6 +915,19 @@
     }
 
     /**
+     * Check if warning dialog should be presented when erasing all eSIMS.
+     *
+     * @param context Context to check if any sim carrier use RAC and device Wi-Fi connection.
+     * @return {@code true} if dialog should be presented to the user.
+     */
+    public static boolean shouldShowRacDialog(@NonNull Context context) {
+        if (sEnableRacDialogForTesting != null) {
+            return sEnableRacDialogForTesting;
+        }
+        return !isConnectedToWifi(context) && hasSubscriptionWithRacCarrier(context);
+    }
+
+    /**
      * Retrieves NetworkCapabilities for the active network.
      *
      * @param context context
diff --git a/src/com/android/settings/network/telephony/EuiccRacConnectivityDialogActivity.java b/src/com/android/settings/network/telephony/EuiccRacConnectivityDialogActivity.java
index cb4ab18..d439d4f 100644
--- a/src/com/android/settings/network/telephony/EuiccRacConnectivityDialogActivity.java
+++ b/src/com/android/settings/network/telephony/EuiccRacConnectivityDialogActivity.java
@@ -23,21 +23,28 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
 
 import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
 
 /** This dialog activity advise the user to have connectivity if the eSIM uses a RAC. */
-public class EuiccRacConnectivityDialogActivity extends SubscriptionActionDialogActivity
+public class EuiccRacConnectivityDialogActivity extends FragmentActivity
         implements WarningDialogFragment.OnConfirmListener {
 
     private static final String TAG = "EuiccRacConnectivityDialogActivity";
     // Dialog tags
     private static final int DIALOG_TAG_ERASE_ANYWAY_CONFIRMATION = 1;
+    private static final String ARG_SUB_ID = "sub_id";
+    private static final String ARG_RESET_MOBILE_NETWORK_ID = "reset_mobile_netword_id";
 
     private int mSubId;
+    @Nullable
+    private Intent mResetMobileNetworkIntent;
 
     /**
-     * Returns an intent of EuiccRacConnectivityDialogActivity.
+     * Returns an intent of EuiccRacConnectivityDialogActivity for Settings: erase eSIM.
      *
      * @param context The context used to start the EuiccRacConnectivityDialogActivity.
      * @param subId The subscription ID of the subscription needs to be deleted. If the subscription
@@ -50,12 +57,29 @@
         return intent;
     }
 
+    /**
+     * Returns an intent of EuiccRacConnectivityDialogActivity for Reset: Mobile network settings.
+     *
+     * @param context The context used to start the EuiccRacConnectivityDialogActivity.
+     * @param resetMobileNetworkIntent The intent that will continue the reset of mobile network
+     *     settings.
+     */
+    @NonNull
+    public static Intent getIntent(@NonNull Context context,
+            @NonNull Intent resetMobileNetworkIntent) {
+        Intent intent = new Intent(context, EuiccRacConnectivityDialogActivity.class);
+        intent.putExtra(ARG_RESET_MOBILE_NETWORK_ID, resetMobileNetworkIntent);
+        return intent;
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         Intent intent = getIntent();
         mSubId = intent.getIntExtra(ARG_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        mResetMobileNetworkIntent =
+                intent.getParcelableExtra(ARG_RESET_MOBILE_NETWORK_ID, Intent.class);
 
         if (savedInstanceState == null) {
             showConnectivityWarningDialog();
@@ -72,8 +96,13 @@
         switch (tag) {
             case DIALOG_TAG_ERASE_ANYWAY_CONFIRMATION:
                 finish();
-                Log.i(TAG, "Show dialogue activity that handles deleting eSIM profiles");
-                startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(this, mSubId));
+                if (mResetMobileNetworkIntent != null) {
+                    Log.i(TAG, "Show fragment activity that handles mobile network settings reset");
+                    new SubSettingLauncher(this).launchWithIntent(mResetMobileNetworkIntent);
+                } else {
+                    Log.i(TAG, "Show dialogue activity that handles deleting eSIM profiles");
+                    startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(this, mSubId));
+                }
                 break;
             default:
                 Log.e(TAG, "Unrecognized confirmation dialog tag: " + tag);
diff --git a/tests/robotests/src/com/android/settings/ResetNetworkTest.java b/tests/robotests/src/com/android/settings/ResetNetworkTest.java
index 0c2c7e8..db724c4 100644
--- a/tests/robotests/src/com/android/settings/ResetNetworkTest.java
+++ b/tests/robotests/src/com/android/settings/ResetNetworkTest.java
@@ -27,6 +27,9 @@
 import android.view.View;
 import android.widget.CheckBox;
 
+import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -51,6 +54,7 @@
     @Test
     @Ignore
     public void showFinalConfirmation_checkboxVisible_eraseEsimChecked() {
+        SubscriptionUtil.setEnableRacDialogForTesting(true);
         mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
         mResetNetwork.mEsimCheckbox.setChecked(true);
 
@@ -62,6 +66,21 @@
     }
 
     @Test
+    public void showFinalConfirmation_checkboxVisible_eraseEsimChecked_showRacWarningDialog() {
+        SubscriptionUtil.setEnableRacDialogForTesting(true);
+        mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
+        mResetNetwork.mEsimCheckbox.setChecked(true);
+
+        mResetNetwork.showFinalConfirmation();
+
+        Intent intent = shadowOf(mActivity).getNextStartedActivity();
+
+        assertThat(intent).isNotNull();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(
+                EuiccRacConnectivityDialogActivity.class.getName());
+    }
+
+    @Test
     public void showFinalConfirmation_checkboxVisible_eraseEsimUnchecked() {
         mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
         mResetNetwork.mEsimCheckbox.setChecked(false);
diff --git a/tests/robotests/src/com/android/settings/core/SubSettingLauncherTest.java b/tests/robotests/src/com/android/settings/core/SubSettingLauncherTest.java
index bfc8ea6..e7051d2 100644
--- a/tests/robotests/src/com/android/settings/core/SubSettingLauncherTest.java
+++ b/tests/robotests/src/com/android/settings/core/SubSettingLauncherTest.java
@@ -67,7 +67,7 @@
     }
 
     @Test(expected = IllegalStateException.class)
-    public void cannotReuseLauncher() {
+    public void cannotReuseLauncher_launchMethod() {
         final SubSettingLauncher launcher = spy(new SubSettingLauncher(mContext))
                 .setDestination(SubSettingLauncherTest.class.getName())
                 .setSourceMetricsCategory(123);
@@ -77,6 +77,43 @@
     }
 
     @Test(expected = IllegalArgumentException.class)
+    public void verifyIntent_noDestination() {
+        final SubSettingLauncher launcher =
+                spy(new SubSettingLauncher(mContext))
+                        .setSourceMetricsCategory(123);
+        doNothing().when(launcher).launch(any(Intent.class));
+        launcher.launchWithIntent(launcher.toIntent());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void verifyIntent_noMetricsCategory() {
+        final SubSettingLauncher launcher = spy(new SubSettingLauncher(mContext))
+                .setDestination(SubSettingLauncherTest.class.getName());
+        doNothing().when(launcher).launch(any(Intent.class));
+        launcher.launchWithIntent(launcher.toIntent());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void verifyIntent_notTheCorrectClass() {
+        final SubSettingLauncher launcher = spy(new SubSettingLauncher(mContext))
+                .setDestination(SubSettingLauncherTest.class.getName())
+                .setSourceMetricsCategory(123);
+        doNothing().when(launcher).launch(any(Intent.class));
+        launcher.launchWithIntent(new Intent(Intent.ACTION_MAIN));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void cannotReuseLauncher_launchAndLaunchWithIntentMethod() {
+        final SubSettingLauncher launcher =
+                spy(new SubSettingLauncher(mContext))
+                        .setDestination(SubSettingLauncherTest.class.getName())
+                        .setSourceMetricsCategory(123);
+        doNothing().when(launcher).launch(any(Intent.class));
+        launcher.launchWithIntent(launcher.toIntent());
+        launcher.launch();
+    }
+
+    @Test(expected = IllegalArgumentException.class)
     public void launch_noSourceMetricsCategory_shouldCrash() {
         final SubSettingLauncher launcher = spy(new SubSettingLauncher(mContext))
                 .setDestination(SubSettingLauncherTest.class.getName());
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 6c946e5..6df281a 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -649,6 +649,39 @@
         assertFalse(SubscriptionUtil.isConnectedToWifi(mContext));
     }
 
+    @Test
+    public void hasSubscriptionWithRacCarrier_hasNoWifi_showRacDialog_returnTrue() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+        addNetworkTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
+
+        assertTrue(SubscriptionUtil.shouldShowRacDialog(mContext));
+    }
+
+    @Test
+    public void hasSubscriptionWithRacCarrier_hasWifi_showRacDialog_returnFalse() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getCarrierId()).thenReturn(RAC_CARRIER_ID);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+        addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+
+        assertFalse(SubscriptionUtil.shouldShowRacDialog(mContext));
+    }
+
+    @Test
+    public void hasNoSubscriptionWithRacCarrier_hasNoWifi_showRacDialog_returnFalse() {
+        when(mResources.getIntArray(anyInt())).thenReturn(CARRIERS_THAT_USE_RAC);
+        final SubscriptionInfo info = mock(SubscriptionInfo.class);
+        when(info.getCarrierId()).thenReturn(NO_RAC_CARRIER_ID);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+        addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+
+        assertFalse(SubscriptionUtil.shouldShowRacDialog(mContext));
+    }
+
     private void addNetworkTransportType(int networkType) {
         mNetworkCapabilities =
                 new NetworkCapabilities.Builder().addTransportType(networkType).build();