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

Commit 1951412d authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Create UiccSlotRepository

Also fix crash when TelephonyManager.uiccSlotsInfo returns array
contains null.

Fix: 358215954
Flag: EXEMPT bug fix
Test: manual - on Mobile Settings
Test: atest UiccSlotUtilTest
Change-Id: I4f92c9a43a430e295b6e048aee059416c46a256b
parent e3702e9b
Loading
Loading
Loading
Loading
+10 −29
Original line number Diff line number Diff line
@@ -24,10 +24,10 @@ import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.UiccCardInfo
import android.telephony.UiccSlotInfo
import android.util.Log
import com.android.settings.network.SimOnboardingActivity.Companion.CallbackType
import com.android.settings.network.telephony.MobileDataRepository
import com.android.settings.network.telephony.UiccSlotRepository
import com.android.settings.sim.SimActivationNotifier
import com.android.settings.spa.network.setDefaultData
import com.android.settings.spa.network.setDefaultSms
@@ -46,7 +46,6 @@ class SimOnboardingService {
    var targetSubInfo: SubscriptionInfo? = null
    var availableSubInfoList: List<SubscriptionInfo> = listOf()
    var activeSubInfoList: List<SubscriptionInfo> = listOf()
    var slotInfoList: List<UiccSlotInfo> = listOf()
    var uiccCardInfoList: List<UiccCardInfo> = listOf()
    var targetPrimarySimCalls: Int = INVALID_SUBSCRIPTION_ID
    var targetPrimarySimTexts: Int = INVALID_SUBSCRIPTION_ID
@@ -73,14 +72,6 @@ class SimOnboardingService {
            }
            return  uiccCardInfoList.any { it.isMultipleEnabledProfilesSupported }
        }
    var isRemovablePsimProfileEnabled: Boolean = false
        get() {
            if(slotInfoList.isEmpty()) {
                Log.w(TAG, "UICC Slot info list is empty.")
                return false
            }
            return UiccSlotUtil.isRemovableSimEnabled(slotInfoList)
        }
    var isEsimProfileEnabled: Boolean = false
        get() {
            activeSubInfoList.stream().anyMatch { it.isEmbedded }
@@ -137,19 +128,11 @@ class SimOnboardingService {
            return telephonyManager?.doesSwitchMultiSimConfigTriggerReboot() ?: false
        }

    fun isValid(): Boolean {
        return targetSubId != INVALID_SUBSCRIPTION_ID
            && targetSubInfo != null
            && activeSubInfoList.isNotEmpty()
            && slotInfoList.isNotEmpty()
    }

    fun clear() {
        targetSubId = -1
        targetSubInfo = null
        availableSubInfoList = listOf()
        activeSubInfoList = listOf()
        slotInfoList = listOf()
        uiccCardInfoList = listOf()
        targetPrimarySimCalls = -1
        targetPrimarySimTexts = -1
@@ -181,8 +164,6 @@ class SimOnboardingService {
                availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
            targetSubInfo?.let { userSelectedSubInfoList.add(it) }
            Log.d(TAG, "targetSubId: $targetSubId , targetSubInfo: $targetSubInfo")
            slotInfoList = telephonyManager?.uiccSlotsInfo?.toList() ?: listOf()
            Log.d(TAG, "slotInfoList: $slotInfoList.")
            uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
            Log.d(TAG, "uiccCardInfoList: $uiccCardInfoList")

@@ -192,7 +173,6 @@ class SimOnboardingService {

            Log.d(
                TAG,"doesTargetSimHaveEsimOperation: $doesTargetSimHaveEsimOperation" +
                    ", isRemovableSimEnabled: $isRemovablePsimProfileEnabled" +
                    ", isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported" +
                    ", targetPrimarySimCalls: $targetPrimarySimCalls" +
                    ", targetPrimarySimTexts: $targetPrimarySimTexts" +
@@ -317,14 +297,15 @@ class SimOnboardingService {
            return true
        }

        if (doesTargetSimHaveEsimOperation && isRemovablePsimProfileEnabled) {
            Log.d(TAG,
        if (doesTargetSimHaveEsimOperation) {
            if (UiccSlotRepository(telephonyManager).anyRemovablePhysicalSimEnabled()) {
                Log.d(
                    TAG,
                    "eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
                )
                return true
            }

        if (!doesTargetSimHaveEsimOperation && isEsimProfileEnabled) {
        } else if (isEsimProfileEnabled) {
            Log.d(TAG,
                "Removable SIM operation and eSIM profile is enabled. DSDS condition"
                        + " satisfied."
+4 −6
Original line number Diff line number Diff line
@@ -30,8 +30,6 @@ import android.util.Log;
import com.android.settings.SidecarFragment;
import com.android.settings.network.telephony.EuiccOperationSidecar;

import com.google.common.collect.ImmutableList;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
@@ -205,10 +203,10 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
    }

    private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
        ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(mTelephonyManager);
        if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.size()
                && slotInfos.get(physicalSlotIndex) != null) {
            for (UiccPortInfo portInfo : slotInfos.get(physicalSlotIndex).getPorts()) {
        UiccSlotInfo[] slotInfos = mTelephonyManager.getUiccSlotsInfo();
        if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length
                && slotInfos[physicalSlotIndex] != null) {
            for (UiccPortInfo portInfo : slotInfos[physicalSlotIndex].getPorts()) {
                if (portInfo.getPortIndex() == portIndex) {
                    return portInfo.getLogicalSlotIndex();
                }
+5 −53
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.utils.ThreadUtils;

import com.google.common.collect.ImmutableList;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -105,18 +103,6 @@ public class UiccSlotUtil {
        int SYNC_CLEANUP = 2;
    }

    /**
     * Returns an immutable list of all UICC slots. If TelephonyManager#getUiccSlotsInfo returns, it
     * returns an empty list instead.
     */
    public static ImmutableList<UiccSlotInfo> getSlotInfos(TelephonyManager telMgr) {
        UiccSlotInfo[] slotInfos = telMgr.getUiccSlotsInfo();
        if (slotInfos == null) {
            return ImmutableList.of();
        }
        return ImmutableList.copyOf(slotInfos);
    }

    /**
     * Switches to the removable slot. It waits for SIM_STATE_LOADED after switch. If slotId is
     * INVALID_PHYSICAL_SLOT_ID, the method will use the first detected inactive removable slot.
@@ -219,14 +205,13 @@ public class UiccSlotUtil {
     */
    public static int getEsimSlotId(Context context, int subId) {
        TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
        List<UiccCardInfo> uiccCardInfos = telMgr.getUiccCardsInfo();
        ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
        SubscriptionManager subscriptionManager = context.getSystemService(
                SubscriptionManager.class).createForAllUserProfiles();
        SubscriptionInfo subInfo = SubscriptionUtil.getSubById(subscriptionManager, subId);

        // checking whether this is the removable esim. If it is, then return the removable slot id.
        if (subInfo != null && subInfo.isEmbedded()) {
            List<UiccCardInfo> uiccCardInfos = telMgr.getUiccCardsInfo();
            for (UiccCardInfo uiccCardInfo : uiccCardInfos) {
                if (uiccCardInfo.getCardId() == subInfo.getCardId()
                        && uiccCardInfo.getCardId() > TelephonyManager.UNSUPPORTED_CARD_ID
@@ -238,10 +223,12 @@ public class UiccSlotUtil {
            }
        }

        int firstEsimSlot = IntStream.range(0, slotInfos.size())
        UiccSlotInfo[] slotInfos = telMgr.getUiccSlotsInfo();
        if (slotInfos == null) return -1;
        int firstEsimSlot = IntStream.range(0, slotInfos.length)
                .filter(
                        index -> {
                            UiccSlotInfo slotInfo = slotInfos.get(index);
                            UiccSlotInfo slotInfo = slotInfos[index];
                            if (slotInfo == null) {
                                return false;
                            }
@@ -421,41 +408,6 @@ public class UiccSlotUtil {
                .orElse(INVALID_LOGICAL_SLOT_ID);
    }

    /**
     * Return whether the removable psim is enabled.
     *
     * @param telMgr is a TelephonyManager.
     * @return whether the removable psim is enabled.
     */
    public static boolean isRemovableSimEnabled(TelephonyManager telMgr) {
        if (telMgr == null) {
            return false;
        }
        List<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
        return isRemovableSimEnabled(slotInfos);
    }

    /**
     * Return whether the removable psim is enabled.
     *
     * @param slotInfos is a List of UiccSlotInfo.
     * @return whether the removable psim is enabled.
     */
    public static boolean isRemovableSimEnabled(List<UiccSlotInfo> slotInfos) {
        boolean isRemovableSimEnabled =
                slotInfos.stream()
                        .anyMatch(
                                slot -> slot != null
                                        && slot.isRemovable()
                                        && !slot.getIsEuicc()
                                        && slot.getPorts().stream()
                                                .anyMatch(port -> port.isActive())
                                        && slot.getCardStateInfo()
                                        == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
        Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
        return isRemovableSimEnabled;
    }

    private static boolean isMultipleEnabledProfilesSupported(TelephonyManager telMgr) {
        List<UiccCardInfo> cardInfos = telMgr.getUiccCardsInfo();
        if (cardInfos == null) {
+1 −1
Original line number Diff line number Diff line
@@ -583,7 +583,7 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc
    }

    private boolean isRemovableSimEnabled() {
        return UiccSlotUtil.isRemovableSimEnabled(mTelMgr);
        return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimEnabled();
    }

    private boolean isMultipleEnabledProfilesSupported() {
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.telephony.TelephonyManager
import android.telephony.UiccSlotInfo
import android.util.Log

class UiccSlotRepository(private val telephonyManager: TelephonyManager?) {

    /** Returns whether any removable physical sim is enabled. */
    fun anyRemovablePhysicalSimEnabled(): Boolean {
        val result =
            telephonyManager?.uiccSlotsInfo?.any { uiccSlotInfo: UiccSlotInfo? ->
                uiccSlotInfo.isRemovablePhysicalSimEnabled()
            } ?: false
        Log.i(TAG, "anyRemovablePhysicalSimEnabled: $result")
        return result
    }

    private fun UiccSlotInfo?.isRemovablePhysicalSimEnabled(): Boolean {
        return this != null &&
            isRemovable &&
            !isEuicc &&
            ports.any { port -> port.isActive } &&
            cardStateInfo == UiccSlotInfo.CARD_STATE_INFO_PRESENT
    }

    companion object {
        private const val TAG = "UiccRepository"
    }
}
Loading