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

Commit 6265cf8e authored by Jiashen Wang's avatar Jiashen Wang Committed by Android (Google) Code Review
Browse files

Merge "[SIM Dialog Migration] Migrate eSIM erase dialog"

parents 17eed892 ff311a21
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -516,6 +516,11 @@
                  android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
                  android:theme="@style/Transparent" />

        <activity android:name=".network.telephony.DeleteEuiccSubscriptionDialogActivity"
                  android:exported="false"
                  android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
                  android:theme="@style/Transparent" />

        <activity
            android:name="Settings$TetherSettingsActivity"
            android:label="@string/tether_settings_title_all"
+14 −0
Original line number Diff line number Diff line
@@ -11931,6 +11931,20 @@
    <!-- Body text of error message indicating the device could not disable the mobile network, due to an unknown issue. [CHAR LIMIT=NONE] -->
    <string name="privileged_action_disable_fail_text">Something went wrong and your carrier could not be disabled.</string>
    <!-- Strings for deleting eUICC subscriptions dialog activity -->
    <!-- Title on confirmation dialog asking the user if they want to erase the downloaded SIM from the device. [CHAR_LIMIT=NONE] -->
    <string name="erase_sim_dialog_title">Erase this downloaded SIM?</string>
    <!-- Body text in confirmation dialog indicating what erasing a SIM entails. [CHAR_LIMIT=NONE] -->
    <string name="erase_sim_dialog_text">Erasing this SIM removes <xliff:g id="carrier_name_a" example="Google Fi">%1$s</xliff:g> service from this device.\n\nService for <xliff:g id="carrier_name_b" example="Google Fi">%1$s</xliff:g> won\'t be canceled.</string>
    <!-- Button label to erase the eSIM [CHAR_LIMIT=20] -->
    <string name="erase_sim_confirm_button">Erase</string>
    <!-- Status message indicating the device is in the process of erasing the SIM. [CHAR_LIMIT=NONE] -->
    <string name="erasing_sim">Erasing SIM&#8230;</string>
    <!-- Title of error message indicating the device could not erase the SIM. [CHAR_LIMIT=NONE] -->
    <string name="erase_sim_fail_title">Can\'t erase SIM</string>
    <!-- Body text of error message indicating the device could not erase the SIM due to an error. [CHAR_LIMIT=NONE] -->
    <string name="erase_sim_fail_text">This SIM can\'t be erased due to an error.\n\nRestart your device and try again.</string>
    <!-- Title for Network connection request Dialog [CHAR LIMIT=60] -->
    <string name="network_connection_request_dialog_title">Connect to device</string>
    <!-- Summary for Network connection request Dialog [CHAR LIMIT=NONE] -->
+37 −0
Original line number Diff line number Diff line
@@ -31,12 +31,15 @@ import android.telephony.UiccSlotInfo;

import androidx.annotation.VisibleForTesting;

