Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 562f7b2f authored by Antony Sargent's avatar Antony Sargent
Browse files

Add 'Erase SIM' to mobile network details page

This adds a preference to the mobile network details page that lets a
user delete an eSIM profile.

Bug: 124254555
Test: make RunSettingsRoboTests
Change-Id: I1e266566afc36ff39bf1b1c6d1db674c7c6e8648
parent 64693e31
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -102,6 +102,8 @@
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />

    <protected-broadcast android:name="com.android.settings.DELETE_SIM_PROFILE_RESULT"/>

    <application android:label="@string/settings_label"
            android:icon="@drawable/ic_launcher_settings"
            android:theme="@style/Theme.Settings"
+6 −0
Original line number Diff line number Diff line
@@ -191,4 +191,10 @@

    </PreferenceCategory>

    <Preference
        android:key="erase_sim"
        android:persistent="false"
        android:title="@string/mobile_network_erase_sim"
        settings:controller="com.android.settings.network.telephony.DeleteSimProfilePreferenceController" />

</PreferenceScreen>
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.telephony.SubscriptionInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

public class DeleteSimProfileConfirmationDialog extends InstrumentedDialogFragment implements
        DialogInterface.OnClickListener {
    public static final String TAG = "confirm_delete_sim";
    public static final String KEY_SUBSCRIPTION_INFO = "subscription_info";
    private SubscriptionInfo mInfo;

    public static DeleteSimProfileConfirmationDialog newInstance(SubscriptionInfo info) {
        final DeleteSimProfileConfirmationDialog dialog =
                new DeleteSimProfileConfirmationDialog();
        final Bundle args = new Bundle();
        args.putParcelable(KEY_SUBSCRIPTION_INFO, info);
        dialog.setArguments(args);
        return dialog;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        mInfo = getArguments().getParcelable(KEY_SUBSCRIPTION_INFO);
        Context context = getContext();
        final String message = context.getString(R.string.mobile_network_erase_sim_dialog_body,
                mInfo.getCarrierName(), mInfo.getCarrierName());
        return new AlertDialog.Builder(context)
                .setTitle(R.string.mobile_network_erase_sim_dialog_title)
                .setMessage(message)
                .setNegativeButton(R.string.cancel, null)
                .setPositiveButton(R.string.mobile_network_erase_sim_dialog_ok, this)
                .create();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            beginDeletionWithProgress();
        }
    }

    @VisibleForTesting
    void beginDeletionWithProgress() {
        final DeleteSimProfileProgressDialog progress =
                DeleteSimProfileProgressDialog.newInstance(mInfo.getSubscriptionId());
        progress.setTargetFragment(getTargetFragment(), 0);
        progress.show(getFragmentManager(), DeleteSimProfileProgressDialog.TAG);
    }

    @Override
    public int getMetricsCategory() {
        // TODO(b/131519375) - use a real id here once it's been created in the metrics proto
        return 0;
    }
}
+74 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.content.Context;
import android.telephony.SubscriptionInfo;

import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.SubscriptionUtil;

/** This controls a preference allowing the user to delete the profile for an eSIM. */
public class DeleteSimProfilePreferenceController extends BasePreferenceController {

    private SubscriptionInfo mSubscriptionInfo;
    private Fragment mParentFragment;

    public DeleteSimProfilePreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
    }

    public void init(int subscriptionId, Fragment parentFragment) {
        mParentFragment = parentFragment;

        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(
                mContext)) {
            if (info.getSubscriptionId() == subscriptionId && info.isEmbedded()) {
                mSubscriptionInfo = info;
                break;
            }
        }
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        final Preference pref = screen.findPreference(getPreferenceKey());
        pref.setOnPreferenceClickListener(p -> {
            final DeleteSimProfileConfirmationDialog dialogFragment =
                    DeleteSimProfileConfirmationDialog.newInstance(mSubscriptionInfo);
            dialogFragment.setTargetFragment(mParentFragment, 0);
            dialogFragment.show(mParentFragment.getFragmentManager(),
                    DeleteSimProfileConfirmationDialog.TAG);
            return true;
        });
    }

    @Override
    public int getAvailabilityStatus() {
        if (mSubscriptionInfo != null) {
            return AVAILABLE;
        } else {
            return CONDITIONALLY_UNAVAILABLE;
        }
    }

}
+120 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.Dialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.euicc.EuiccManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

public class DeleteSimProfileProgressDialog extends InstrumentedDialogFragment {
    public static final String TAG = "delete_sim_progress";

    // Note that this must be listed in AndroidManfiest.xml in a <protected-broadcast> tag
    @VisibleForTesting
    static final String PENDING_INTENT =
            "com.android.settings.DELETE_SIM_PROFILE_RESULT";
    private static final int PENDING_INTENT_REQUEST_CODE = 1;
    private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
    @VisibleForTesting
    static final String KEY_DELETE_STARTED = "delete_started";

    private boolean mDeleteStarted;
    private BroadcastReceiver mReceiver;

    public static DeleteSimProfileProgressDialog newInstance(int subscriptionId) {
        final DeleteSimProfileProgressDialog dialog = new DeleteSimProfileProgressDialog();
        final Bundle args = new Bundle();
        args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
        dialog.setArguments(args);
        return dialog;
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(KEY_DELETE_STARTED, mDeleteStarted);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            mDeleteStarted = savedInstanceState.getBoolean(KEY_DELETE_STARTED, false);
        }
        final Context context = getContext();
        final ProgressDialog progressDialog = new ProgressDialog(context);
        progressDialog.setMessage(
                context.getString(R.string.mobile_network_erase_sim_dialog_progress));

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                dismiss();
                final Activity activity = getActivity();
                if (activity != null && !activity.isFinishing()) {
                    activity.finish();
                }
            }
        };
        context.registerReceiver(mReceiver, new IntentFilter(PENDING_INTENT));

        if (!mDeleteStarted) {
            final PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                    PENDING_INTENT_REQUEST_CODE, new Intent(PENDING_INTENT),
                    PendingIntent.FLAG_ONE_SHOT);

            final EuiccManager euiccManager = context.getSystemService(EuiccManager.class);
            final int subId = getArguments().getInt(KEY_SUBSCRIPTION_ID);
            euiccManager.deleteSubscription(subId, pendingIntent);
            mDeleteStarted = true;
        }

        return progressDialog;
    }

    @Override
    public void onDismiss(@NonNull DialogInterface dialog) {
        if (mReceiver != null) {
            final Context context = getContext();
            if (context != null) {
                context.unregisterReceiver(mReceiver);
            }
            mReceiver = null;
        }
    }

    @Override
    public int getMetricsCategory() {
        // TODO(b/131519375) - use a real id here once it's been created in the metrics proto
        return 0;
    }
}
Loading