Merge changes I6871db6c,Ia261e3b4,I1588bd4a,I1b81faf0,I9a596440, ...
* changes: [MEP] sort the simSlotMapping by logcal slot id In E+E, the user can't enable the PSIM [MEP] psim's logical slot index is 0 [MEP] The condition of "null point check" is wrong Fix the settings crash when SimDialogActivity is null [MEP] The subscriptionInfo's getSimSlotIndex is logical slotId [MEP] the port id is wrong [MEP] Inserting a pSIM while user has 2 esims, showing the MEP dialog [MEP] Refactor SlotSidecar API for all of sim page. [MEP]The Esim's PhysicalSlotIndex is wrong Lost code for setting the list as visible The list does not follow the UX dialog design doc in alert dialog. The carrier name is wrong in the dialog Refine the mobile data selection UI
This commit is contained in:
@@ -78,11 +78,19 @@ public class SwitchSlotSidecar
|
||||
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);
|
||||
|
||||
@@ -21,14 +21,13 @@ import android.app.PendingIntent;
|
||||
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 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
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 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
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 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
mEuiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, mPort,
|
||||
mCallbackIntent);
|
||||
} else {
|
||||
mSwitchSlotSidecar.runSwitchToEuiccSlot(getTargetSlot(), mPort, removedSubInfo);
|
||||
mSwitchSlotSidecar.runSwitchToEuiccSlot(targetSlot, mPort, removedSubInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,18 +126,26 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
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 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
}
|
||||
|
||||
private int getTargetSlot() {
|
||||
return ESIM_SLOT_ID;
|
||||
return UiccSlotUtil.getEsimSlotId(getContext());
|
||||
}
|
||||
|
||||
private void onSwitchSlotSidecarStateChange() {
|
||||
|
||||
@@ -80,29 +80,6 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -124,7 +101,7 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
||||
// 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,
|
||||
|
||||
@@ -20,11 +20,13 @@ import android.annotation.IntDef;
|
||||
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.Retention;
|
||||
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 @@ public class UiccSlotUtil {
|
||||
|
||||
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 @@ public class UiccSlotUtil {
|
||||
}
|
||||
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 @@ public class UiccSlotUtil {
|
||||
* 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 @@ public class UiccSlotUtil {
|
||||
* 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 @@ public class UiccSlotUtil {
|
||||
}
|
||||
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 @@ public class UiccSlotUtil {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.view.LayoutInflater;
|
||||
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 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
||||
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 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
||||
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 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
||||
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 @@ public class ConfirmDialogFragment extends BaseDialogFragment
|
||||
}
|
||||
});
|
||||
}
|
||||
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)) {
|
||||
|
||||
@@ -159,11 +159,12 @@ public class ChooseSimActivity extends Activity
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,10 +84,11 @@ public class PreferredSimDialogFragment extends SimDialogFragment implements
|
||||
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;
|
||||
|
||||
@@ -26,8 +26,6 @@ import android.text.TextUtils;
|
||||
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 @@ public class SelectSpecificDataSimDialogFragment extends SimDialogFragment imple
|
||||
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 @@ public class SelectSpecificDataSimDialogFragment extends SimDialogFragment imple
|
||||
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 @@ public class SelectSpecificDataSimDialogFragment extends SimDialogFragment imple
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -83,6 +83,12 @@ public abstract class SimDialogFragment extends InstrumentedDialogFragment imple
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
mChangeListener.stop();
|
||||
super.dismiss();
|
||||
}
|
||||
|
||||
public abstract void updateDialog();
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.settings.sim;
|
||||
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.util.Log;
|
||||
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 @@ import java.util.List;
|
||||
* 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 @@ public class SimListDialogFragment extends SimDialogFragment implements
|
||||
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 @@ public class SimListDialogFragment extends SimDialogFragment implements
|
||||
final SimDialogActivity activity = (SimDialogActivity) getActivity();
|
||||
activity.onSubscriptionSelected(getDialogType(), subId);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
protected List<SubscriptionInfo> getCurrentSubscriptions() {
|
||||
@@ -114,12 +128,13 @@ public class SimListDialogFragment extends SimDialogFragment implements
|
||||
@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 @@ public class SimListDialogFragment extends SimDialogFragment implements
|
||||
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 @@ public class SimListDialogFragment extends SimDialogFragment implements
|
||||
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);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.util.Log;
|
||||
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 @@ public class SwitchToEsimConfirmDialogActivity extends SubscriptionActionDialogA
|
||||
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,
|
||||
|
||||
@@ -26,12 +26,14 @@ import android.provider.Settings;
|
||||
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.android.settings.sim.SwitchToEsimConfirmDialogActivity;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -83,8 +86,8 @@ public class SimSlotChangeHandler {
|
||||
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 @@ public class SimSlotChangeHandler {
|
||||
|
||||
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 @@ public class SimSlotChangeHandler {
|
||||
}
|
||||
|
||||
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 @@ public class SimSlotChangeHandler {
|
||||
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 @@ public class SimSlotChangeHandler {
|
||||
}
|
||||
for (UiccSlotInfo slotInfo : slotInfos) {
|
||||
if (slotInfo != null && slotInfo.isRemovable()) {
|
||||
|
||||
return slotInfo;
|
||||
}
|
||||
}
|
||||
@@ -296,6 +330,16 @@ public class SimSlotChangeHandler {
|
||||
.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 @@ public class SimSlotChangeHandler {
|
||||
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() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user