[SIM Dialog Migration] Add SIM dialogs to support screen rotation

Adding dialog fragments to handle SIM enable, disable, rename, and
erase and make dialogs persistent over screen rotation.
Bug: 160819390
Test: Manually tested eSIM profile disabling.
Design: https://docs.google.com/document/d/1wb5_hoBkZVbkXGNWHbx4Jf61swjfxsJzkytiTzJosYo/edit?usp=sharing

Change-Id: I6b8c9a1c88eacdcbd3a5f0e466b1308ef639c225
diff --git a/src/com/android/settings/network/telephony/AlertDialogFragment.java b/src/com/android/settings/network/telephony/AlertDialogFragment.java
new file mode 100644
index 0000000..5940789
--- /dev/null
+++ b/src/com/android/settings/network/telephony/AlertDialogFragment.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+/** Fragment to show an alert dialog which only has the positive button. */
+public class AlertDialogFragment extends BaseDialogFragment
+        implements DialogInterface.OnClickListener {
+    private static final String TAG = "AlertDialogFragment";
+
+    // Arguments
+    private static final String ARG_TITLE = "title";
+    private static final String ARG_MSG = "msg";
+
+    /**
+     * @param activity
+     * @param title
+     * @param msg
+     */
+    public static void show(Activity activity, String title, String msg) {
+        AlertDialogFragment fragment = new AlertDialogFragment();
+        Bundle arguments = new Bundle();
+        arguments.putString(ARG_TITLE, title);
+        arguments.putString(ARG_MSG, msg);
+        fragment.setArguments(arguments);
+        fragment.show(activity.getFragmentManager(), TAG);
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(getContext())
+                        .setTitle(getArguments().getString(ARG_TITLE))
+                        .setPositiveButton(android.R.string.ok, this);
+        if (!TextUtils.isEmpty(getArguments().getString(ARG_MSG))) {
+            builder.setMessage(getArguments().getString(ARG_MSG));
+        }
+        return builder.show();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (getActivity() != null) {
+            getActivity().finish();
+        }
+        super.dismiss();
+    }
+}
diff --git a/src/com/android/settings/network/telephony/BaseDialogFragment.java b/src/com/android/settings/network/telephony/BaseDialogFragment.java
new file mode 100644
index 0000000..7da3259
--- /dev/null
+++ b/src/com/android/settings/network/telephony/BaseDialogFragment.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Base dialog fragment class with the functionality to make a fragment or an activity as a listener
+ * which can survive through the activity restarts.
+ */
+public abstract class BaseDialogFragment extends DialogFragment {
+    // Tags for the listener which receives event callbacks.
+    private static final String ARG_LISTENER_TAG = "listener_tag";
+    private static final String ARG_IN_CALLER_TAG = "in_caller_tag";
+
+    /**
+     * @param activity The caller activity or the activity attached with the fragment.
+     * @param listener The original caller, that is, the listener. The listener can be the fragment
+     *     to receive event callbacks. If it is null, will use the activity to handle the event
+     *     callback instead.
+     * @param callbackInterfaceClass The interface that the listener should implements.
+     * @param arguments The arguments bundle of the dispatcher fragment used to store the listener's
+     *     info.
+     * @param tagInCaller An integer given by the listener to distinguish the action when calling
+     *     the listener's callback function.
+     */
+    protected static <T> void setListener(
+            Activity activity,
+            @Nullable Fragment listener,
+            Class<T> callbackInterfaceClass,
+            int tagInCaller,
+            Bundle arguments) {
+        checkValidity(activity, listener, callbackInterfaceClass);
+
+        if (listener != null && listener.getParentFragment() != null) {
+            throw new IllegalArgumentException("The listener must be attached to an activity.");
+        }
+        arguments.putInt(ARG_IN_CALLER_TAG, tagInCaller);
+        if (listener != null) {
+            arguments.putString(ARG_LISTENER_TAG, listener.getTag());
+        }
+    }
+
+    /**
+     * @param callbackInterfaceClass The interface that the listener should implements.
+     * @param <T> Template type.
+     * @return The listener class.
+     */
+    @SuppressWarnings("unchecked")
+    protected <T> T getListener(Class<T> callbackInterfaceClass) {
+        Object listener;
+        String listenerTag = getArguments().getString(ARG_LISTENER_TAG);
+        if (listenerTag == null) {
+            listener = getActivity();
+        } else {
+            listener = getActivity().getFragmentManager().findFragmentByTag(listenerTag);
+        }
+        if (callbackInterfaceClass.isInstance(listener)) {
+            return (T) listener;
+        }
+        throw new IllegalArgumentException("The caller should implement the callback function.");
+    }
+
+    /** @return The tag set in the listener. */
+    protected int getTagInCaller() {
+        return getArguments().getInt(ARG_IN_CALLER_TAG);
+    }
+
+    private static <T> void checkValidity(
+            Activity activity, @Nullable Fragment listener, Class<T> callbackInterfaceClass) {
+        if (listener != null) {
+            if (!callbackInterfaceClass.isInstance(listener)) {
+                throw new IllegalArgumentException(
+                        "The listener fragment should implement the callback function.");
+            }
+        } else {
+            if (!callbackInterfaceClass.isInstance(activity)) {
+                throw new IllegalArgumentException(
+                        "The caller activity should implement the callback function.");
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/ConfirmDialogFragment.java b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
new file mode 100644
index 0000000..1ba99c5
--- /dev/null
+++ b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+
+/** Fragment to show a confirm dialog. The caller should implement onConfirmListener. */
+public class ConfirmDialogFragment extends BaseDialogFragment
+        implements DialogInterface.OnClickListener {
+    private static final String TAG = "ConfirmDialogFragment";
+    private static final String ARG_TITLE = "title";
+    private static final String ARG_MSG = "msg";
+    private static final String ARG_POS_BUTTON_STRING = "pos_button_string";
+    private static final String ARG_NEG_BUTTON_STRING = "neg_button_string";
+
+    /**
+     * Interface defining the method that will be invoked when the user has done with the dialog.
+     */
+    public interface OnConfirmListener {
+        /**
+         * @param tag The tag in the caller.
+         * @param confirmed True if the user has clicked the positive button. False if the user has
+         *     clicked the negative button or cancel the dialog.
+         */
+        void onConfirm(int tag, boolean confirmed);
+    }
+
+    /** Displays a confirmation dialog which has confirm and cancel buttons. */
+    public static <T> void show(
+            Activity activity,
+            Class<T> callbackInterfaceClass,
+            int tagInCaller,
+            String title,
+            String msg,
+            String posButtonString,
+            String negButtonString) {
+        ConfirmDialogFragment fragment = new ConfirmDialogFragment();
+        Bundle arguments = new Bundle();
+        arguments.putString(ARG_TITLE, title);
+        arguments.putCharSequence(ARG_MSG, msg);
+        arguments.putString(ARG_POS_BUTTON_STRING, posButtonString);
+        arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
+        setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
+        fragment.setArguments(arguments);
+        fragment.show(activity.getFragmentManager(), TAG);
+    }
+
+    @Override
+    public final Dialog onCreateDialog(Bundle savedInstanceState) {
+        String title = getArguments().getString(ARG_TITLE);
+        String message = getArguments().getString(ARG_MSG);
+        String posBtnString = getArguments().getString(ARG_POS_BUTTON_STRING);
+        String negBtnString = getArguments().getString(ARG_NEG_BUTTON_STRING);
+
+        Log.i("Showing dialog with title = %s", title);
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(getContext())
+                        .setTitle(title)
+                        .setPositiveButton(posBtnString, this)
+                        .setNegativeButton(negBtnString, this);
+
+        if (!TextUtils.isEmpty(message)) {
+            builder.setMessage(message);
+        }
+        AlertDialog dialog = builder.show();
+        dialog.setCanceledOnTouchOutside(false);
+        return dialog;
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        informCaller(which == DialogInterface.BUTTON_POSITIVE);
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        informCaller(false);
+    }
+
+    private void informCaller(boolean confirmed) {
+        OnConfirmListener listener = getListener(OnConfirmListener.class);
+        if (listener == null) {
+            return;
+        }
+        listener.onConfirm(getTagInCaller(), confirmed);
+    }
+}
diff --git a/src/com/android/settings/network/telephony/ProgressDialogFragment.java b/src/com/android/settings/network/telephony/ProgressDialogFragment.java
new file mode 100644
index 0000000..0d1b657
--- /dev/null
+++ b/src/com/android/settings/network/telephony/ProgressDialogFragment.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+
+/** Fragment to show a progress dialog. */
+public class ProgressDialogFragment extends DialogFragment {
+    private static final String ARG_TITLE = "title";
+
+    private static final String TAG = "ProgressDialogFragment";
+
+    private OnDismissCallback mDismissCallback;
+
+    // Host fragment is optional to implement this interface.
+    public interface OnDismissCallback {
+        // Action performed when the progress dialog is dismissed.
+        void onProgressDialogDismiss();
+    }
+
+    /**
+     * Check whether there is already a showing progress dialog. If yes and the title of the showing
+     * one is the same with the new coming one, just return and do nothing. If the title of the
+     * showing one is different from the new one, remove the showing one and create a new dialog for
+     * the new one. If there is no progress dialog right now, just create a new one.
+     */
+    public static void show(FragmentManager fm, String title, OnDismissCallback dismissCallback) {
+        ProgressDialogFragment fragment = (ProgressDialogFragment) fm.findFragmentByTag(TAG);
+        if (fragment != null
+                && TextUtils.equals(fragment.getArguments().getString(ARG_TITLE), title)) {
+            return;
+        }
+
+        FragmentTransaction ft = fm.beginTransaction();
+        if (fragment != null) {
+            ft.remove(fragment);
+        }
+
+        fragment = new ProgressDialogFragment();
+        fragment.setDismissCallback(dismissCallback);
+
+        Bundle arguments = new Bundle();
+        arguments.putString(ARG_TITLE, title);
+        fragment.setArguments(arguments);
+        fragment.show(ft, TAG);
+    }
+
+    /**
+     * Called by the caller activity or fragment when the progress is finished.
+     *
+     * @param fm The fragment manager.
+     */
+    public static void dismiss(FragmentManager fm) {
+        DialogFragment fragment = (DialogFragment) fm.findFragmentByTag(TAG);
+        if (fragment != null) {
+            fragment.dismiss();
+        }
+    }
+
+    @Override
+    @SuppressWarnings("deprecation") // ProgressDialog is deprecated but is intended UX for now
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        ProgressDialog dialog = new ProgressDialog(getActivity());
+        dialog.setCancelable(false);
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.setMessage(getArguments().getString(ARG_TITLE));
+        dialog.setOnKeyListener(
+                (progressDialog, keyCode, event) -> KeyEvent.KEYCODE_BACK == keyCode);
+
+        return dialog;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if (mDismissCallback != null) {
+            mDismissCallback.onProgressDialogDismiss();
+        }
+    }
+
+    private void setDismissCallback(OnDismissCallback dismissCallback) {
+        mDismissCallback = dismissCallback;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java b/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
index 491a776..7ff0d9a 100644
--- a/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/SubscriptionActionDialogActivity.java
@@ -16,25 +16,24 @@
 
 package com.android.settings.network.telephony;
 
-import android.R;
 import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.DialogInterface;
 import android.os.Bundle;
-
-import androidx.appcompat.app.AlertDialog;
+import android.telephony.SubscriptionManager;
 
 /** The base class for subscription action dialogs */
 public class SubscriptionActionDialogActivity extends Activity {
 
     private static final String TAG = "SubscriptionActionDialogActivity";
+    // Arguments
+    protected static final String ARG_SUB_ID = "sub_id";
 
-    private ProgressDialog mProgressDialog;
-    private AlertDialog mErrorDialog;
+    protected SubscriptionManager mSubscriptionManager;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        mSubscriptionManager = getSystemService(SubscriptionManager.class);
     }
 
     /**
@@ -43,20 +42,12 @@
      * @param message The string content should be displayed in the progress dialog.
      */
     protected void showProgressDialog(String message) {
-        if (mProgressDialog == null) {
-            mProgressDialog = ProgressDialog.show(this, null, message);
-            mProgressDialog.setCanceledOnTouchOutside(false);
-            mProgressDialog.setCancelable(false);
-        }
-        mProgressDialog.setMessage(message);
-        mProgressDialog.show();
+        ProgressDialogFragment.show(getFragmentManager(), message, null);
     }
 
     /** Dismisses the loading dialog. */
     protected void dismissProgressDialog() {
-        if (mProgressDialog != null) {
-            mProgressDialog.dismiss();
-        }
+        ProgressDialogFragment.dismiss(getFragmentManager());
     }
 
     /**
@@ -64,31 +55,8 @@
      *
      * @param title The title of the error dialog.
      * @param message The body text of the error dialog.
-     * @param positiveOnClickListener The callback function after users confirm with the error.
      */
-    protected void showErrorDialog(
-            String title, String message, DialogInterface.OnClickListener positiveOnClickListener) {
-        if (mErrorDialog == null) {
-            mErrorDialog =
-                    new AlertDialog.Builder(this)
-                            .setTitle(title)
-                            .setMessage(message)
-                            .setPositiveButton(
-                                    R.string.ok,
-                                    (dialog, which) -> {
-                                        positiveOnClickListener.onClick(dialog, which);
-                                        dismissErrorDialog();
-                                    })
-                            .create();
-        }
-        mErrorDialog.setMessage(message);
-        mErrorDialog.show();
-    }
-
-    /** Dismisses the error dialog. */
-    protected void dismissErrorDialog() {
-        if (mErrorDialog != null) {
-            mErrorDialog.dismiss();
-        }
+    protected void showErrorDialog(String title, String message) {
+        AlertDialogFragment.show(this, title, message);
     }
 }
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index 062c984..905ead0 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -17,7 +17,6 @@
 package com.android.settings.network.telephony;
 
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.UserManager;
@@ -35,15 +34,17 @@
 
 /** This dialog activity handles both eSIM and pSIM subscriptions enabling and disabling. */
 public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogActivity
-        implements SidecarFragment.Listener {
+        implements SidecarFragment.Listener, ConfirmDialogFragment.OnConfirmListener {
 
     private static final String TAG = "ToggleSubscriptionDialogActivity";
-
-    private static final String ARG_SUB_ID = "sub_id";
+    // Arguments
     private static final String ARG_enable = "enable";
+    // Dialog tags
+    private static final int DIALOG_TAG_DISABLE_SIM_CONFIRMATION = 1;
 
     /**
      * Returns an intent of ToggleSubscriptionDialogActivity.
+     *
      * @param context The context used to start the ToggleSubscriptionDialogActivity.
      * @param subId The subscription ID of the subscription needs to be toggled.
      * @param enable Whether the activity should enable or disable the subscription.
@@ -55,7 +56,6 @@
         return intent;
     }
 
-    private SubscriptionManager mSubscriptionManager;
     private SubscriptionInfo mSubInfo;
     private SwitchToEuiccSubscriptionSidecar mSwitchToEuiccSubscriptionSidecar;
     private AlertDialog mToggleSimConfirmDialog;
@@ -67,7 +67,6 @@
 
         Intent intent = getIntent();
         int subId = intent.getIntExtra(ARG_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-        mSubscriptionManager = getSystemService(SubscriptionManager.class);
 
         UserManager userManager = getSystemService(UserManager.class);
         if (!userManager.isAdminUser()) {
@@ -87,10 +86,12 @@
                 SwitchToEuiccSubscriptionSidecar.get(getFragmentManager());
         mEnable = intent.getBooleanExtra(ARG_enable, true);
 
-        if (mEnable) {
-            handleEnablingSubAction();
-        } else {
-            handleDisablingSubAction();
+        if (savedInstanceState == null) {
+            if (mEnable) {
+                handleEnablingSubAction();
+            } else {
+                showDisableSimConfirmDialog();
+            }
         }
     }
 
@@ -113,6 +114,31 @@
         }
     }
 
+    @Override
+    public void onConfirm(int tag, boolean confirmed) {
+        if (!confirmed) {
+            finish();
+            return;
+        }
+
+        switch (tag) {
+            case DIALOG_TAG_DISABLE_SIM_CONFIRMATION:
+                if (mSubInfo.isEmbedded()) {
+                    Log.i(TAG, "Disabling the eSIM profile.");
+                    showProgressDialog(
+                            getString(R.string.privileged_action_disable_sub_dialog_progress));
+                    mSwitchToEuiccSubscriptionSidecar.run(
+                            SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                    return;
+                }
+                Log.i(TAG, "Disabling the pSIM profile.");
+                break;
+            default:
+                Log.e(TAG, "Unrecognized confirmation dialog tag: " + tag);
+                break;
+        }
+    }
+
     private void handleSwitchToEuiccSubscriptionSidecarStateChange() {
         switch (mSwitchToEuiccSubscriptionSidecar.getState()) {
             case SidecarFragment.State.SUCCESS:
@@ -134,8 +160,7 @@
                 dismissProgressDialog();
                 showErrorDialog(
                         getString(R.string.privileged_action_disable_fail_title),
-                        getString(R.string.privileged_action_disable_fail_text),
-                        (dialog, which) -> finish());
+                        getString(R.string.privileged_action_disable_fail_text));
                 break;
         }
     }
@@ -146,45 +171,24 @@
         // TODO(b/160819390): Implement enabling eSIM/pSIM profile.
     }
 
-    /* Handles the disabling SIM action. */
-    private void handleDisablingSubAction() {
-        showToggleSimConfirmDialog(
-                (dialog, which) -> {
-                    if (mSubInfo.isEmbedded()) {
-                        Log.i(TAG, "Disabling the eSIM profile.");
-                        showProgressDialog(
-                                getString(R.string.privileged_action_disable_sub_dialog_progress));
-                        mSwitchToEuiccSubscriptionSidecar.run(
-                                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-                        return;
-                    }
-                    Log.i(TAG, "Disabling the pSIM profile.");
-                    // TODO(b/160819390): Implement disabling pSIM profile.
-                });
-    }
-
     /* Displays the SIM toggling confirmation dialog. */
-    private void showToggleSimConfirmDialog(
-            DialogInterface.OnClickListener positiveOnClickListener) {
-        if (mToggleSimConfirmDialog == null) {
-            mToggleSimConfirmDialog =
-                    new AlertDialog.Builder(this)
-                            .setTitle(getToggleSimConfirmDialogTitle())
-                            .setPositiveButton(
-                                    R.string.yes,
-                                    (dialog, which) -> {
-                                        positiveOnClickListener.onClick(dialog, which);
-                                        dismissToggleSimConfirmDialog();
-                                    })
-                            .setNegativeButton(
-                                    R.string.cancel,
-                                    (dialog, which) -> {
-                                        dismissToggleSimConfirmDialog();
-                                        finish();
-                                    })
-                            .create();
-        }
-        mToggleSimConfirmDialog.show();
+    private void showDisableSimConfirmDialog() {
+        String title =
+                mSubInfo == null || TextUtils.isEmpty(mSubInfo.getDisplayName())
+                        ? getString(
+                                R.string.privileged_action_disable_sub_dialog_title_without_carrier)
+                        : getString(
+                                R.string.privileged_action_disable_sub_dialog_title,
+                                mSubInfo.getDisplayName());
+
+        ConfirmDialogFragment.show(
+                this,
+                ConfirmDialogFragment.OnConfirmListener.class,
+                DIALOG_TAG_DISABLE_SIM_CONFIRMATION,
+                title,
+                null,
+                getString(R.string.yes),
+                getString(R.string.cancel));
     }
 
     /* Dismisses the SIM toggling confirmation dialog. */
@@ -193,17 +197,4 @@
             mToggleSimConfirmDialog.dismiss();
         }
     }
-
-    /* Returns the title of toggling SIM confirmation dialog. */
-    private String getToggleSimConfirmDialogTitle() {
-        if (mEnable) {
-            // TODO(b/160819390): Handle the case for enabling SIM.
-            return null;
-        }
-        return mSubInfo == null || TextUtils.isEmpty(mSubInfo.getDisplayName())
-                ? getString(R.string.privileged_action_disable_sub_dialog_title_without_carrier)
-                : getString(
-                        R.string.privileged_action_disable_sub_dialog_title,
-                        mSubInfo.getDisplayName());
-    }
 }