blob: cf1eba9cf0f84d4bc234e7db9beb0072313037d0 [file] [log] [blame]
/*
* 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.car.settings.network;
import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
import static com.android.internal.util.CollectionUtils.emptyIfNull;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccSlotInfo;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/** Shared logic related to dealing with multiple subscriptions. */
public final class SubscriptionUtils {
private SubscriptionUtils() {
}
/**
* Returns the list of available subscriptions, accounting for duplicates possible through a
* virtual network provider.
*/
public static List<SubscriptionInfo> getAvailableSubscriptions(
SubscriptionManager subscriptionManager, TelephonyManager telephonyManager) {
List<SubscriptionInfo> subscriptions = new ArrayList<>(
emptyIfNull(subscriptionManager.getSelectableSubscriptionInfoList()));
// Look for inactive but present physical SIMs that are missing from the selectable list.
List<UiccSlotInfo> missing = new ArrayList<>();
UiccSlotInfo[] slotsInfo = telephonyManager.getUiccSlotsInfo();
for (int i = 0; slotsInfo != null && i < slotsInfo.length; i++) {
UiccSlotInfo slotInfo = slotsInfo[i];
if (isInactiveInsertedPSim(slotInfo)) {
int index = slotInfo.getLogicalSlotIdx();
String cardId = slotInfo.getCardId();
boolean found = subscriptions.stream().anyMatch(
info -> index == info.getSimSlotIndex() && cardId.equals(
info.getCardString()));
if (!found) {
missing.add(slotInfo);
}
}
}
if (!missing.isEmpty()) {
for (SubscriptionInfo info : subscriptionManager.getAllSubscriptionInfoList()) {
for (UiccSlotInfo slotInfo : missing) {
if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx()
&& info.getCardString().equals(slotInfo.getCardId())) {
subscriptions.add(info);
break;
}
}
}
}
// With some carriers such as Google Fi which provide a sort of virtual service that spans
// across multiple underlying networks, we end up with subscription entries for the
// underlying networks that need to be hidden from the user in the UI.
for (Iterator<SubscriptionInfo> iter = subscriptions.iterator(); iter.hasNext(); ) {
SubscriptionInfo info = iter.next();
if (TextUtils.isEmpty(info.getMncString())) {
iter.remove();
}
}
return subscriptions;
}
private static boolean isInactiveInsertedPSim(UiccSlotInfo slotInfo) {
return !slotInfo.getIsEuicc() && !slotInfo.getIsActive()
&& slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT;
}
}