import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class SubscriptionUtil {
    private static final String TAG = "SubscriptionUtil";
@@ -287,6 +290,11 @@ public class SubscriptionUtil {
        context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
    }

    /** Starts a dialog activity to handle eSIM deletion. */
    public static void startDeleteEuiccSubscriptionDialogActivity(Context context, int subId) {
        context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
    }

    /**
     * Finds and returns a subscription with a specific subscription ID.
     * @param subscriptionManager The ProxySubscriptionManager for accessing subscription
@@ -332,4 +340,33 @@ public class SubscriptionUtil {
                || subscriptionManager.canManageSubscription(info);
        return hasCarrierPrivilegePermission;
    }

    /**
     * Finds all the available subscriptions having the same group uuid as {@code subscriptionInfo}.
     * @param subscriptionManager The SubscriptionManager for accessing subscription information
     * @param subId The id of subscription
     * @return a list of {@code SubscriptionInfo} which have the same group UUID.
     */
    public static List<SubscriptionInfo> findAllSubscriptionsInGroup(
            SubscriptionManager subscriptionManager, int subId) {

        SubscriptionInfo subscription = getSubById(subscriptionManager, subId);
        if (subscription == null) {
            return Collections.emptyList();
        }
        ParcelUuid groupUuid = subscription.getGroupUuid();
        List<SubscriptionInfo> availableSubscriptions =
                subscriptionManager.getAvailableSubscriptionInfoList();

        if (availableSubscriptions == null
                || availableSubscriptions.isEmpty()
                || groupUuid == null) {
            return Collections.singletonList(subscription);
        }

        return availableSubscriptions
                .stream()
                .filter(sub -> sub.isEmbedded() && groupUuid.equals(sub.getGroupUuid()))
                .collect(Collectors.toList());
    }
}
+149 −0
Original line number Diff line number Diff line
/*
 * 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.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;

import com.android.settings.R;
import com.android.settings.SidecarFragment;
import com.android.settings.network.SubscriptionUtil;

import java.util.List;

/** This dialog activity handles deleting eSIM profiles. */
public class DeleteEuiccSubscriptionDialogActivity extends SubscriptionActionDialogActivity
        implements SidecarFragment.Listener, ConfirmDialogFragment.OnConfirmListener {

    private static final String TAG = "DeleteEuiccSubscriptionDialogActivity";
    // Dialog tags
    private static final int DIALOG_TAG_DELETE_SIM_CONFIRMATION = 1;

    /**
     * Returns an intent of DeleteEuiccSubscriptionDialogActivity.
     *
     * @param context The context used to start the DeleteEuiccSubscriptionDialogActivity.
     * @param subId The subscription ID of the subscription needs to be deleted. If the subscription
     *     belongs to a group of subscriptions, all subscriptions from the group will be deleted.
     */
    public static Intent getIntent(Context context, int subId) {
        Intent intent = new Intent(context, DeleteEuiccSubscriptionDialogActivity.class);
        intent.putExtra(ARG_SUB_ID, subId);
        return intent;
    }

    private DeleteEuiccSubscriptionSidecar mDeleteEuiccSubscriptionSidecar;
    private List<SubscriptionInfo> mSubscriptionsToBeDeleted;
    private SubscriptionInfo mSubscriptionToBeDeleted;
    private AlertDialog mDeleteSimConfirmDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        int subId = intent.getIntExtra(ARG_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        mSubscriptionToBeDeleted = SubscriptionUtil.getSubById(mSubscriptionManager, subId);
        mSubscriptionsToBeDeleted =
                SubscriptionUtil.findAllSubscriptionsInGroup(mSubscriptionManager, subId);
        mDeleteEuiccSubscriptionSidecar = DeleteEuiccSubscriptionSidecar.get(getFragmentManager());

        if (mSubscriptionToBeDeleted == null || mDeleteEuiccSubscriptionSidecar == null) {
            Log.e(TAG, "Cannot find subscription with sub ID: " + subId);
            finish();
            return;
        }

        if (savedInstanceState == null) {
            showDeleteSimConfirmDialog();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mDeleteEuiccSubscriptionSidecar.addListener(this);
    }

    @Override
    protected void onPause() {
        mDeleteEuiccSubscriptionSidecar.removeListener(this);
        super.onPause();
    }

    @Override
    public void onStateChange(SidecarFragment fragment) {
        if (fragment == mDeleteEuiccSubscriptionSidecar) {
            handleDeleteEuiccSubscriptionSidecarStateChange();
        }
    }

    @Override
    public void onConfirm(int tag, boolean confirmed) {
        if (!confirmed) {
            finish();
            return;
        }

        switch (tag) {
            case DIALOG_TAG_DELETE_SIM_CONFIRMATION:
                Log.i(TAG, "Subscription deletion confirmed");
                showProgressDialog(getString(R.string.erasing_sim));
                mDeleteEuiccSubscriptionSidecar.run(mSubscriptionsToBeDeleted);
                break;
            default:
                Log.e(TAG, "Unrecognized confirmation dialog tag: " + tag);
                break;
        }
    }

    private void handleDeleteEuiccSubscriptionSidecarStateChange() {
        switch (mDeleteEuiccSubscriptionSidecar.getState()) {
            case SidecarFragment.State.SUCCESS:
                Log.i(TAG, "Successfully delete the subscription.");
                mDeleteEuiccSubscriptionSidecar.reset();
                dismissProgressDialog();
                finish();
                break;
            case SidecarFragment.State.ERROR:
                Log.e(TAG, "Failed to delete the subscription.");
                mDeleteEuiccSubscriptionSidecar.reset();
                showErrorDialog(
                        getString(R.string.erase_sim_fail_title),
                        getString(R.string.erase_sim_fail_text));
                break;
        }
    }

    /* Displays the eSIM deleting confirmation dialog. */
    private void showDeleteSimConfirmDialog() {
        ConfirmDialogFragment.show(
                this,
                ConfirmDialogFragment.OnConfirmListener.class,
                DIALOG_TAG_DELETE_SIM_CONFIRMATION,
                getString(R.string.erase_sim_dialog_title),
                getString(
                        R.string.erase_sim_dialog_text, mSubscriptionToBeDeleted.getDisplayName()),
                getString(R.string.erase_sim_confirm_button),
                getString(R.string.cancel));
    }
}
+77 −0
Original line number Diff line number Diff line
/*
 * 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.FragmentManager;
import android.app.PendingIntent;
import android.telephony.SubscriptionInfo;
import android.telephony.euicc.EuiccManager;
import android.util.Log;

import com.android.settings.SidecarFragment;

import java.util.ArrayList;
import java.util.List;

/** A headless fragment encapsulating long-running eSIM erasing operations. */
public class DeleteEuiccSubscriptionSidecar extends EuiccOperationSidecar {
    private static final String TAG = "DeleteEuiccSubscriptionSidecar";
    private static final String ACTION_DELETE_SUBSCRIPTION =
            "com.android.settings.network.delete_subscription";

    private List<SubscriptionInfo> mSubscriptions;

    @Override
    public String getReceiverAction() {
        return ACTION_DELETE_SUBSCRIPTION;
    }

    /** Returns a DeleteEuiccSubscriptionSidecar sidecar instance. */
    public static DeleteEuiccSubscriptionSidecar get(FragmentManager fm) {
        return SidecarFragment.get(fm, TAG, DeleteEuiccSubscriptionSidecar.class, null /* args */);
    }

    /** Starts calling EuiccManager#deleteSubscription to delete the eSIM profile. */
    public void run(List<SubscriptionInfo> subscriptions) {
        if (subscriptions == null || subscriptions.isEmpty()) {
            throw new IllegalArgumentException("Subscriptions cannot be empty.");
        }

        setState(State.RUNNING, Substate.UNUSED);

        mSubscriptions = new ArrayList<>(subscriptions);
        deleteSubscription();
    }

    @Override
    protected void onActionReceived() {
        if (getResultCode() == EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK
                && !mSubscriptions.isEmpty()) {
            // Continue to delete remaining subscriptions.
            deleteSubscription();
        } else {
            super.onActionReceived();
        }
    }

    private void deleteSubscription() {
        SubscriptionInfo subscription = mSubscriptions.remove(0);
        PendingIntent intent = createCallbackIntent();
        Log.i(TAG, "Deleting subscription ID: " + subscription.getSubscriptionId());
        mEuiccManager.deleteSubscription(subscription.getSubscriptionId(), intent);
    }
}
Loading