Merge sc-v2-dev-plus-aosp-without-vendor@8433047
Bug: 226662282
Merged-In: I800f0f39a469a95eb36eeaaeb2aa60a39fd916d3
Change-Id: I71459583120f712298f47b4dbd2c791d8ef4e022
diff --git a/res/layout/select_account_list_item.xml b/res/layout/select_account_list_item.xml
index 716adff..dbc31be 100644
--- a/res/layout/select_account_list_item.xml
+++ b/res/layout/select_account_list_item.xml
@@ -20,7 +20,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeightSmall"
- android:background="@drawable/sim_confirm_dialog_rounded_bg"
android:gravity="center">
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.SimConfirmDialogList"
@@ -36,6 +35,5 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
- android:textColor="?android:attr/textColorSecondary"
android:layout_alignStart="@id/title" />
</LinearLayout>
diff --git a/res/layout/sim_confirm_dialog_item_multiple_enabled_profiles_supported.xml b/res/layout/sim_confirm_dialog_item_multiple_enabled_profiles_supported.xml
index 003cdbf..700fab3 100644
--- a/res/layout/sim_confirm_dialog_item_multiple_enabled_profiles_supported.xml
+++ b/res/layout/sim_confirm_dialog_item_multiple_enabled_profiles_supported.xml
@@ -25,6 +25,5 @@
android:paddingBottom="?attr/listPreferredItemPaddingEnd"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
- android:background="@drawable/sim_confirm_dialog_rounded_bg"
android:textAppearance="@style/TextAppearance.SimConfirmDialogList"
/>
diff --git a/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml b/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml
index 610bf3d..081efb3 100644
--- a/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml
+++ b/res/layout/sim_confirm_dialog_multiple_enabled_profiles_supported.xml
@@ -26,15 +26,19 @@
android:paddingEnd="24dp"
android:paddingTop="16dp"
android:paddingStart="24dp"
+ android:paddingBottom="32dp"
android:gravity="center"
- android:textAppearance="@style/TextAppearance.DialogMessage"/>
+ android:textAppearance="@style/TextAppearance.DialogMessage"
+ android:visibility="gone"/>
<ListView
android:id="@+id/carrier_list"
android:layout_gravity="center"
- android:paddingTop="16dp"
- android:dividerHeight="1dp"
+ android:divider="?android:attr/colorBackgroundFloating"
+ android:dividerHeight="4dp"
+ android:background="@drawable/sim_confirm_dialog_rounded_bg"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:visibility="gone"/>
<LinearLayout
android:id="@+id/info_outline_layout"
@@ -46,7 +50,8 @@
android:paddingTop="16dp"
android:paddingStart="24dp"
android:layout_marginBottom="16dp"
- android:baselineAligned="true">
+ android:baselineAligned="true"
+ android:visibility="gone">
<ImageView
android:src="@drawable/ic_info_outline_24dp"
android:layout_width="wrap_content"
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index a388855..f69c952 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -28,6 +28,6 @@
<style name="TextAppearance.SimConfirmDialogList.Summary">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
- <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
</style>
</resources>
\ No newline at end of file
diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml
index 4564827..946cd91 100644
--- a/res/values-night/themes.xml
+++ b/res/values-night/themes.xml
@@ -34,12 +34,6 @@
<item name="android:colorBackground">@*android:color/surface_dark</item>
</style>
- <style name="Theme.AlertDialog.Base.Material3" parent="Theme.MaterialComponents.DayNight.Dialog.Alert">
- <item name="colorPrimary">@*android:color/primary_device_default_settings</item>
- <item name="colorAccent">@*android:color/accent_device_default_dark</item>
- <item name="android:colorBackground">@*android:color/surface_dark</item>
- </style>
-
<!-- Material theme for the pages containing TabLayout and ViewPager -->
<style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/edge_effect_device_default_dark</item>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 244f0fd..4f3d407 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -441,4 +441,8 @@
<dimen name="chartview_trapezoid_radius">5dp</dimen>
<dimen name="chartview_trapezoid_margin_start">1dp</dimen>
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
+
+ <!-- Sims/Data mobile/Calls/SMS select dialog-->
+ <dimen name="sims_select_margin_bottom">24dp</dimen>
+ <dimen name="sims_select_margin_top">8dp</dimen>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index afa13a1..838d63b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -919,6 +919,7 @@
<style name="TextAppearance.SimConfirmDialogList.Summary">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="SimConfirmDialog.OutlineButton" parent="@android:style/Widget.Material.Button">
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index b57ea92..f0809ad 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -20,6 +20,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.Log;
@@ -31,6 +32,7 @@
import androidx.preference.SwitchPreference;
import com.android.settings.R;
+import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LeAudioProfile;
@@ -70,6 +72,7 @@
private List<CachedBluetoothDevice> mAllOfCachedDevices;
private Map<String, List<CachedBluetoothDevice>> mProfileDeviceMap =
new HashMap<String, List<CachedBluetoothDevice>>();
+ private boolean mIsLeContactSharingEnabled = false;
@VisibleForTesting
PreferenceCategory mProfilesContainer;
@@ -88,6 +91,8 @@
protected void init(PreferenceScreen screen) {
mProfilesContainer = (PreferenceCategory)screen.findPreference(getPreferenceKey());
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
+ mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
// Call refresh here even though it will get called later in onResume, to avoid the
// list of switches appearing to "pop" into the page.
refresh();
@@ -119,21 +124,11 @@
private void refreshProfilePreference(SwitchPreference profilePref,
LocalBluetoothProfile profile) {
BluetoothDevice device = mCachedDevice.getDevice();
- boolean isLeAudioEnabled = false;
+ boolean isLeAudioEnabled = isLeAudioEnabled();
if (profile instanceof A2dpProfile || HEADSET_CLIENT.equals(profile.toString())) {
- LocalBluetoothProfile leAudio = mProfileManager.getLeAudioProfile();
- if (leAudio != null) {
- List<CachedBluetoothDevice> leAudioDeviceList = mProfileDeviceMap.get(
- leAudio.toString());
- if (leAudioDeviceList != null
- && leAudioDeviceList.stream()
- .anyMatch(item -> leAudio.isEnabled(item.getDevice()))) {
- isLeAudioEnabled = true;
- }
- }
if (isLeAudioEnabled) {
// If the LeAudio profile is enabled on the LeAudio devices, then the
- // SwitchPreferences of A2dp profile and Hfp profile are graied out.
+ // SwitchPreferences of A2dp profile and Hfp profile are grayed out.
profilePref.setEnabled(false);
} else {
List<CachedBluetoothDevice> deviceList = mProfileDeviceMap.get(
@@ -145,12 +140,9 @@
} else if (profile instanceof LeAudioProfile) {
List<CachedBluetoothDevice> leAudioDeviceList = mProfileDeviceMap.get(
profile.toString());
- boolean isLeAudioProfileEnable =
- leAudioDeviceList != null && leAudioDeviceList.stream().anyMatch(
- item -> profile.isEnabled(item.getDevice()));
boolean isBusy = leAudioDeviceList != null
&& leAudioDeviceList.stream().anyMatch(item -> item.isBusy());
- if (isLeAudioProfileEnable && !isBusy) {
+ if (isLeAudioEnabled && !isBusy) {
LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
LocalBluetoothProfile hfp = mProfileManager.getHfpClientProfile();
// If the LeAudio profile is enabled on the LeAudio devices, then the
@@ -169,6 +161,10 @@
}
}
profilePref.setEnabled(!isBusy);
+ } else if (profile instanceof PbapServerProfile
+ && isLeAudioEnabled
+ && !mIsLeContactSharingEnabled) {
+ profilePref.setEnabled(false);
} else {
profilePref.setEnabled(!mCachedDevice.isBusy());
}
@@ -203,6 +199,20 @@
}
}
+ private boolean isLeAudioEnabled(){
+ LocalBluetoothProfile leAudio = mProfileManager.getLeAudioProfile();
+ if (leAudio != null) {
+ List<CachedBluetoothDevice> leAudioDeviceList = mProfileDeviceMap.get(
+ leAudio.toString());
+ if (leAudioDeviceList != null
+ && leAudioDeviceList.stream()
+ .anyMatch(item -> leAudio.isEnabled(item.getDevice()))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Helper method to enable a profile for a device.
*/
@@ -505,4 +515,4 @@
public String getPreferenceKey() {
return KEY_PROFILES_GROUP;
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/core/SettingsUIDeviceConfig.java b/src/com/android/settings/core/SettingsUIDeviceConfig.java
index 8c85c82..94074df 100644
--- a/src/com/android/settings/core/SettingsUIDeviceConfig.java
+++ b/src/com/android/settings/core/SettingsUIDeviceConfig.java
@@ -33,7 +33,11 @@
* {@code true} if near by device suggestion is enabled in connected device page
*/
public static final String BT_NEAR_BY_SUGGESTION_ENABLED = "bt_near_by_suggestion_enabled";
-
+ /**
+ * {@code true} if le audio contact sharing is enabled in BT device detail page
+ */
+ public static final String BT_LE_AUDIO_CONTACT_SHARING_ENABLED =
+ "bt_le_audio_contact_sharing_enabled";
/**
* {@code true} whether or not event_log for generic actions is enabled. Default is true.
*/
diff --git a/src/com/android/settings/network/SwitchSlotSidecar.java b/src/com/android/settings/network/SwitchSlotSidecar.java
index abf8842..7005452 100644
--- a/src/com/android/settings/network/SwitchSlotSidecar.java
+++ b/src/com/android/settings/network/SwitchSlotSidecar.java
@@ -78,11 +78,19 @@
super.run(param);
}
- /** Starts switching to the removable slot. */
- public void runSwitchToEuiccSlot(int id, int port, SubscriptionInfo removedSubInfo) {
+ /**
+ * Start the SimSlotMapping process if the euicc slot is not in SimSlotMapping list.
+ * @param physicalSlotId The physical slot id.
+ * @param port The port id.
+ * @param removedSubInfo The subscriptionInfo which is selected by the user to disable when all
+ * of sim slots are full in the device. If all of slots are not full in
+ * the device, then this is null.
+ */
+ public void runSwitchToEuiccSlot(int physicalSlotId, int port,
+ SubscriptionInfo removedSubInfo) {
Param param = new Param();
param.command = Command.SWITCH_TO_EUICC_SIM;
- param.slotId = id;
+ param.slotId = physicalSlotId;
param.removedSubInfo = removedSubInfo;
param.port = port;
super.run(param);
diff --git a/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java b/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
index 888e5b2..0b39d6a 100644
--- a/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
+++ b/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
@@ -21,14 +21,13 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.UiccCardInfo;
-import android.telephony.UiccSlotMapping;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
import com.android.settings.SidecarFragment;
import com.android.settings.network.telephony.EuiccOperationSidecar;
-import java.util.Collection;
+import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@@ -37,7 +36,6 @@
private static final String TAG = "SwitchToEuiccSidecar";
private static final String ACTION_SWITCH_TO_SUBSCRIPTION =
"com.android.settings.network.SWITCH_TO_SUBSCRIPTION";
- private static final int ESIM_SLOT_ID = 1;
private PendingIntent mCallbackIntent;
private int mSubId;
@@ -70,20 +68,15 @@
}
}
- /** Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile. */
- // ToDo: delete this api and refactor the related code.
- public void run(int subscriptionId) {
- setState(State.RUNNING, Substate.UNUSED);
- mCallbackIntent = createCallbackIntent();
- mEuiccManager.switchToSubscription(subscriptionId, mCallbackIntent);
- }
-
/**
* Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile.
*
* @param subscriptionId the esim's subscriptionId.
- * @param port the esim's portId. If user wants to inactivate esim, then user must to assign the
- * the port. If user wants to activate esim, then the port can be -1.
+ * @param port the esim's portId. If user wants to inactivate esim, then user must to assign
+ * the corresponding port. If user wants to activate esim, then the port can be
+ * {@link UiccSlotUtil#INVALID_PORT_ID}. When it is
+ * {@link UiccSlotUtil#INVALID_PORT_ID}, the system will reassign a corresponding
+ * port id.
* @param removedSubInfo if the all of slots have sims, it should remove the one of active sim.
* If the removedSubInfo is null, then use the default value.
* The default value is the esim slot and portId 0.
@@ -92,11 +85,20 @@
setState(State.RUNNING, Substate.UNUSED);
mCallbackIntent = createCallbackIntent();
mSubId = subscriptionId;
+ int targetSlot = getTargetSlot();
+ if (targetSlot < 0) {
+ Log.d(TAG, "There is no esim, the TargetSlot is " + targetSlot);
+ setState(State.ERROR, Substate.UNUSED);
+ return;
+ }
+
// To check whether the esim slot's port is active. If yes, skip setSlotMapping. If no,
// set this slot+port into setSimSlotMapping.
mPort = (port < 0) ? getTargetPortId(removedSubInfo) : port;
mRemovedSubInfo = removedSubInfo;
- Log.i(TAG, "The SubId is " + mSubId + ". The port is " + mPort);
+ Log.d(TAG,
+ String.format("set esim into the SubId%d Slot%d:Port%d",
+ mSubId, targetSlot, mPort));
if (mTelephonyManager.isMultiSimEnabled() && removedSubInfo != null
&& removedSubInfo.isEmbedded()) {
@@ -108,7 +110,7 @@
mEuiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, mPort,
mCallbackIntent);
} else {
- mSwitchSlotSidecar.runSwitchToEuiccSlot(getTargetSlot(), mPort, removedSubInfo);
+ mSwitchSlotSidecar.runSwitchToEuiccSlot(targetSlot, mPort, removedSubInfo);
}
}
@@ -124,18 +126,26 @@
return removedSubInfo.getPortIndex();
}
- // In DSDS+MEP mode, the removedSubInfo is psim or is null, it means the this esim need
- // another port in the esim slot.
- // To find another esim's port and value is from 0;
+ // In DSDS+MEP mode, the removedSubInfo is psim or is null, it means this esim needs
+ // a new corresponding port in the esim slot.
+ // For example:
+ // 1) If there is no enabled esim and the user add new esim. This new esim's port is 0.
+ // 2) If there is one enabled esim in port0 and the user add new esim. This new esim's
+ // port is 1.
+ // 3) If there is one enabled esim in port1 and the user add new esim. This new esim's
+ // port is 0.
+
int port = 0;
- Collection<UiccSlotMapping> uiccSlotMappings = mTelephonyManager.getSimSlotMapping();
- for (UiccSlotMapping uiccSlotMapping :
- uiccSlotMappings.stream()
- .filter(
- uiccSlotMapping -> uiccSlotMapping.getPhysicalSlotIndex()
- == getTargetSlot())
- .collect(Collectors.toList())) {
- if (uiccSlotMapping.getPortIndex() == port) {
+ SubscriptionManager subscriptionManager = getContext().getSystemService(
+ SubscriptionManager.class);
+ List<SubscriptionInfo> activeEsimSubInfos =
+ SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
+ .stream()
+ .filter(i -> i.isEmbedded())
+ .sorted(Comparator.comparingInt(SubscriptionInfo::getPortIndex))
+ .collect(Collectors.toList());
+ for (SubscriptionInfo subscriptionInfo : activeEsimSubInfos) {
+ if (subscriptionInfo.getPortIndex() == port) {
port++;
}
}
@@ -143,7 +153,7 @@
}
private int getTargetSlot() {
- return ESIM_SLOT_ID;
+ return UiccSlotUtil.getEsimSlotId(getContext());
}
private void onSwitchSlotSidecarStateChange() {
diff --git a/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java b/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
index 9b9c0dd..a870f3b 100644
--- a/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
+++ b/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
@@ -81,29 +81,6 @@
}
/**
- * Starts switching to the removable slot. It disables the active eSIM profile before switching
- * if there is one.
- *
- * @param physicalSlotId removable physical SIM slot ID.
- */
- // ToDo: delete this api and refactor the related code.
- public void run(int physicalSlotId) {
- mPhysicalSlotId = physicalSlotId;
- SubscriptionManager subscriptionManager =
- getContext().getSystemService(SubscriptionManager.class);
- if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream()
- .anyMatch(SubscriptionInfo::isEmbedded)) {
- // In SS mode, the esim is active, then inactivate the esim.
- Log.i(TAG, "There is an active eSIM profile. Disable the profile first.");
- // Use INVALID_SUBSCRIPTION_ID to disable the only active profile.
- mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0, null);
- } else {
- Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot.");
- mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId, null);
- }
- }
-
- /**
* Starts switching to the removable slot.
*
* @param physicalSlotId removable physical SIM slot ID.
@@ -124,7 +101,7 @@
// Use INVALID_SUBSCRIPTION_ID to disable the only active profile.
mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0, null);
} else if (mTelephonyManager.isMultiSimEnabled() && mRemovedSubInfo != null) {
- // In DSDS mode+MEP, if the replaced esim is active, then it should be disabled esim
+ // In DSDS mode+MEP, if the replaced esim is active, then it should disable that esim
// profile before changing SimSlotMapping process.
// Use INVALID_SUBSCRIPTION_ID to disable the esim profile.
mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index ef031f6..c83d971 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -31,6 +31,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
+import android.net.EthernetManager;
+import android.net.IpConfiguration;
import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -40,6 +42,7 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
@@ -53,6 +56,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -81,6 +85,16 @@
private static final String TAG = "TetherEnabler";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final class EthernetListener implements EthernetManager.InterfaceStateListener {
+ public void onInterfaceStateChanged(@NonNull String iface, int state, int role,
+ @NonNull IpConfiguration configuration) {
+ if (state == EthernetManager.STATE_LINK_UP) {
+ mAvailableInterfaces.put(iface, configuration);
+ } else {
+ mAvailableInterfaces.remove(iface, configuration);
+ }
+ }
+ }
@Retention(SOURCE)
@IntDef(
@@ -108,7 +122,6 @@
private final ConnectivityManager mConnectivityManager;
private final TetheringManager mTetheringManager;
private final UserManager mUserManager;
- private final String mEthernetRegex;
private final DataSaverBackend mDataSaverBackend;
private boolean mDataSaverEnabled;
@VisibleForTesting
@@ -121,6 +134,10 @@
private final AtomicReference<BluetoothPan> mBluetoothPan;
private boolean mBluetoothEnableForTether;
private final BluetoothAdapter mBluetoothAdapter;
+ private final EthernetManager mEthernetManager;
+ private final EthernetManager.InterfaceStateListener mEthernetListener = new EthernetListener();
+ private final ConcurrentHashMap<String, IpConfiguration> mAvailableInterfaces =
+ new ConcurrentHashMap<>();
public TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
AtomicReference<BluetoothPan> bluetoothPan) {
@@ -134,11 +151,10 @@
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothPan = bluetoothPan;
- mEthernetRegex =
- context.getString(com.android.internal.R.string.config_ethernet_iface_regex);
mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
mListeners = new ArrayList<>();
mMainThreadHandler = new Handler(Looper.getMainLooper());
+ mEthernetManager = context.getSystemService(EthernetManager.class);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
@@ -163,6 +179,10 @@
mOnStartTetheringCallback = new OnStartTetheringCallback(this);
updateState(null/*tethered*/);
+ if (mEthernetManager != null) {
+ mEthernetManager.addInterfaceStateListener(r -> mMainThreadHandler.post(r),
+ mEthernetListener);
+ }
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
@@ -173,6 +193,9 @@
mContext.unregisterReceiver(mTetherChangeReceiver);
mTetheringManager.unregisterTetheringEventCallback(mTetheringEventCallback);
mTetheringEventCallback = null;
+ if (mEthernetManager != null) {
+ mEthernetManager.removeInterfaceStateListener(mEthernetListener);
+ }
}
public void addListener(OnTetherStateUpdateListener listener) {
@@ -246,7 +269,7 @@
tetherState |= TETHERING_USB_ON;
}
}
- if (s.matches(mEthernetRegex)) {
+ if (mAvailableInterfaces.containsKey(s)) {
tetherState |= TETHERING_ETHERNET_ON;
}
}
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index 8938cdb..8fdc370 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -20,11 +20,13 @@
import android.content.Context;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.utils.ThreadUtils;
import com.google.common.collect.ImmutableList;
@@ -33,9 +35,11 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
// ToDo: to do the refactor for renaming
public class UiccSlotUtil {
@@ -44,6 +48,7 @@
private static final long DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS = 25 * 1000L;
+ public static final int INVALID_LOGICAL_SLOT_ID = -1;
public static final int INVALID_PHYSICAL_SLOT_ID = -1;
public static final int INVALID_PORT_ID = -1;
@@ -112,9 +117,27 @@
}
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
int inactiveRemovableSlot = getInactiveRemovableSlot(telMgr.getUiccSlotsInfo(), slotId);
+ Log.d(TAG, "The InactiveRemovableSlot: " + inactiveRemovableSlot);
+ if (inactiveRemovableSlot == INVALID_PHYSICAL_SLOT_ID) {
+ // The slot is invalid slot id, then to skip this.
+ // The slot is active, then the sim can enable directly.
+ return;
+ }
+
+ Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
+ Log.d(TAG, "The SimSlotMapping: " + uiccSlotMappings);
+
+ SubscriptionManager subscriptionManager = context.getSystemService(
+ SubscriptionManager.class);
+ int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
+ SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
+ telMgr.isMultiSimEnabled());
performSwitchToSlot(telMgr,
- prepareUiccSlotMappingsForRemovableSlot(telMgr.getSimSlotMapping(),
- inactiveRemovableSlot, removedSubInfo, telMgr.isMultiSimEnabled()),
+ prepareUiccSlotMappings(uiccSlotMappings,
+ /*slot is psim*/ true,
+ inactiveRemovableSlot,
+ /*removable sim's port Id*/ TelephonyManager.DEFAULT_PORT_INDEX,
+ excludedLogicalSlotIndex),
context);
}
@@ -122,7 +145,7 @@
* Switches to the Euicc slot. It waits for SIM_STATE_LOADED after switch.
*
* @param context the application context.
- * @param slotId the Euicc slot id.
+ * @param physicalSlotId the Euicc slot id.
* @param port the Euicc slot port id.
* @param removedSubInfo In the DSDS+MEP mode, if the all of slots have sims, it should
* remove the one of active sim.
@@ -130,7 +153,7 @@
* The default value is the esim slot and portId 0.
* @throws UiccSlotsException if there is an error.
*/
- public static synchronized void switchToEuiccSlot(Context context, int slotId, int port,
+ public static synchronized void switchToEuiccSlot(Context context, int physicalSlotId, int port,
SubscriptionInfo removedSubInfo) throws UiccSlotsException {
if (ThreadUtils.isMainThread()) {
throw new IllegalThreadStateException(
@@ -138,47 +161,51 @@
}
TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
Collection<UiccSlotMapping> uiccSlotMappings = telMgr.getSimSlotMapping();
- Log.i(TAG, "The SimSlotMapping: " + uiccSlotMappings);
+ Log.d(TAG, "The SimSlotMapping: " + uiccSlotMappings);
- if (isTargetSlotActive(uiccSlotMappings, slotId, port)) {
- Log.i(TAG, "The slot is active, then the sim can enable directly.");
+ if (isTargetSlotActive(uiccSlotMappings, physicalSlotId, port)) {
+ Log.d(TAG, "The slot is active, then the sim can enable directly.");
return;
}
- Collection<UiccSlotMapping> newUiccSlotMappings = new ArrayList<>();
- if (!telMgr.isMultiSimEnabled()) {
- // In the 'SS mode', the port is 0.
- newUiccSlotMappings.add(new UiccSlotMapping(port, slotId, 0));
- } else {
- // DSDS+MEP
- // The target slot+port is not active, but the all of logical slots are full. It
- // needs to replace one of logical slots.
- int removedSlot =
- (removedSubInfo != null) ? removedSubInfo.getSimSlotIndex() : slotId;
- int removedPort = (removedSubInfo != null) ? removedSubInfo.getPortIndex() : 0;
- Log.i(TAG,
- String.format("Start to set SimSlotMapping from slot%d-port%d to slot%d-port%d",
- slotId, port, removedSlot, removedPort));
- newUiccSlotMappings =
- uiccSlotMappings.stream().map(uiccSlotMapping -> {
- if (uiccSlotMapping.getPhysicalSlotIndex() == removedSlot
- && uiccSlotMapping.getPortIndex() == removedPort) {
- return new UiccSlotMapping(port, slotId,
- uiccSlotMapping.getLogicalSlotIndex());
- }
- return uiccSlotMapping;
- }).collect(Collectors.toList());
- }
+ SubscriptionManager subscriptionManager = context.getSystemService(
+ SubscriptionManager.class);
+ int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
+ SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
+ telMgr.isMultiSimEnabled());
+ performSwitchToSlot(telMgr,
+ prepareUiccSlotMappings(uiccSlotMappings, /*slot is not psim*/ false,
+ physicalSlotId, port, excludedLogicalSlotIndex),
+ context);
+ }
- Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings);
- performSwitchToSlot(telMgr, newUiccSlotMappings, context);
+ /**
+ * @param context the application context.
+ * @return the esim slot. If the value is -1, there is not the esim.
+ */
+ public static int getEsimSlotId(Context context) {
+ TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
+ ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+ int firstEsimSlot = IntStream.range(0, slotInfos.size())
+ .filter(
+ index -> {
+ UiccSlotInfo slotInfo = slotInfos.get(index);
+ if (slotInfo == null) {
+ return false;
+ }
+ return !slotInfo.isRemovable();
+ })
+ .findFirst().orElse(-1);
+
+ Log.i(TAG, "firstEsimSlot: " + firstEsimSlot);
+ return firstEsimSlot;
}
private static boolean isTargetSlotActive(Collection<UiccSlotMapping> uiccSlotMappings,
- int slotId, int port) {
+ int physicalSlotId, int port) {
return uiccSlotMappings.stream()
.anyMatch(
- uiccSlotMapping -> uiccSlotMapping.getPhysicalSlotIndex() == slotId
+ uiccSlotMapping -> uiccSlotMapping.getPhysicalSlotIndex() == physicalSlotId
&& uiccSlotMapping.getPortIndex() == port);
}
@@ -239,49 +266,112 @@
return INVALID_PHYSICAL_SLOT_ID;
}
- private static Collection<UiccSlotMapping> prepareUiccSlotMappingsForRemovableSlot(
- Collection<UiccSlotMapping> uiccSlotMappings, int slotId,
- SubscriptionInfo removedSubInfo, boolean isMultiSimEnabled) {
- if (slotId == INVALID_PHYSICAL_SLOT_ID
- || uiccSlotMappings.stream().anyMatch(uiccSlotMapping ->
- uiccSlotMapping.getPhysicalSlotIndex() == slotId
- && uiccSlotMapping.getPortIndex() == 0)) {
- // The slot is invalid slot id, then to skip this.
- // The slot is active, then the sim can enable directly.
+ // Device | |Slot |
+ // Working| |Mapping|
+ // State |Type |Mode |Friendly name
+ //--------------------------------------------------------------------------
+ // Single |SIM pSIM [RIL 0] |1 |pSIM active
+ // Single |SIM MEP Port #0 [RIL0] |2 |eSIM Port0 active
+ // Single |SIM MEP Port #1 [RIL0] |2.1 |eSIM Port1 active
+ // DSDS |pSIM [RIL 0] + MEP Port #0 [RIL 1] |3 |pSIM+Port0
+ // DSDS |pSIM [RIL 0] + MEP Port #1 [RIL 1] |3.1 |pSIM+Port1
+ // DSDS |MEP Port #0 [RIL 0] + MEP Port #1 [RIL1]|3.2 |Dual-Ports-A
+ // DSDS |MEP Port #1 [RIL 0] + MEP Port #0 [RIL1]|4 |Dual-Ports-B
+ //
+ // The rules are:
+ // 1. pSIM's logical slots always is [RIL 0].
+ // 2. assign the new active port to the same stack that will be de-activated
+ // For example: mode#3->mode#4
+
+ @VisibleForTesting
+ static Collection<UiccSlotMapping> prepareUiccSlotMappings(
+ Collection<UiccSlotMapping> uiccSlotMappings, boolean isPsim, int physicalSlotId,
+ int port, int removedLogicalSlotId) {
+ if (removedLogicalSlotId == INVALID_LOGICAL_SLOT_ID) {
+ Log.d(TAG, "There is no removedLogicalSlotId. Do nothing.");
return uiccSlotMappings;
}
-
+ Log.d(TAG,
+ String.format(
+ "Create new SimSlotMapping. Remove the UiccSlotMapping of logicalSlot%d"
+ + ", and insert PhysicalSlotId%d-Port%d",
+ removedLogicalSlotId, physicalSlotId, port));
Collection<UiccSlotMapping> newUiccSlotMappings = new ArrayList<>();
- if (!isMultiSimEnabled) {
- // In the 'SS mode', the port is 0.
- newUiccSlotMappings.add(new UiccSlotMapping(0, slotId, 0));
- } else if (removedSubInfo != null) {
- // DSDS+MEP
- // The target slot+port is not active, but the all of logical slots are full. It
- // needs to replace one of logical slots.
- Log.i(TAG,
- String.format("Start to set SimSlotMapping from slot%d-port%d to slot%d-port%d",
- slotId, 0, removedSubInfo.getSimSlotIndex(),
- removedSubInfo.getPortIndex()));
- newUiccSlotMappings =
- uiccSlotMappings.stream().map(uiccSlotMapping -> {
- if (uiccSlotMapping.getPhysicalSlotIndex()
- == removedSubInfo.getSimSlotIndex()
- && uiccSlotMapping.getPortIndex()
- == removedSubInfo.getPortIndex()) {
- return new UiccSlotMapping(0, slotId,
- uiccSlotMapping.getLogicalSlotIndex());
- }
- return uiccSlotMapping;
- }).collect(Collectors.toList());
- } else {
- // DSDS+no MEP
- // The removable slot should be in UiccSlotMapping.
- newUiccSlotMappings = uiccSlotMappings;
- Log.i(TAG, "The removedSubInfo is null");
+ int logicalSlotIndex = 0;
+ if (isPsim) {
+ // The target slot is psim. The psim is always the first index at LogicalSlot.
+ newUiccSlotMappings.add(
+ new UiccSlotMapping(port, physicalSlotId, logicalSlotIndex++));
+ }
+ Collection<UiccSlotMapping> tempUiccSlotMappings =
+ uiccSlotMappings.stream()
+ .sorted(Comparator.comparingInt(UiccSlotMapping::getLogicalSlotIndex))
+ .collect(Collectors.toList());
+ for (UiccSlotMapping uiccSlotMapping : tempUiccSlotMappings) {
+ if (uiccSlotMapping.getLogicalSlotIndex() == removedLogicalSlotId) {
+ if (!isPsim) {
+ // Replace this uiccSlotMapping
+ newUiccSlotMappings.add(new UiccSlotMapping(port, physicalSlotId,
+ uiccSlotMapping.getLogicalSlotIndex()));
+ }
+ continue;
+ }
+
+ // If the psim is inserted, then change the logicalSlotIndex for another
+ // uiccSlotMappings.
+ newUiccSlotMappings.add(isPsim
+ ? new UiccSlotMapping(uiccSlotMapping.getPortIndex(),
+ uiccSlotMapping.getPhysicalSlotIndex(), logicalSlotIndex++)
+ : uiccSlotMapping);
}
- Log.i(TAG, "The SimSlotMapping: " + newUiccSlotMappings);
+ Log.d(TAG, "The new SimSlotMapping: " + newUiccSlotMappings);
return newUiccSlotMappings;
}
+
+ /**
+ * To get the excluded logical slot index from uiccSlotMapping list. If the sim which is
+ * enabled by user does not have the corresponding slot, then it needs to do the
+ * SimSlotMapping changed. This method can find the logical slot index of the corresponding slot
+ * before the Frameworks do the SimSlotMapping changed.
+ *
+ * @param uiccSlotMappings The uiccSlotMapping list from the Telephony Frameworks.
+ * @param activeSubInfos The active subscriptionInfo list.
+ * @param removedSubInfo The removed sim card which is selected by the user. If the user
+ * don't select removed sim , then the value is null.
+ * @param isMultiSimEnabled whether the device is in the DSDS mode or not.
+ * @return The logical slot index of removed slot. If it can't find the removed slot, it
+ * returns {@link #INVALID_LOGICAL_SLOT_ID}.
+ */
+ @VisibleForTesting
+ static int getExcludedLogicalSlotIndex(Collection<UiccSlotMapping> uiccSlotMappings,
+ Collection<SubscriptionInfo> activeSubInfos, SubscriptionInfo removedSubInfo,
+ boolean isMultiSimEnabled) {
+ if (!isMultiSimEnabled) {
+ Log.i(TAG, "In the ss mode.");
+ return 0;
+ }
+ if (removedSubInfo != null) {
+ // Use removedSubInfo's logicalSlotIndex
+ Log.i(TAG, "The removedSubInfo is not null");
+ return removedSubInfo.getSimSlotIndex();
+ }
+ // If it needs to do simSlotMapping when user enables sim and there is an empty slot which
+ // there is no enabled sim in this slot, then the empty slot can be removed.
+ Log.i(TAG, "The removedSubInfo is null");
+ return uiccSlotMappings.stream()
+ .filter(uiccSlotMapping -> {
+ // find the empty slots.
+ for (SubscriptionInfo subInfo : activeSubInfos) {
+ if (subInfo.getSimSlotIndex() == uiccSlotMapping.getLogicalSlotIndex()) {
+ return false;
+ }
+ }
+ return true;
+ })
+ .sorted(Comparator.comparingInt(UiccSlotMapping::getLogicalSlotIndex))
+ .mapToInt(uiccSlotMapping -> uiccSlotMapping.getLogicalSlotIndex())
+ .findFirst()
+ .orElse(INVALID_LOGICAL_SLOT_ID);
+ }
}
diff --git a/src/com/android/settings/network/telephony/ConfirmDialogFragment.java b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
index 6352180..dceaf1c 100644
--- a/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
+++ b/src/com/android/settings/network/telephony/ConfirmDialogFragment.java
@@ -25,6 +25,7 @@
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
@@ -115,13 +116,12 @@
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setPositiveButton(posBtnString, this)
.setNegativeButton(negBtnString, this);
+ View content = LayoutInflater.from(getContext()).inflate(
+ R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
- if (list != null && !list.isEmpty()) {
+ if (list != null && !list.isEmpty() && content != null) {
Log.i(TAG, "list =" + list.toString());
- View content = LayoutInflater.from(getContext()).inflate(
- R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
-
if (!TextUtils.isEmpty(title)) {
View titleView = LayoutInflater.from(getContext()).inflate(
R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported,
@@ -133,6 +133,7 @@
TextView dialogMessage = content.findViewById(R.id.msg);
if (!TextUtils.isEmpty(message) && dialogMessage != null) {
dialogMessage.setText(message);
+ dialogMessage.setVisibility(View.VISIBLE);
}
final ArrayAdapter<String> arrayAdapterItems = new ArrayAdapter<String>(
@@ -140,8 +141,8 @@
R.layout.sim_confirm_dialog_item_multiple_enabled_profiles_supported, list);
final ListView lvItems = content.findViewById(R.id.carrier_list);
if (lvItems != null) {
+ lvItems.setVisibility(View.VISIBLE);
lvItems.setAdapter(arrayAdapterItems);
- lvItems.setChoiceMode(ListView.CHOICE_MODE_NONE);
lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
@@ -158,6 +159,10 @@
}
});
}
+ final LinearLayout infoOutline = content.findViewById(R.id.info_outline_layout);
+ if (infoOutline != null) {
+ infoOutline.setVisibility(View.VISIBLE);
+ }
builder.setView(content);
} else {
if (!TextUtils.isEmpty(title)) {
diff --git a/src/com/android/settings/sim/ChooseSimActivity.java b/src/com/android/settings/sim/ChooseSimActivity.java
index d0ccc4c..cebc1ba 100644
--- a/src/com/android/settings/sim/ChooseSimActivity.java
+++ b/src/com/android/settings/sim/ChooseSimActivity.java
@@ -159,11 +159,12 @@
mSelectedItemIndex = subItem.getId();
if (mSelectedItemIndex == INDEX_PSIM) {
Log.i(TAG, "Ready to switch to pSIM slot.");
- mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID);
+ mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID, null);
} else {
Log.i(TAG, "Ready to switch to eSIM subscription with index: " + mSelectedItemIndex);
mSwitchToEuiccSubscriptionSidecar.run(
- mEmbeddedSubscriptions.get(mSelectedItemIndex).getSubscriptionId());
+ mEmbeddedSubscriptions.get(mSelectedItemIndex).getSubscriptionId(),
+ UiccSlotUtil.INVALID_PORT_ID, null);
}
}
diff --git a/src/com/android/settings/sim/PreferredSimDialogFragment.java b/src/com/android/settings/sim/PreferredSimDialogFragment.java
index 7786dd1..6b5e2b5 100644
--- a/src/com/android/settings/sim/PreferredSimDialogFragment.java
+++ b/src/com/android/settings/sim/PreferredSimDialogFragment.java
@@ -84,10 +84,11 @@
private void updateDialog(AlertDialog dialog) {
Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed);
- final SubscriptionInfo info = getPreferredSubscription();
if (mWasDismissed) {
return;
}
+
+ final SubscriptionInfo info = getPreferredSubscription();
if (info == null) {
dismiss();
return;
diff --git a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
index f5c2406..1f84177 100644
--- a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
+++ b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
@@ -26,8 +26,6 @@
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -88,10 +86,11 @@
if (subInfos == null || dds == null) {
return null;
}
- return subInfos.stream().filter(subinfo -> subinfo != dds).findFirst().orElse(null);
+ return subInfos.stream().filter(subinfo -> subinfo.getSubscriptionId()
+ != dds.getSubscriptionId()).findFirst().orElse(null);
}
- private SubscriptionInfo getDefaultDataSubId() {
+ private SubscriptionInfo getDefaultDataSubInfo() {
return getSubscriptionManager().getDefaultDataSubscriptionInfo();
}
@@ -101,20 +100,22 @@
return;
}
- SubscriptionInfo activeSubInfo = getDefaultDataSubId();
- SubscriptionInfo newSubInfo = getNonDefaultDataSubscriptionInfo(activeSubInfo);
+ SubscriptionInfo currentDataSubInfo = getDefaultDataSubInfo();
+ SubscriptionInfo newSubInfo = getNonDefaultDataSubscriptionInfo(currentDataSubInfo);
- if (newSubInfo == null || activeSubInfo == null) {
+ if (newSubInfo == null || currentDataSubInfo == null) {
+ Log.d(TAG, "one of target SubscriptionInfos is null");
dismiss();
return;
}
-
+ Log.d(TAG, "newSubId: " + newSubInfo.getSubscriptionId()
+ + "currentDataSubID: " + currentDataSubInfo.getSubscriptionId());
setTargetSubscriptionInfo(newSubInfo);
CharSequence newDataCarrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
newSubInfo, getContext());
CharSequence currentDataCarrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName(
- activeSubInfo, getContext());
+ currentDataSubInfo, getContext());
String positive = getContext().getString(
R.string.select_specific_sim_for_data_button, newDataCarrierName);
@@ -123,18 +124,10 @@
View content = LayoutInflater.from(getContext()).inflate(
R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
- TextView dialogMessage = content.findViewById(R.id.msg);
+ TextView dialogMessage = content != null ? content.findViewById(R.id.msg) : null;
if (!TextUtils.isEmpty(message) && dialogMessage != null) {
dialogMessage.setText(message);
- }
-
- final ListView lvItems = content.findViewById(R.id.carrier_list);
- if (lvItems != null) {
- lvItems.setVisibility(View.GONE);
- }
- final LinearLayout infoOutline = content.findViewById(R.id.info_outline_layout);
- if (infoOutline != null) {
- infoOutline.setVisibility(View.GONE);
+ dialogMessage.setVisibility(View.VISIBLE);
}
dialog.setView(content);
diff --git a/src/com/android/settings/sim/SimDialogFragment.java b/src/com/android/settings/sim/SimDialogFragment.java
index 889f062..2e4fa49 100644
--- a/src/com/android/settings/sim/SimDialogFragment.java
+++ b/src/com/android/settings/sim/SimDialogFragment.java
@@ -83,6 +83,12 @@
}
}
+ @Override
+ public void dismiss() {
+ mChangeListener.stop();
+ super.dismiss();
+ }
+
public abstract void updateDialog();
@Override
diff --git a/src/com/android/settings/sim/SimListDialogFragment.java b/src/com/android/settings/sim/SimListDialogFragment.java
index 629a087..166d00a 100644
--- a/src/com/android/settings/sim/SimListDialogFragment.java
+++ b/src/com/android/settings/sim/SimListDialogFragment.java
@@ -19,7 +19,6 @@
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -28,6 +27,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
@@ -47,12 +47,10 @@
* Shows a dialog consisting of a list of SIMs (aka subscriptions), possibly including an additional
* entry indicating "ask me every time".
*/
-public class SimListDialogFragment extends SimDialogFragment implements
- DialogInterface.OnClickListener {
+public class SimListDialogFragment extends SimDialogFragment {
private static final String TAG = "SimListDialogFragment";
protected static final String KEY_INCLUDE_ASK_EVERY_TIME = "include_ask_every_time";
protected static final String KEY_SHOW_CANCEL_ITEM = "show_cancel_item";
- private static final int LIST_VIEW_DIVIDER_LINE_WEIGHT = 2;
protected SelectSubscriptionAdapter mAdapter;
@VisibleForTesting
@@ -79,21 +77,36 @@
TextView titleTextView = titleView.findViewById(R.id.title);
titleTextView.setText(getContext().getString(getTitleResId()));
builder.setCustomTitle(titleTextView);
-
mAdapter = new SelectSubscriptionAdapter(builder.getContext(), mSubscriptions);
- setAdapter(builder);
final AlertDialog dialog = builder.create();
- ListView listView = dialog.getListView();
- if (listView != null) {
- listView.setDividerHeight(LIST_VIEW_DIVIDER_LINE_WEIGHT);
+
+ View content = LayoutInflater.from(getContext()).inflate(
+ R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
+
+ final ListView lvItems = content != null ? content.findViewById(R.id.carrier_list) : null;
+ if (lvItems != null) {
+ setAdapter(lvItems);
+ lvItems.setVisibility(View.VISIBLE);
+ lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ onClick(position);
+ }
+ });
}
+
+ dialog.setView(content);
updateDialog();
+
return dialog;
}
- @Override
- public void onClick(DialogInterface dialog, int selectionIndex) {
+ /**
+ * If the user click the item at the list, then it sends the callback.
+ * @param selectionIndex the index of item in the list.
+ */
+ public void onClick(int selectionIndex) {
if (selectionIndex >= 0 && selectionIndex < mSubscriptions.size()) {
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
final SubscriptionInfo subscription = mSubscriptions.get(selectionIndex);
@@ -103,6 +116,7 @@
final SimDialogActivity activity = (SimDialogActivity) getActivity();
activity.onSubscriptionSelected(getDialogType(), subId);
}
+ dismiss();
}
protected List<SubscriptionInfo> getCurrentSubscriptions() {
@@ -114,12 +128,13 @@
@Override
public void updateDialog() {
Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed);
+ if (mWasDismissed) {
+ return;
+ }
List<SubscriptionInfo> currentSubscriptions = getCurrentSubscriptions();
if (currentSubscriptions == null) {
- if (!mWasDismissed) {
- dismiss();
- }
+ dismiss();
return;
}
boolean includeAskEveryTime = getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME);
@@ -143,14 +158,15 @@
if (currentSubscriptions.equals(mSubscriptions)) {
return;
}
+
mSubscriptions.clear();
mSubscriptions.addAll(currentSubscriptions);
mAdapter.notifyDataSetChanged();
}
@VisibleForTesting
- void setAdapter(AlertDialog.Builder builder) {
- builder.setAdapter(mAdapter, this);
+ void setAdapter(ListView lvItems) {
+ lvItems.setAdapter(mAdapter);
}
@Override
@@ -200,6 +216,16 @@
final TextView title = convertView.findViewById(R.id.title);
final TextView summary = convertView.findViewById(R.id.summary);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
+ if (lp != null) {
+ lp.setMargins(0, mContext.getResources().getDimensionPixelSize(
+ R.dimen.sims_select_margin_top), 0,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.sims_select_margin_bottom));
+ convertView.setLayoutParams(lp);
+ }
+
if (sub == null) {
if (position == 0) {
title.setText(R.string.sim_calls_ask_first_prefs_title);
diff --git a/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java b/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
index be2fa2d..db6e1b4 100644
--- a/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
+++ b/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
@@ -23,6 +23,7 @@
import com.android.settings.R;
import com.android.settings.SidecarFragment;
import com.android.settings.network.SwitchToEuiccSubscriptionSidecar;
+import com.android.settings.network.UiccSlotUtil;
import com.android.settings.network.telephony.AlertDialogFragment;
import com.android.settings.network.telephony.ConfirmDialogFragment;
import com.android.settings.network.telephony.SubscriptionActionDialogActivity;
@@ -110,7 +111,8 @@
return;
}
Log.i(TAG, "User confirmed to switch to embedded slot.");
- mSwitchToEuiccSubscriptionSidecar.run(mSubToEnabled.getSubscriptionId());
+ mSwitchToEuiccSubscriptionSidecar.run(mSubToEnabled.getSubscriptionId(),
+ UiccSlotUtil.INVALID_PORT_ID, null);
showProgressDialog(
getString(
R.string.sim_action_switch_sub_dialog_progress,
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
index e0bc9cd..4a6b96c 100644
--- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
+++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
@@ -26,12 +26,14 @@
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.SubscriptionUtil;
import com.android.settings.network.UiccSlotUtil;
import com.android.settings.network.UiccSlotsException;
+import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
import com.android.settings.sim.ChooseSimActivity;
import com.android.settings.sim.DsdsDialogActivity;
import com.android.settings.sim.SimActivationNotifier;
@@ -40,6 +42,7 @@
import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -83,8 +86,8 @@
throw new IllegalStateException("Cannot be called from main thread.");
}
- if (mTelMgr.getActiveModemCount() > 1) {
- Log.i(TAG, "The device is already in DSDS mode. Do nothing.");
+ if (mTelMgr.getActiveModemCount() > 1 && !isMultipleEnabledProfilesSupported()) {
+ Log.i(TAG, "The device is already in DSDS mode and no MEP. Do nothing.");
return;
}
@@ -96,17 +99,30 @@
int lastRemovableSlotState = getLastRemovableSimSlotState(mContext);
int currentRemovableSlotState = removableSlotInfo.getCardStateInfo();
+ boolean isRemovableSimInserted =
+ lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
+ && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT;
+ boolean isRemovableSimRemoved =
+ lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT
+ && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT;
// Sets the current removable slot state.
setRemovableSimSlotState(mContext, currentRemovableSlotState);
- if (lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
- && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT) {
+ if (mTelMgr.getActiveModemCount() > 1 && isMultipleEnabledProfilesSupported()) {
+ if(!isRemovableSimInserted) {
+ Log.i(TAG, "Removable Sim is not inserted in DSDS mode and MEP. Do nothing.");
+ return;
+ }
+ handleRemovableSimInsertUnderDsdsMep(removableSlotInfo);
+ return;
+ }
+
+ if (isRemovableSimInserted) {
handleSimInsert(removableSlotInfo);
return;
}
- if (lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT
- && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT) {
+ if (isRemovableSimRemoved) {
handleSimRemove(removableSlotInfo);
return;
}
@@ -210,10 +226,11 @@
}
List<SubscriptionInfo> groupedEmbeddedSubscriptions = getGroupedEmbeddedSubscriptions();
-
if (groupedEmbeddedSubscriptions.size() == 0 || !removableSlotInfo.getPorts().stream()
.findFirst().get().isActive()) {
- Log.i(TAG, "eSIM slot is active or no subscriptions exist. Do nothing.");
+ Log.i(TAG, "eSIM slot is active or no subscriptions exist. Do nothing."
+ + " The removableSlotInfo: " + removableSlotInfo
+ + ", groupedEmbeddedSubscriptions: " + groupedEmbeddedSubscriptions);
return;
}
@@ -231,6 +248,24 @@
startChooseSimActivity(false);
}
+ private void handleRemovableSimInsertUnderDsdsMep(UiccSlotInfo removableSlotInfo) {
+ Log.i(TAG, "Handle Removable SIM inserted under DSDS+Mep.");
+
+ if (removableSlotInfo.getPorts().stream().findFirst().get().isActive()) {
+ Log.i(TAG, "The removable slot is already active. Do nothing. removableSlotInfo: "
+ + removableSlotInfo);
+ return;
+ }
+
+ List<SubscriptionInfo> subscriptionInfos = getAvailableRemovableSubscription();
+ if (subscriptionInfos == null || subscriptionInfos.get(0) == null) {
+ Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.");
+ return;
+ }
+ Log.d(TAG, "getAvailableRemovableSubscription:" + subscriptionInfos);
+ startSimConfirmDialogActivity(subscriptionInfos.get(0).getSubscriptionId());
+ }
+
private int getLastRemovableSimSlotState(Context context) {
final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
return prefs.getInt(KEY_REMOVABLE_SLOT_STATE, UiccSlotInfo.CARD_STATE_INFO_ABSENT);
@@ -260,7 +295,6 @@
}
for (UiccSlotInfo slotInfo : slotInfos) {
if (slotInfo != null && slotInfo.isRemovable()) {
-
return slotInfo;
}
}
@@ -296,6 +330,16 @@
.collect(Collectors.toList()));
}
+ protected List<SubscriptionInfo> getAvailableRemovableSubscription() {
+ List<SubscriptionInfo> subList = new ArrayList<>();
+ for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
+ if (!info.isEmbedded()) {
+ subList.add(info);
+ }
+ }
+ return subList;
+ }
+
private void startChooseSimActivity(boolean psimInserted) {
Intent intent = ChooseSimActivity.getIntent(mContext);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -316,5 +360,26 @@
mContext.startActivity(intent);
}
+ private void startSimConfirmDialogActivity(int subId) {
+ if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
+ Log.i(TAG, "Unable to enable subscription due to invalid subscription ID.");
+ return;
+ }
+ Log.d(TAG, "Start ToggleSubscriptionDialogActivity with " + subId + " under DSDS+Mep.");
+ Intent intent = ToggleSubscriptionDialogActivity.getIntent(mContext, subId, true);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ }
+
+ private boolean isMultipleEnabledProfilesSupported() {
+ List<UiccCardInfo> cardInfos = mTelMgr.getUiccCardsInfo();
+ if (cardInfos == null) {
+ Log.d(TAG, "UICC cards info list is empty.");
+ return false;
+ }
+ return cardInfos.stream().anyMatch(
+ cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
+ }
+
private SimSlotChangeHandler() {}
}
diff --git a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
index 070bcb1..7b17b74 100644
--- a/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimListDialogFragmentTest.java
@@ -77,7 +77,7 @@
doReturn(activity).when(mFragment).getActivity();
doNothing().when(activity).onSubscriptionSelected(anyInt(), anyInt());
- mFragment.onClick(alertDialog, 1);
+ mFragment.onClick(1);
verify(activity).onSubscriptionSelected(dialogType, SIM2_ID);
}
@@ -117,7 +117,7 @@
doReturn(activity).when(mFragment).getActivity();
doNothing().when(activity).onSubscriptionSelected(anyInt(), anyInt());
- mFragment.onClick(alertDialog, 0);
+ mFragment.onClick(0);
verify(activity).onSubscriptionSelected(dialogType,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
}
diff --git a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
new file mode 100644
index 0000000..2cf9845
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2022 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;
+
+import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+import android.telephony.UiccPortInfo;
+import android.telephony.UiccSlotInfo;
+import android.telephony.UiccSlotMapping;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class UiccSlotUtilTest {
+ private Context mContext;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+
+ private static final int ESIM_PHYSICAL_SLOT = 0;
+ private static final int PSIM_PHYSICAL_SLOT = 1;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ }
+
+ @Test
+ public void getSlotInfos_oneSimSlotDevice_returnTheCorrectSlotInfoList() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(oneSimSlotDeviceActivePsim());
+ ImmutableList<UiccSlotInfo> testUiccSlotInfos =
+ UiccSlotUtil.getSlotInfos(mTelephonyManager);
+
+ assertThat(testUiccSlotInfos.size()).isEqualTo(1);
+ }
+
+ @Test
+ public void getSlotInfos_twoSimSlotsDevice_returnTheCorrectSlotInfoList() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActivePsimActiveEsim());
+ ImmutableList<UiccSlotInfo> testUiccSlotInfos =
+ UiccSlotUtil.getSlotInfos(mTelephonyManager);
+
+ assertThat(testUiccSlotInfos.size()).isEqualTo(2);
+ }
+
+ @Test
+ public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot0_returnTheCorrectEsimSlot() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActiveEsimActivePsim());
+ int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
+
+ assertThat(testSlot).isEqualTo(0);
+ }
+
+ @Test
+ public void getEsimSlotId_twoSimSlotsDeviceAndEsimIsSlot1_returnTheCorrectEsimSlot() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActivePsimActiveEsim());
+ int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
+
+ assertThat(testSlot).isEqualTo(1);
+ }
+
+ @Test
+ public void getEsimSlotId_noEimSlotDevice_returnTheCorrectEsimSlot() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ oneSimSlotDeviceActivePsim());
+ int testSlot = UiccSlotUtil.getEsimSlotId(mContext);
+
+ assertThat(testSlot).isEqualTo(-1);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromPsimActiveToEsimPort0Active_esimPort0Active() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModePsimActive();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingSsModeEsimPort0Active();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromEsimPort0ActiveToPsimActive_psimActive() {
+ Collection<UiccSlotMapping> uiccSlotMappings =
+ createUiccSlotMappingSsModeEsimPort0Active();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingSsModePsimActive();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromPsimAndPort0ToPsimAndPort1_psimAndPort1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromPsimAndPort1ToPsimAndPort0_psimAndPort0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromPsimAndPort0ToDualPortsB_dualPortsB() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingDualPortsB();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromPsimAndPort1ToDualPortsA_dualPortsA() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingDualPortsA();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_noPsimAndFromPsimAndPort0ToDualPortsB_dualPortsB() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingDualPortsB();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 1, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_noPsimAndFromPsimAndPort1ToDualPortsA_dualPortsA() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingDualPortsA();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, false, ESIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsAToPsimAndPort1_psimAndPort1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsAToPsimAndPort0_psimAndPort0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsBToPsimAndPort1_psimAndPort1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_oneEsimAndFromDualPortsBToPsimAndPort0_psimAndPort0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromDualPortsAToPsimAndPort1_psimAndPort1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromDualPortsAToPsimAndPort0_psimAndPort0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromDualPortsBToPsimAndPort1_psimAndPort1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort1();
+ int removedLogicalSlotIndex = 1;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void prepareUiccSlotMappings_fromDualPortsBToPsimAndPort0_psimAndPort0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<UiccSlotMapping> verifyUiccSlotMappings =
+ createUiccSlotMappingPsimAndPort0();
+ int removedLogicalSlotIndex = 0;
+
+ Collection<UiccSlotMapping> testUiccSlotMappings = UiccSlotUtil.prepareUiccSlotMappings(
+ uiccSlotMappings, true, PSIM_PHYSICAL_SLOT, 0, removedLogicalSlotIndex);
+
+ compareTwoUiccSlotMappings(testUiccSlotMappings, verifyUiccSlotMappings);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimActiveToEsimPort0Active_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModePsimActive();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, false);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromEsimPort0ActiveToPsimActive_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingSsModeEsimPort0Active();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, false);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort0ToPsimAndPort1_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 0);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort1ToPsimAndPort0_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 1);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort0ToDualPortsB_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromPsimAndPort1ToDualPortsA_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noPsimAndFromPsimAndPort0ToDualPortsB_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort0();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noPsimAndFromPsimAndPort1ToDualPortsA_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingPsimAndPort1();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsAToPsimAndPort1_logicalSlot0() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsAToPsimAndPort0_logicalSlot1() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsBToPsimAndPort1_logicalSlot1() {
+ // There is only one enabled esimPort1 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(0, 1);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_oneEsimAndFromDualPortsBToPsimAndPort0_logicalSlot0() {
+ // There is only one enabled esimPort0 before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListOneSim(1, 0);
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsAToPsimAndPort1_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 0);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsAToPsimAndPort0_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 0, 1, 1);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 1);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsBToPsimAndPort1_logicalSlot1() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 1, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(1, 0);
+ int verifyExcludedLogicalSlotIndex = 1;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_fromDualPortsBToPsimAndPort0_logicalSlot0() {
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList =
+ createActiveSubscriptionInfoListTwoSims(0, 1, 1, 0);
+ SubscriptionInfo removedSubInfo = createSubscriptionInfo(0, 1);
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noEsimAndFromDualPortsAToPsimAndPort1_logicalSlot0() {
+ // There is no profiles enabled on either esim port before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsA();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<>();
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noEsimAndFromDualPortsBToPsimAndPort0_logicalSlot0() {
+ // There is no profiles enabled on either esim port before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsB();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<>();
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ @Test
+ public void getExcludedLogicalSlotIndex_noEsimNoOrdingFromDualPortsBToPsimAndPort1_logical0() {
+ // There is no profiles enabled on either esim port before user enables the psim.
+ Collection<UiccSlotMapping> uiccSlotMappings = createUiccSlotMappingDualPortsBNoOrding();
+ Collection<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<>();
+ SubscriptionInfo removedSubInfo = null;
+ int verifyExcludedLogicalSlotIndex = 0;
+
+ int testExcludedLogicalSlotIndex = UiccSlotUtil.getExcludedLogicalSlotIndex(
+ uiccSlotMappings, activeSubscriptionInfoList, removedSubInfo, true);
+
+ assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
+ }
+
+ private void compareTwoUiccSlotMappings(Collection<UiccSlotMapping> testUiccSlotMappings,
+ Collection<UiccSlotMapping> verifyUiccSlotMappings) {
+ assertThat(testUiccSlotMappings.size()).isEqualTo(verifyUiccSlotMappings.size());
+ Iterator<UiccSlotMapping> testIterator = testUiccSlotMappings.iterator();
+ Iterator<UiccSlotMapping> verifyIterator = verifyUiccSlotMappings.iterator();
+ while (testIterator.hasNext()) {
+ UiccSlotMapping testUiccSlotMapping = testIterator.next();
+ UiccSlotMapping verifyUiccSlotMapping = verifyIterator.next();
+ assertThat(testUiccSlotMapping.getLogicalSlotIndex()).isEqualTo(
+ verifyUiccSlotMapping.getLogicalSlotIndex());
+ assertThat(testUiccSlotMapping.getPortIndex()).isEqualTo(
+ verifyUiccSlotMapping.getPortIndex());
+ assertThat(testUiccSlotMapping.getPhysicalSlotIndex()).isEqualTo(
+ verifyUiccSlotMapping.getPhysicalSlotIndex());
+ }
+ }
+
+ private SubscriptionInfo createSubscriptionInfo(int logicalSlotIndex, int portIndex) {
+ return new SubscriptionInfo(
+ 0, "", logicalSlotIndex, "", "", 0, 0, "", 0, null, "", "", "",
+ true /* isEmbedded */,
+ null, "", 25,
+ false, null, false, 0, 0, 0, null, null, true, portIndex);
+ }
+
+ private List<SubscriptionInfo> createActiveSubscriptionInfoListOneSim(int logicalSlotIndex,
+ int portIndex) {
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex, portIndex));
+
+ return subscriptionInfoList;
+ }
+
+ private List<SubscriptionInfo> createActiveSubscriptionInfoListTwoSims(int logicalSlotIndex1,
+ int portIndex1, int logicalSlotIndex2, int portIndex2) {
+ List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex1, portIndex1));
+ subscriptionInfoList.add(createSubscriptionInfo(logicalSlotIndex2, portIndex2));
+ return subscriptionInfoList;
+ }
+
+ // Device | |Slot |
+ // Working| |Mapping|
+ // State |Type |Mode |Friendly name
+ //--------------------------------------------------------------------------
+ // Single |SIM pSIM [RIL 0] |1 |pSIM active
+ // Single |SIM MEP Port #0 [RIL0] |2 |eSIM Port0 active
+ // Single |SIM MEP Port #1 [RIL0] |2.1 |eSIM Port1 active
+ // DSDS |pSIM [RIL 0] + MEP Port #0 [RIL 1] |3 |pSIM+Port0
+ // DSDS |pSIM [RIL 0] + MEP Port #1 [RIL 1] |3.1 |pSIM+Port1
+ // DSDS |MEP Port #0 [RIL 0] + MEP Port #1 [RIL1]|3.2 |Dual-Ports-A
+ // DSDS |MEP Port #1 [RIL 0] + MEP Port #0 [RIL1]|4 |Dual-Ports-B
+ private List<UiccSlotMapping> createUiccSlotMappingSsModePsimActive() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingSsModeEsimPort0Active() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 0));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingSsModeEsimPort1Active() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingPsimAndPort0() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0));
+ slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 1));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingPsimAndPort1() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, PSIM_PHYSICAL_SLOT, 0));
+ slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 1));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingDualPortsA() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 0));
+ slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 1));
+
+ return slotMap;
+ }
+
+ private List<UiccSlotMapping> createUiccSlotMappingDualPortsB() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0));
+ slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 1));
+
+ return slotMap;
+ }
+ private List<UiccSlotMapping> createUiccSlotMappingDualPortsBNoOrding() {
+ List<UiccSlotMapping> slotMap = new ArrayList<>();
+ slotMap.add(new UiccSlotMapping(0, ESIM_PHYSICAL_SLOT, 1));
+ slotMap.add(new UiccSlotMapping(1, ESIM_PHYSICAL_SLOT, 0));
+
+ return slotMap;
+ }
+ /**
+ * The "oneSimSlotDevice" has below cases
+ * 1) The device is one psim slot and no esim slot
+ * 2) The device is no psim slot and one esim slot. like the watch.
+ *
+ * The "twoSimsSlotDevice" has below cases
+ * 1) The device is one psim slot and one esim slot
+ * 2) The device is two psim slots
+ */
+
+ private UiccSlotInfo[] oneSimSlotDeviceActivePsim() {
+ return new UiccSlotInfo[]{createUiccSlotInfo(false, true, 0, true)};
+ }
+
+ private UiccSlotInfo[] oneSimSlotDeviceActiveEsim() {
+ return new UiccSlotInfo[]{createUiccSlotInfo(true, false, 1, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceActivePsimActiveEsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(false, true, 0, true),
+ createUiccSlotInfo(true, false, 1, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceActiveEsimActivePsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(true, false, 0, true),
+ createUiccSlotInfo(false, true, 1, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceTwoActiveEsims() {
+ // device supports MEP, so device can enable two esims.
+ // If device has psim slot, the UiccSlotInfo of psim always be in UiccSlotInfo[].
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(false, true, -1, true),
+ createUiccSlotInfoForEsimMep(0, true, 1, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceActivePsimInactiveEsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(false, true, 0, true),
+ createUiccSlotInfo(true, false, -1, false)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceInactivePsimActiveEsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(false, true, 0, false),
+ createUiccSlotInfo(true, false, 1, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceNoInsertPsimActiveEsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(false, true, -1, false),
+ createUiccSlotInfo(true, false, 1, true)};
+ }
+ //ToDo: add more cases.
+
+ private UiccSlotInfo createUiccSlotInfo(boolean isEuicc, boolean isRemovable,
+ int logicalSlotIdx, boolean isActive) {
+ return new UiccSlotInfo(
+ isEuicc, /* isEuicc */
+ "123", /* cardId */
+ CARD_STATE_INFO_PRESENT, /* cardStateInfo */
+ true, /* isExtendApduSupported */
+ isRemovable, /* isRemovable */
+ Collections.singletonList(
+ new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
+ logicalSlotIdx /* logicalSlotIdx */, isActive /* isActive */))
+ );
+ }
+
+ private UiccSlotInfo createUiccSlotInfoForEsimMep(int logicalSlotIdx1, boolean isActiveEsim1,
+ int logicalSlotIdx2, boolean isActiveEsim2) {
+ return new UiccSlotInfo(
+ true, /* isEuicc */
+ "123", /* cardId */
+ CARD_STATE_INFO_PRESENT, /* cardStateInfo */
+ true, /* isExtendApduSupported */
+ false, /* isRemovable */
+ Arrays.asList(
+ new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
+ logicalSlotIdx1 /* logicalSlotIdx */, isActiveEsim1 /* isActive */),
+ new UiccPortInfo("" /* iccId */, 1 /* portIdx */,
+ logicalSlotIdx2 /* logicalSlotIdx */,
+ isActiveEsim2 /* isActive */)));
+ }
+}