From 7e04453c74a284017287f8f93b3ed584c925dedc Mon Sep 17 00:00:00 2001 From: Jiashen Wang Date: Thu, 1 Oct 2020 18:28:50 -0700 Subject: [PATCH] [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 --- .../telephony/AlertDialogFragment.java | 68 ++++++++++ .../network/telephony/BaseDialogFragment.java | 102 +++++++++++++++ .../telephony/ConfirmDialogFragment.java | 107 ++++++++++++++++ .../telephony/ProgressDialogFragment.java | 106 ++++++++++++++++ .../SubscriptionActionDialogActivity.java | 52 ++------ .../ToggleSubscriptionDialogActivity.java | 117 ++++++++---------- 6 files changed, 447 insertions(+), 105 deletions(-) create mode 100644 src/com/android/settings/network/telephony/AlertDialogFragment.java create mode 100644 src/com/android/settings/network/telephony/BaseDialogFragment.java create mode 100644 src/com/android/settings/network/telephony/ConfirmDialogFragment.java create mode 100644 src/com/android/settings/network/telephony/ProgressDialogFragment.java 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 00000000000..5940789673e --- /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 00000000000..7da325910e9 --- /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 void setListener( + Activity activity, + @Nullable Fragment listener, + Class 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 Template type. + * @return The listener class. + */ + @SuppressWarnings("unchecked") + protected T getListener(Class 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 void checkValidity( + Activity activity, @Nullable Fragment listener, Class 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 00000000000..1ba99c567bf --- /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 void show( + Activity activity, + Class 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 00000000000..0d1b65716db --- /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 491a776afaa..7ff0d9a874c 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 @@ public class SubscriptionActionDialogActivity extends Activity { * @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 @@ public class SubscriptionActionDialogActivity extends Activity { * * @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 062c9846b2a..905ead0f92c 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 @@ import com.android.settings.network.SwitchToEuiccSubscriptionSidecar; /** 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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc return intent; } - private SubscriptionManager mSubscriptionManager; private SubscriptionInfo mSubInfo; private SwitchToEuiccSubscriptionSidecar mSwitchToEuiccSubscriptionSidecar; private AlertDialog mToggleSimConfirmDialog; @@ -67,7 +67,6 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc 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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc 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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc } } + @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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc 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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc // 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 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc 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()); - } }