diff --git a/res/values/strings.xml b/res/values/strings.xml index 03acf60a94b..b703980a099 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4321,6 +4321,20 @@ result from their use. + + + There is an issue erasing the downloaded SIMs + + Please reboot the device and try again. If you continue factory reset, the downloaded SIMs may remain on the device. + + Reboot + + Continue factory reset? + + Downloaded SIMs will remain on device. + + Factory reset + Your device and personal data are more vulnerable diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java index 3ace43621b6..676789edc8d 100644 --- a/src/com/android/settings/MasterClearConfirm.java +++ b/src/com/android/settings/MasterClearConfirm.java @@ -21,20 +21,26 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.app.ActionBar; import android.app.Activity; +import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.admin.DevicePolicyManager; import android.app.admin.FactoryResetProtectionPolicy; import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; +import android.os.PowerManager; import android.os.UserHandle; import android.os.UserManager; import android.service.oemlock.OemLockManager; import android.service.persistentdata.PersistentDataBlockManager; +import android.telephony.TelephonyManager; +import android.telephony.UiccSlotInfo; +import android.telephony.euicc.EuiccManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -54,6 +60,8 @@ import com.google.android.setupcompat.template.FooterButton.ButtonType; import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupdesign.GlifLayout; +import java.util.Arrays; + /** * Confirm and execute a reset of the device to a clean "just out of the box" * state. Multiple confirmations are required: first, a general "are you sure @@ -83,6 +91,89 @@ public class MasterClearConfirm extends InstrumentedFragment { return; } + // If the eSIM slot is in an error state, display a dialog to warn users that their eSIM + // profiles may not be fully deleted during FDR. + if (shouldShowEsimEraseFailureDialog()) { + Log.e(TAG, "eUICC card is in an error state. Display a dialog to warn the user."); + showEsimErrorDialog(); + return; + } + + performFactoryReset(); + } + + /** + * Returns true if the user choose to erase eSIM profile but the eUICC card is in an error + * state. + */ + private boolean shouldShowEsimEraseFailureDialog() { + EuiccManager euiccManager = getActivity().getSystemService(EuiccManager.class); + TelephonyManager telephonyManager = + getActivity().getSystemService(TelephonyManager.class); + + if (euiccManager == null || !euiccManager.isEnabled()) { + Log.i( + TAG, + "eSIM manager is disabled. No need to check eSIM slot before FDR."); + return false; + } + if (!mEraseEsims) { + Log.i( + TAG, + "eSIM does not need to be reset. No need to check eSIM slot before FDR."); + return false; + } + UiccSlotInfo[] slotInfos = telephonyManager.getUiccSlotsInfo(); + if (slotInfos == null) { + Log.i(TAG, "Unable to get UICC slots."); + return false; + } + // If getIsEuicc() returns false for an eSIM slot, it means the eSIM is in the error + // state. + return Arrays.stream(slotInfos).anyMatch( + slot -> slot != null && !slot.isRemovable() && !slot.getIsEuicc()); + } + + private void showEsimErrorDialog() { + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.fdr_esim_failure_title) + .setMessage(R.string.fdr_esim_failure_text) + .setNeutralButton(R.string.dlg_cancel, + (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + }) + .setNegativeButton(R.string.fdr_esim_failure_reboot_btn, + (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + PowerManager pm = (PowerManager) getActivity() + .getSystemService(Context.POWER_SERVICE); + pm.reboot(null); + }) + .setPositiveButton(R.string.lockpassword_continue_label, + (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + showContinueFdrDialog(); + }) + .show(); + } + + private void showContinueFdrDialog() { + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.fdr_continue_title) + .setMessage(R.string.fdr_continue_text) + .setNegativeButton(R.string.dlg_cancel, + (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + }) + .setPositiveButton(R.string.fdr_continue_btn, + (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + performFactoryReset(); + }) + .show(); + } + + private void performFactoryReset() { final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager) getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);