Authenticated confirmation before deletion of eSim

adds an authentication confirmation before deleting an eSim
this feature is turned on/off in the security page

Bug: 138861284
Test: mp settingsg
Change-Id: I32e0e3bff2091ec1097b3c37fa066d966e3373df
diff --git a/res/values/config.xml b/res/values/config.xml
index 42bc0d6..2373b25 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -206,6 +206,9 @@
         com.android.settings.intelligence
     </string>
 
+    <!-- Whether the confirmation for sim deletion is defaulted to be on or off-->
+    <bool name="config_sim_deletion_confirmation_default_on">false</bool>
+
     <!-- Package Installer package name -->
     <string name="config_package_installer_package_name" translatable="false">
         com.android.packageinstaller
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f5b1931..3a62daa 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9013,6 +9013,11 @@
     <!-- [CHAR LIMIT=60] Unlock setting for screen pinning -->
     <string name="screen_pinning_unlock_none">Lock device when unpinning</string>
 
+    <!-- [CHAR LIMIT=60] turn eSim deletion confirmation on/off  -->
+    <string name="confirm_sim_deletion_title">Confirm SIM deletion</string>
+    <!-- [CHAR LIMIT=NONE] eSim deletion confirmation description  -->
+    <string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing a downloaded SIM</string>
+
     <!-- Opening string on the dialog that prompts the user to confirm that they really want to delete their existing work profile. The administration app icon and name appear after the final colon. [CHAR LIMIT=NONE] -->
     <string name="opening_paragraph_delete_profile_unknown_company">This work profile is managed by:</string>
     <!-- Summary for work profile accounts group. [CHAR LIMIT=25] -->
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index d417bb2..7610b32 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -147,4 +147,11 @@
         android:summary="@string/summary_placeholder"
         android:fragment="com.android.settings.security.ScreenPinningSettings" />
 
-</PreferenceScreen>
+    <SwitchPreference
+        android:order="90"
+        android:key="confirm_sim_deletion"
+        android:title="@string/confirm_sim_deletion_title"
+        android:summary="@string/confirm_sim_deletion_description"
+        settings:controller="com.android.settings.security.ConfirmSimDeletionPreferenceController"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java b/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
index daabf8b..b6a78a1 100644
--- a/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
+++ b/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceController.java
@@ -18,15 +18,18 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.euicc.EuiccManager;
 
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.security.ConfirmSimDeletionPreferenceController;
+import com.android.settings.wifi.dpp.WifiDppUtils;
 
 /** This controls a preference allowing the user to delete the profile for an eSIM. */
 public class DeleteSimProfilePreferenceController extends BasePreferenceController {
@@ -34,16 +37,19 @@
     private SubscriptionInfo mSubscriptionInfo;
     private Fragment mParentFragment;
     private int mRequestCode;
+    private boolean mConfirmationDefaultOn;
 
     public DeleteSimProfilePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
+        mConfirmationDefaultOn =
+                context.getResources()
+                        .getBoolean(R.bool.config_sim_deletion_confirmation_default_on);
     }
 
     public void init(int subscriptionId, Fragment parentFragment, int requestCode) {
         mParentFragment = parentFragment;
 
-        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(
-                mContext)) {
+        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
             if (info.getSubscriptionId() == subscriptionId && info.isEmbedded()) {
                 mSubscriptionInfo = info;
                 break;
@@ -53,16 +59,27 @@
     }
 
     @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        final Preference pref = screen.findPreference(getPreferenceKey());
-        pref.setOnPreferenceClickListener(p -> {
-            final Intent intent = new Intent(EuiccManager.ACTION_DELETE_SUBSCRIPTION_PRIVILEGED);
-            intent.putExtra(EuiccManager.EXTRA_SUBSCRIPTION_ID,
-                    mSubscriptionInfo.getSubscriptionId());
-            mParentFragment.startActivityForResult(intent, mRequestCode);
-            return true;
-        });
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        boolean confirmDeletion =
+                Settings.Global.getInt(
+                                mContext.getContentResolver(),
+                                ConfirmSimDeletionPreferenceController.KEY_CONFIRM_SIM_DELETION,
+                                mConfirmationDefaultOn ? 1 : 0)
+                        == 1;
+        if (confirmDeletion) {
+            WifiDppUtils.showLockScreen(mContext, () -> deleteSim());
+        } else {
+            deleteSim();
+        }
+
+        return true;
+    }
+
+    private void deleteSim() {
+        final Intent intent = new Intent(EuiccManager.ACTION_DELETE_SUBSCRIPTION_PRIVILEGED);
+        intent.putExtra(EuiccManager.EXTRA_SUBSCRIPTION_ID, mSubscriptionInfo.getSubscriptionId());
+        mParentFragment.startActivityForResult(intent, mRequestCode);
+        // result handled in MobileNetworkSettings
     }
 
     @Override
