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

Commit 9c3ff48c authored by Xiangyu/Malcolm Chen's avatar Xiangyu/Malcolm Chen Committed by Gerrit Code Review
Browse files

Merge changes from topics "131919246", "132631355"

* changes:
  Fix bug of disabling grouped CBRS during profile switch on primary SIM
  Update isEmptyProfile of UiccProfile.
  Triggering notifications when dual CDMA SIM combinations are detected
parents a521114a 0cfffde1
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -3457,8 +3457,9 @@ public class GsmCdmaPhone extends Phone {
        }
    }

    //return true if either CSIM or RUIM app is present
    private boolean isCdmaSubscriptionAppPresent(){
    // Return true if either CSIM or RUIM app is present
    @Override
    public boolean isCdmaSubscriptionAppPresent() {
        UiccCardApplication cdmaApplication =
                mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
        return cdmaApplication != null && (cdmaApplication.getType() == AppType.APPTYPE_CSIM ||
+118 −17
Original line number Diff line number Diff line
@@ -22,10 +22,15 @@ import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELE
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE;
import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_NAMES;
import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE;
import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA;
import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE;
import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
@@ -36,6 +41,8 @@ import android.provider.Settings.SettingNotFoundException;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
@@ -247,6 +254,7 @@ public class MultiSimSettingController extends Handler {
        if (DBG) log("onAllSubscriptionsLoaded");
        updateDefaults(/*init*/ true);
        disableDataForNonDefaultNonOpportunisticSubscriptions();
        deactivateGroupedOpportunisticSubscriptionIfNeeded();
    }

    /**
@@ -259,6 +267,7 @@ public class MultiSimSettingController extends Handler {
        if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;
        updateDefaults(/*init*/ false);
        disableDataForNonDefaultNonOpportunisticSubscriptions();
        deactivateGroupedOpportunisticSubscriptionIfNeeded();
    }

    /**
@@ -392,7 +401,7 @@ public class MultiSimSettingController extends Handler {
                mSubController.getDefaultSmsSubId(),
                (newValue -> mSubController.setDefaultSmsSubId(newValue)));

        showSimSelectDialogIfNeeded(change, dataSelected, voiceSelected, smsSelected);
        sendSubChangeNotificationIfNeeded(change, dataSelected, voiceSelected, smsSelected);
    }

    @PrimarySubChangeType
@@ -440,11 +449,41 @@ public class MultiSimSettingController extends Handler {
        }
    }

    private void showSimSelectDialogIfNeeded(int change, boolean dataSelected,
    private void sendSubChangeNotificationIfNeeded(int change, boolean dataSelected,
            boolean voiceSelected, boolean smsSelected) {
        @TelephonyManager.DefaultSubscriptionSelectType
        int simSelectDialogType = getSimSelectDialogType(
                change, dataSelected, voiceSelected, smsSelected);
        SimCombinationWarningParams simCombinationParams = getSimCombinationWarningParams(change);

        if (simSelectDialogType != EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE
                || simCombinationParams.mWarningType != EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE) {
            log("[sendSubChangeNotificationIfNeeded] showing dialog type "
                    + simSelectDialogType);
            log("[sendSubChangeNotificationIfNeeded] showing sim warning "
                    + simCombinationParams.mWarningType);
            Intent intent = new Intent();
            intent.setAction(ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
            intent.setClassName("com.android.settings",
                    "com.android.settings.sim.SimSelectNotification");
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, simSelectDialogType);
            if (simSelectDialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
                intent.putExtra(EXTRA_SUBSCRIPTION_ID, mPrimarySubList.get(0));
            }

            intent.putExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE, simCombinationParams.mWarningType);
            if (simCombinationParams.mWarningType == EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA) {
                intent.putExtra(EXTRA_SIM_COMBINATION_NAMES, simCombinationParams.mSimNames);
            }
            mContext.sendBroadcast(intent);
        }
    }

    private int getSimSelectDialogType(int change, boolean dataSelected,
            boolean voiceSelected, boolean smsSelected) {
        int dialogType = EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE;
        int preferredSubId = INVALID_SUBSCRIPTION_ID;

        // If a primary subscription is removed and only one is left active, ask user
        // for preferred sub selection if any default setting is not set.
@@ -453,26 +492,56 @@ public class MultiSimSettingController extends Handler {
        if (mPrimarySubList.size() == 1 && change == PRIMARY_SUB_REMOVED
                && (!dataSelected || !smsSelected || !voiceSelected)) {
            dialogType = EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
            preferredSubId = mPrimarySubList.get(0);
        } else if (mPrimarySubList.size() > 1 && (change == PRIMARY_SUB_REMOVED
                || change == PRIMARY_SUB_ADDED || change == PRIMARY_SUB_SWAPPED)) {
        } else if (mPrimarySubList.size() > 1 && isUserVisibleChange(change)) {
            // If change is SWAPPED_IN_GROUP or MARKED_OPPT orINITIALIZED, don't ask user again.
            dialogType = EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA;
        }

        if (dialogType != EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE) {
            log("[showSimSelectDialogIfNeeded] showing dialog type " + dialogType);
            Intent intent = new Intent();
            intent.setAction(ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
            intent.setClassName("com.android.settings",
                    "com.android.settings.sim.SimSelectNotification");
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, dialogType);
            if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
                intent.putExtra(EXTRA_SUBSCRIPTION_ID, preferredSubId);
        return dialogType;
    }
            mContext.sendBroadcast(intent);

    private class SimCombinationWarningParams {
        @TelephonyManager.SimCombinationWarningType
        int mWarningType = EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE;
        String mSimNames;
    }

    private SimCombinationWarningParams getSimCombinationWarningParams(int change) {
        SimCombinationWarningParams params = new SimCombinationWarningParams();
        // If it's single SIM active, no SIM combination warning is needed.
        if (mPrimarySubList.size() <= 1) return params;
        // If it's no primary SIM change or it's not user visible change
        // (initialized or swapped in a group), no SIM combination warning is needed.
        if (!isUserVisibleChange(change)) return params;

        List<String> simNames = new ArrayList<>();
        int cdmaPhoneCount = 0;
        for (int subId : mPrimarySubList) {
            Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
            // If a dual CDMA SIM combination warning is needed.
            if (phone != null && phone.isCdmaSubscriptionAppPresent()) {
                cdmaPhoneCount++;
                String simName = mSubController.getActiveSubscriptionInfo(
                        subId, mContext.getOpPackageName()).getDisplayName().toString();
                if (TextUtils.isEmpty(simName)) {
                    // Fall back to carrier name.
                    simName = phone.getCarrierName();
                }
                simNames.add(simName);
            }
        }

        if (cdmaPhoneCount > 1) {
            params.mWarningType = EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA;
            params.mSimNames = String.join(" & ", simNames);
        }

        return params;
    }

    private boolean isUserVisibleChange(int change) {
        return (change == PRIMARY_SUB_ADDED || change == PRIMARY_SUB_REMOVED
                || change == PRIMARY_SUB_SWAPPED);
    }

    private void disableDataForNonDefaultNonOpportunisticSubscriptions() {
@@ -580,6 +649,38 @@ public class MultiSimSettingController extends Handler {
        return SubscriptionManager.isValidSubscriptionId(newValue);
    }

    // When a primary and its grouped opportunistic subscriptions were active, and the primary
    // subscription gets deactivated or removed, we need to automatically disable the grouped
    // opportunistic subscription, which will be marked isGroupDisabled as true by SubController.
    private void deactivateGroupedOpportunisticSubscriptionIfNeeded() {
        if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return;

        List<SubscriptionInfo> opptSubList = mSubController.getOpportunisticSubscriptions(
                mContext.getOpPackageName());

        if (ArrayUtils.isEmpty(opptSubList)) return;

        for (SubscriptionInfo info : opptSubList) {
            if (info.isGroupDisabled() && mSubController.isActiveSubId(info.getSubscriptionId())) {
                log("[deactivateGroupedOpptSubIfNeeded] "
                        + "Deactivating grouped opportunistic subscription "
                        + info.getSubscriptionId());
                deactivateSubscription(info);
            }
        }
    }

    private void deactivateSubscription(SubscriptionInfo info) {
        // TODO: b/133379187 have a way to deactivate pSIM.
        if (info.isEmbedded()) {
            log("[deactivateSubscription] eSIM profile " + info.getSubscriptionId());
            EuiccManager euiccManager = (EuiccManager)
                    mContext.getSystemService(Context.EUICC_SERVICE);
            euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
                    PendingIntent.getService(mContext, 0, new Intent(), 0));
        }
    }

    private void log(String msg) {
        Log.d(LOG_TAG, msg);
    }
+5 −0
Original line number Diff line number Diff line
@@ -4036,6 +4036,11 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return mDcTrackers.get(transportType);
    }

    // Return true if either CSIM or RUIM app is present. By default it returns false.
    public boolean isCdmaSubscriptionAppPresent() {
        return false;
    }

    /**
     * Get the HAL version.
     *
+11 −26
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
@@ -114,6 +115,7 @@ public class SubscriptionController extends ISub.Stub {

    /* Similar to mCacheActiveSubInfoList but only caching opportunistic subscriptions. */
    private List<SubscriptionInfo> mCacheOpportunisticSubInfoList = new ArrayList<>();
    private AtomicBoolean mOpptSubInfoListChangedDirtyBit = new AtomicBoolean();

    private static final Comparator<SubscriptionInfo> SUBSCRIPTION_INFO_COMPARATOR =
            (arg0, arg1) -> {
@@ -303,6 +305,10 @@ public class SubscriptionController extends ISub.Stub {
        synchronized (mSubInfoListLock) {
            subInfos = new ArrayList<>(mCacheActiveSubInfoList);
        }

        if (mOpptSubInfoListChangedDirtyBit.getAndSet(false)) {
            notifyOpportunisticSubscriptionInfoChanged();
        }
        metrics.updateActiveSubscriptionInfoList(subInfos);
    }

@@ -717,7 +723,7 @@ public class SubscriptionController extends ISub.Stub {
            }

            // Refresh cached opportunistic sub list and detect whether it's changed.
            opptSubListChanged = refreshCachedOpportunisticSubscriptionInfoList();
            refreshCachedOpportunisticSubscriptionInfoList();

            if (DBG_CACHE) {
                if (!mCacheActiveSubInfoList.isEmpty()) {
@@ -730,11 +736,6 @@ public class SubscriptionController extends ISub.Stub {
                }
            }
        }

        // Send notification outside synchronization.
        if (opptSubListChanged) {
            notifyOpportunisticSubscriptionInfoChanged();
        }
    }

    /**
@@ -3558,7 +3559,7 @@ public class SubscriptionController extends ISub.Stub {
        }
    }

    private boolean refreshCachedOpportunisticSubscriptionInfoList() {
    private void refreshCachedOpportunisticSubscriptionInfoList() {
        synchronized (mSubInfoListLock) {
            List<SubscriptionInfo> oldOpptCachedList = mCacheOpportunisticSubInfoList;

@@ -3578,13 +3579,6 @@ public class SubscriptionController extends ISub.Stub {
            for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
                if (shouldDisableSubGroup(info.getGroupUuid())) {
                    info.setGroupDisabled(true);
                    // TODO: move it to ONS.
                    if (isActiveSubId(info.getSubscriptionId()) && isSubInfoReady()) {
                        logd("[refreshCachedOpportunisticSubscriptionInfoList] "
                                + "Deactivating grouped opportunistic subscription "
                                + info.getSubscriptionId());
                        deactivateSubscription(info);
                    }
                }
            }

@@ -3599,7 +3593,9 @@ public class SubscriptionController extends ISub.Stub {
                }
            }

            return !oldOpptCachedList.equals(mCacheOpportunisticSubInfoList);
            if (!oldOpptCachedList.equals(mCacheOpportunisticSubInfoList)) {
                mOpptSubInfoListChangedDirtyBit.set(true);
            }
        }
    }

@@ -3615,17 +3611,6 @@ public class SubscriptionController extends ISub.Stub {
        return true;
    }

    private void deactivateSubscription(SubscriptionInfo info) {
        // TODO: b/120439488 deactivate pSIM.
        if (info.isEmbedded()) {
            logd("[deactivateSubscription] eSIM profile " + info.getSubscriptionId());
            EuiccManager euiccManager = (EuiccManager)
                    mContext.getSystemService(Context.EUICC_SERVICE);
            euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
                    PendingIntent.getService(mContext, 0, new Intent(), 0));
        }
    }

    // TODO: This method should belong to Telephony manager like other data enabled settings and
    // override APIs. Remove this once TelephonyManager API is added.
    @Override
+12 −4
Original line number Diff line number Diff line
@@ -137,6 +137,11 @@ public class UiccProfile extends IccCard {
    private IccRecords mIccRecords = null;
    private IccCardConstants.State mExternalState = IccCardConstants.State.UNKNOWN;

    // The number of UiccApplications modem reported. It's different from mUiccApplications.length
    // which is always CARD_MAX_APPS, and only updated when modem sends an update, and NOT updated
    // during SIM refresh. It's currently only used to help identify empty profile.
    private int mLastReportedNumOfUiccApplications;

    private final ContentObserver mProvisionCompleteContentObserver =
            new ContentObserver(new Handler()) {
                @Override
@@ -864,10 +869,11 @@ public class UiccProfile extends IccCard {
    public boolean isEmptyProfile() {
        // If there's no UiccCardApplication, it's an empty profile.
        // Empty profile is a valid case of eSIM (default boot profile).
        for (UiccCardApplication app : mUiccApplications) {
            if (app != null) return false;
        }
        return true;
        // But we clear all apps of mUiccCardApplication to be null during refresh (see
        // resetAppWithAid) but not mLastReportedNumOfUiccApplications.
        // So if mLastReportedNumOfUiccApplications == 0, it means modem confirmed that we landed
        // on empty profile.
        return mLastReportedNumOfUiccApplications == 0;
    }

    @Override
@@ -964,6 +970,8 @@ public class UiccProfile extends IccCard {

            //update applications
            if (DBG) log(ics.mApplications.length + " applications");
            mLastReportedNumOfUiccApplications = ics.mApplications.length;

            for (int i = 0; i < mUiccApplications.length; i++) {
                if (mUiccApplications[i] == null) {
                    //Create newly added Applications
Loading