@@ -73,5 +90,4 @@
             return CONDITIONALLY_UNAVAILABLE;
         }
     }
-
 }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 199564d..e5ba96a 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -274,9 +274,11 @@
                 break;
 
             case REQUEST_CODE_DELETE_SUBSCRIPTION:
-                final Activity activity = getActivity();
-                if (activity != null && !activity.isFinishing()) {
-                    activity.finish();
+                if (resultCode != Activity.RESULT_CANCELED) {
+                    final Activity activity = getActivity();
+                    if (activity != null && !activity.isFinishing()) {
+                        activity.finish();
+                    }
                 }
                 break;
 
diff --git a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
new file mode 100644
index 0000000..f24d8db
--- /dev/null
+++ b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * 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.security;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.TwoStatePreference;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+
+/** Enable/disable user confirmation before deleting an eSim */
+public class ConfirmSimDeletionPreferenceController extends TogglePreferenceController {
+    public static final String KEY_CONFIRM_SIM_DELETION = "confirm_sim_deletion";
+    private boolean mConfirmationDefaultOn;
+
+    public ConfirmSimDeletionPreferenceController(Context context, String key) {
+        super(context, key);
+        mConfirmationDefaultOn =
+                context.getResources()
+                        .getBoolean(R.bool.config_sim_deletion_confirmation_default_on);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        // hide if eSim is not supported on the device
+        return MobileNetworkUtils.showEuiccSettings(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    private boolean getGlobalState() {
+        return Settings.Global.getInt(
+                        mContext.getContentResolver(),
+                        KEY_CONFIRM_SIM_DELETION,
+                        mConfirmationDefaultOn ? 1 : 0)
+                == 1;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return getGlobalState();
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        Settings.Global.putInt(
+                mContext.getContentResolver(), KEY_CONFIRM_SIM_DELETION, isChecked ? 1 : 0);
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+
+        final KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+        if (!keyguardManager.isKeyguardSecure()) {
+            preference.setEnabled(false);
+            if (preference instanceof TwoStatePreference) {
+                ((TwoStatePreference) preference).setChecked(false);
+            }
+            preference.setSummary(R.string.disabled_because_no_backup_security);
+        } else {
+            preference.setEnabled(true);
+            if (preference instanceof TwoStatePreference) {
+                ((TwoStatePreference) preference).setChecked(getGlobalState());
+            }
+            preference.setSummary(R.string.confirm_sim_deletion_description);
+        }
+    }
+}
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index da8f003..effbd70 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -20,7 +20,6 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
-import android.provider.SearchIndexableResource;
 
 import com.android.settings.R;
 import com.android.settings.biometrics.face.FaceProfileStatusPreferenceController;
diff --git a/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
index ca8fcf8..401a92e 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/DeleteSimProfilePreferenceControllerTest.java
@@ -25,6 +25,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.euicc.EuiccManager;
@@ -34,6 +35,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.security.ConfirmSimDeletionPreferenceController;
 
 import org.junit.After;
 import org.junit.Before;
@@ -118,7 +120,11 @@
     public void onPreferenceClick_startsIntent() {
         mController.init(SUB_ID, mFragment, REQUEST_CODE);
         mController.displayPreference(mScreen);
-        mPreference.performClick();
+        // turn off confirmation before click
+        Settings.Global.putInt(mContext.getContentResolver(),
+                ConfirmSimDeletionPreferenceController.KEY_CONFIRM_SIM_DELETION, 0);
+
+        mController.handlePreferenceTreeClick(mPreference);
 
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mFragment).startActivityForResult(intentCaptor.capture(), eq(REQUEST_CODE));
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
index 9bf8370..a4c3672 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Activity;
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.net.NetworkPolicyManager;
@@ -111,12 +112,12 @@
     public void onActivityResult_noActivity_noCrash() {
         when(mFragment.getActivity()).thenReturn(null);
         // this should not crash
-        mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, 0, null);
+        mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, Activity.RESULT_OK, null);
     }
 
     @Test
     public void onActivityResult_deleteSubscription_activityFinishes() {
-        mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, 0, null);
+        mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, Activity.RESULT_OK, null);
         verify(mActivity).finish();
     }