Merge "[MEP] eSIM API refactor to support MEP"

This commit is contained in:
Chen Xu
2022-01-04 18:50:09 +00:00
committed by Gerrit Code Review
17 changed files with 894 additions and 87 deletions

View File

@@ -42580,6 +42580,7 @@ package android.telephony {
method @Deprecated public int getMnc(); method @Deprecated public int getMnc();
method @Nullable public String getMncString(); method @Nullable public String getMncString();
method public String getNumber(); method public String getNumber();
method public int getPortIndex();
method public int getSimSlotIndex(); method public int getSimSlotIndex();
method public int getSubscriptionId(); method public int getSubscriptionId();
method public int getSubscriptionType(); method public int getSubscriptionType();
@@ -43126,14 +43127,28 @@ package android.telephony {
method public int describeContents(); method public int describeContents();
method public int getCardId(); method public int getCardId();
method @Nullable public String getEid(); method @Nullable public String getEid();
method @Nullable public String getIccId(); method @Deprecated @Nullable public String getIccId();
method public int getSlotIndex(); method public int getPhysicalSlotIndex();
method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
method @Deprecated public int getSlotIndex();
method public boolean isEuicc(); method public boolean isEuicc();
method public boolean isMultipleEnabledProfilesSupported();
method public boolean isRemovable(); method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
} }
public final class UiccPortInfo implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String getIccId();
method @IntRange(from=0) public int getLogicalSlotIndex();
method @IntRange(from=0) public int getPortIndex();
method public boolean isActive();
method public void writeToParcel(@Nullable android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccPortInfo> CREATOR;
field public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
}
public abstract class VisualVoicemailService extends android.app.Service { public abstract class VisualVoicemailService extends android.app.Service {
ctor public VisualVoicemailService(); ctor public VisualVoicemailService();
method public android.os.IBinder onBind(android.content.Intent); method public android.os.IBinder onBind(android.content.Intent);
@@ -43434,6 +43449,7 @@ package android.telephony.euicc {
method @Nullable public String getEid(); method @Nullable public String getEid();
method @Nullable public android.telephony.euicc.EuiccInfo getEuiccInfo(); method @Nullable public android.telephony.euicc.EuiccInfo getEuiccInfo();
method public boolean isEnabled(); method public boolean isEnabled();
method public boolean isSimPortAvailable(int);
method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException; method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent); method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent); method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);

View File

@@ -12140,6 +12140,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimSlotMapping(@NonNull java.util.Collection<android.telephony.UiccSlotMapping>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -12151,7 +12152,7 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor); method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation(); method public void updateServiceLocation();
@@ -12325,10 +12326,11 @@ package android.telephony {
method public int describeContents(); method public int describeContents();
method public String getCardId(); method public String getCardId();
method public int getCardStateInfo(); method public int getCardStateInfo();
method public boolean getIsActive(); method @Deprecated public boolean getIsActive();
method public boolean getIsEuicc(); method public boolean getIsEuicc();
method public boolean getIsExtendedApduSupported(); method public boolean getIsExtendedApduSupported();
method public int getLogicalSlotIdx(); method @Deprecated public int getLogicalSlotIdx();
method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
method public boolean isRemovable(); method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);
field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1 field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -12338,6 +12340,15 @@ package android.telephony {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
} }
public final class UiccSlotMapping implements android.os.Parcelable {
method public int describeContents();
method @IntRange(from=0) public int getLogicalSlotIndex();
method @IntRange(from=0) public int getPhysicalSlotIndex();
method @IntRange(from=0) public int getPortIndex();
method public void writeToParcel(@Nullable android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotMapping> CREATOR;
}
public abstract class VisualVoicemailService extends android.app.Service { public abstract class VisualVoicemailService extends android.app.Service {
method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent); method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent);
method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
@@ -12631,7 +12642,8 @@ package android.telephony.euicc {
method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); method @Deprecated public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void disableProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
@@ -12649,7 +12661,8 @@ package android.telephony.euicc {
method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); method @Deprecated public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
method public void switchToProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0 field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1 field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3 field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3

View File

@@ -221,6 +221,11 @@ public class SubscriptionInfo implements Parcelable {
*/ */
private boolean mAreUiccApplicationsEnabled = true; private boolean mAreUiccApplicationsEnabled = true;
/**
* The port index of the Uicc card.
*/
private final int mPortIndex;
/** /**
* Public copy constructor. * Public copy constructor.
* @hide * @hide
@@ -274,6 +279,22 @@ public class SubscriptionInfo implements Parcelable {
int carrierId, int profileClass, int subType, @Nullable String groupOwner, int carrierId, int profileClass, int subType, @Nullable String groupOwner,
@Nullable UiccAccessRule[] carrierConfigAccessRules, @Nullable UiccAccessRule[] carrierConfigAccessRules,
boolean areUiccApplicationsEnabled) { boolean areUiccApplicationsEnabled) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString,
cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass,
subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 0);
}
/**
* @hide
*/
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId,
boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
int carrierId, int profileClass, int subType, @Nullable String groupOwner,
@Nullable UiccAccessRule[] carrierConfigAccessRules,
boolean areUiccApplicationsEnabled, int portIndex) {
this.mId = id; this.mId = id;
this.mIccId = iccId; this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex; this.mSimSlotIndex = simSlotIndex;
@@ -300,8 +321,8 @@ public class SubscriptionInfo implements Parcelable {
this.mGroupOwner = groupOwner; this.mGroupOwner = groupOwner;
this.mCarrierConfigAccessRules = carrierConfigAccessRules; this.mCarrierConfigAccessRules = carrierConfigAccessRules;
this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled; this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
this.mPortIndex = portIndex;
} }
/** /**
* @return the subscription ID. * @return the subscription ID.
*/ */
@@ -737,6 +758,14 @@ public class SubscriptionInfo implements Parcelable {
public int getCardId() { public int getCardId() {
return this.mCardId; return this.mCardId;
} }
/**
* Returns the port index of the SIM card which contains the subscription.
*
* @return the portIndex
*/
public int getPortIndex() {
return this.mPortIndex;
}
/** /**
* Set whether the subscription's group is disabled. * Set whether the subscription's group is disabled.
@@ -783,6 +812,7 @@ public class SubscriptionInfo implements Parcelable {
UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR); UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString(); String cardString = source.readString();
int cardId = source.readInt(); int cardId = source.readInt();
int portId = source.readInt();
boolean isOpportunistic = source.readBoolean(); boolean isOpportunistic = source.readBoolean();
String groupUUID = source.readString(); String groupUUID = source.readString();
boolean isGroupDisabled = source.readBoolean(); boolean isGroupDisabled = source.readBoolean();
@@ -800,7 +830,7 @@ public class SubscriptionInfo implements Parcelable {
carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null, carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null,
mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId,
isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType, isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType,
groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled); groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, portId);
info.setAssociatedPlmns(ehplmns, hplmns); info.setAssociatedPlmns(ehplmns, hplmns);
return info; return info;
} }
@@ -830,6 +860,7 @@ public class SubscriptionInfo implements Parcelable {
dest.writeTypedArray(mNativeAccessRules, flags); dest.writeTypedArray(mNativeAccessRules, flags);
dest.writeString(mCardString); dest.writeString(mCardString);
dest.writeInt(mCardId); dest.writeInt(mCardId);
dest.writeInt(mPortIndex);
dest.writeBoolean(mIsOpportunistic); dest.writeBoolean(mIsOpportunistic);
dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString()); dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString());
dest.writeBoolean(mIsGroupDisabled); dest.writeBoolean(mIsGroupDisabled);
@@ -876,6 +907,7 @@ public class SubscriptionInfo implements Parcelable {
+ " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded + " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
+ " nativeAccessRules=" + Arrays.toString(mNativeAccessRules) + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
+ " cardString=" + cardStringToPrint + " cardId=" + mCardId + " cardString=" + cardStringToPrint + " cardId=" + mCardId
+ " portIndex=" + mPortIndex
+ " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID + " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID
+ " isGroupDisabled=" + mIsGroupDisabled + " isGroupDisabled=" + mIsGroupDisabled
+ " profileClass=" + mProfileClass + " profileClass=" + mProfileClass
@@ -892,7 +924,7 @@ public class SubscriptionInfo implements Parcelable {
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded, return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString, mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString,
mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled, mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled,
mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled); mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex);
} }
@Override @Override
@@ -925,6 +957,7 @@ public class SubscriptionInfo implements Parcelable {
&& Objects.equals(mCountryIso, toCompare.mCountryIso) && Objects.equals(mCountryIso, toCompare.mCountryIso)
&& Objects.equals(mCardString, toCompare.mCardString) && Objects.equals(mCardString, toCompare.mCardString)
&& Objects.equals(mCardId, toCompare.mCardId) && Objects.equals(mCardId, toCompare.mCardId)
&& mPortIndex == toCompare.mPortIndex
&& Objects.equals(mGroupOwner, toCompare.mGroupOwner) && Objects.equals(mGroupOwner, toCompare.mGroupOwner)
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName) && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName) && TextUtils.equals(mCarrierName, toCompare.mCarrierName)

View File

@@ -132,6 +132,8 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -145,6 +147,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
/** /**
* Provides access to information about the telephony services on * Provides access to information about the telephony services on
* the device. Applications can use the methods in this class to * the device. Applications can use the methods in this class to
@@ -3941,8 +3944,8 @@ public class TelephonyManager {
* <p> * <p>
* If the caller has carrier priviliges on any active subscription, then they have permission to * If the caller has carrier priviliges on any active subscription, then they have permission to
* get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card * get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card
* is an eUICC ({@link UiccCardInfo#isEuicc()}), and the slot index where the card is inserted * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the physical slot index where the card is
* ({@link UiccCardInfo#getSlotIndex()}). * inserted ({@link UiccCardInfo#getPhysicalSlotIndex()}.
* <p> * <p>
* To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID * To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID
* ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific * ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific
@@ -3986,7 +3989,7 @@ public class TelephonyManager {
if (telephony == null) { if (telephony == null) {
return null; return null;
} }
return telephony.getUiccSlotsInfo(); return telephony.getUiccSlotsInfo(mContext.getOpPackageName());
} catch (RemoteException e) { } catch (RemoteException e) {
return null; return null;
} }
@@ -4019,8 +4022,13 @@ public class TelephonyManager {
* size should be same as {@link #getUiccSlotsInfo()}. * size should be same as {@link #getUiccSlotsInfo()}.
* @return boolean Return true if the switch succeeds, false if the switch fails. * @return boolean Return true if the switch succeeds, false if the switch fails.
* @hide * @hide
* @deprecated {@link #setSimSlotMapping(Collection, Executor, Consumer)}
*/ */
// TODO: once integrating the HAL changes we can convert int[] to List<UiccSlotMapping> and
// converge API's in ITelephony.aidl and PhoneInterfaceManager
@SystemApi @SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean switchSlots(int[] physicalSlots) { public boolean switchSlots(int[] physicalSlots) {
try { try {
@@ -4034,6 +4042,109 @@ public class TelephonyManager {
} }
} }
/**
* @param slotMapping Logical to physical slot and port mapping.
* @return {@code true} if slotMapping is valid.
* @return {@code false} if slotMapping is invalid.
*
* slotMapping is invalid if there are different entries (physical slot + port) mapping to the
* same logical slot or if there are same {physical slot + port} mapping to the different
* logical slot
* @hide
*/
private static boolean isSlotMappingValid(@NonNull Collection<UiccSlotMapping> slotMapping) {
// Grouping the collection by logicalSlotIndex, finding different entries mapping to the
// same logical slot
Map<Integer, List<UiccSlotMapping>> slotMappingInfo = slotMapping.stream().collect(
Collectors.groupingBy(UiccSlotMapping::getLogicalSlotIndex));
for (Map.Entry<Integer, List<UiccSlotMapping>> entry : slotMappingInfo.entrySet()) {
List<UiccSlotMapping> logicalSlotMap = entry.getValue();
if (logicalSlotMap.size() > 1) {
// duplicate logicalSlotIndex found
return false;
}
}
// Grouping the collection by physical slot and port, finding same entries mapping to the
// different logical slot
Map<List<Integer>, List<UiccSlotMapping>> slotMapInfos = slotMapping.stream().collect(
Collectors.groupingBy(
slot -> Arrays.asList(slot.getPhysicalSlotIndex(), slot.getPortIndex())));
for (Map.Entry<List<Integer>, List<UiccSlotMapping>> entry : slotMapInfos.entrySet()) {
List<UiccSlotMapping> portAndPhysicalSlotList = entry.getValue();
if (portAndPhysicalSlotList.size() > 1) {
// duplicate pair of portIndex and physicalSlotIndex found
return false;
}
}
return true;
}
/**
* Maps the logical slots to physical slots and ports. Mapping is specified from
* {@link UiccSlotMapping} which consist of both physical slot index and port index.
* Logical slot is the slot that is seen by modem. Physical slot is the actual physical slot.
* Port index is the index (enumerated value) for the associated port available on the SIM.
* Each physical slot can have multiple ports if multi-enabled profile(MEP) is supported.
*
* Example: no. of logical slots 1 and physical slots 2 do not support MEP, each physical slot
* has one port:
* The only logical slot (index 0) can be mapped to first physical slot (value 0), port(index
* 0) or
* second physical slot(value 1), port (index 0), while the other physical slot remains unmapped
* and inactive.
* slotMapping[0] = UiccSlotMapping{0 //logical slot, 0 //physical slot//, 0 //port//}
* slotMapping[0] = UiccSlotMapping{1 // logical slot, 1 //physical slot//, 0 //port//}
*
* Example no. of logical slots 2 and physical slots 2 supports MEP with 2 ports available:
* Each logical slot must be mapped to a port (physical slot and port combination).
* First logical slot (index 0) can be mapped to physical slot 1 and the second logical slot
* can be mapped to either port from physical slot 2.
*
* slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 0, 0} or
* slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1}
*
* or the other way around, the second logical slot(index 1) can be mapped to physical slot 1
* and the first logical slot can be mapped to either port from physical slot 2.
*
* slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 0, 0} or
* slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 1, 1}
*
* another possible mapping is each logical slot maps to each port of physical slot 2 and there
* is no active logical modem mapped to physical slot 1.
*
* slotMapping[0] = UiccSlotMapping{1, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1} or
* slotMapping[0] = UiccSlotMapping{1, 1, 1} and slotMapping[1] = UiccSlotMapping{1, 0, 0}
*
* @param slotMapping Logical to physical slot and port mapping.
* @throws IllegalStateException if telephony service is null or slot mapping was sent when the
* radio in middle of a silent restart or other invalid states to handle the command
* @throws IllegalArgumentException if the caller passes in an invalid collection of
* UiccSlotMapping like duplicate data, etc
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setSimSlotMapping(@NonNull Collection<UiccSlotMapping> slotMapping) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
if (isSlotMappingValid(slotMapping)) {
boolean result = telephony.setSimSlotMapping(new ArrayList(slotMapping));
if (!result) {
throw new IllegalStateException("setSimSlotMapping has failed");
}
} else {
throw new IllegalArgumentException("Duplicate UiccSlotMapping data found");
}
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
/** /**
* Get the mapping from logical slots to physical slots. The key of the map is the logical slot * Get the mapping from logical slots to physical slots. The key of the map is the logical slot
* id and the value is the physical slots id mapped to this logical slot id. * id and the value is the physical slots id mapped to this logical slot id.
@@ -4051,7 +4162,7 @@ public class TelephonyManager {
try { try {
ITelephony telephony = getITelephony(); ITelephony telephony = getITelephony();
if (telephony != null) { if (telephony != null) {
int[] slotMappingArray = telephony.getSlotsMapping(); int[] slotMappingArray = telephony.getSlotsMapping(mContext.getOpPackageName());
for (int i = 0; i < slotMappingArray.length; i++) { for (int i = 0; i < slotMappingArray.length; i++) {
slotMapping.put(i, slotMappingArray[i]); slotMapping.put(i, slotMappingArray[i]);
} }

View File

@@ -20,21 +20,27 @@ import android.annotation.Nullable;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
* The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC. * The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC.
*/ */
public final class UiccCardInfo implements Parcelable { public final class UiccCardInfo implements Parcelable {
private final boolean mIsEuicc; private final boolean mIsEuicc;
private final int mCardId; private final int mCardId;
private final String mEid; private final String mEid;
private final String mIccId; private final String mIccId;
private final int mSlotIndex; private final int mPhysicalSlotIndex;
private final boolean mIsRemovable; private final boolean mIsRemovable;
private final boolean mIsMultipleEnabledProfilesSupported;
private final List<UiccPortInfo> mPortList;
private boolean mIccIdAccessRestricted = false;
public static final @android.annotation.NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() { public static final @NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
@Override @Override
public UiccCardInfo createFromParcel(Parcel in) { public UiccCardInfo createFromParcel(Parcel in) {
return new UiccCardInfo(in); return new UiccCardInfo(in);
@@ -47,22 +53,29 @@ public final class UiccCardInfo implements Parcelable {
}; };
private UiccCardInfo(Parcel in) { private UiccCardInfo(Parcel in) {
mIsEuicc = in.readByte() != 0; mIsEuicc = in.readBoolean();
mCardId = in.readInt(); mCardId = in.readInt();
mEid = in.readString(); mEid = in.readString8();
mIccId = in.readString(); mIccId = in.readString8();
mSlotIndex = in.readInt(); mPhysicalSlotIndex = in.readInt();
mIsRemovable = in.readByte() != 0; mIsRemovable = in.readBoolean();
mIsMultipleEnabledProfilesSupported = in.readBoolean();
mPortList = new ArrayList<UiccPortInfo>();
in.readTypedList(mPortList, UiccPortInfo.CREATOR);
mIccIdAccessRestricted = in.readBoolean();
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsEuicc ? 1 : 0)); dest.writeBoolean(mIsEuicc);
dest.writeInt(mCardId); dest.writeInt(mCardId);
dest.writeString(mEid); dest.writeString8(mEid);
dest.writeString(mIccId); dest.writeString8(mIccId);
dest.writeInt(mSlotIndex); dest.writeInt(mPhysicalSlotIndex);
dest.writeByte((byte) (mIsRemovable ? 1 : 0)); dest.writeBoolean(mIsRemovable);
dest.writeBoolean(mIsMultipleEnabledProfilesSupported);
dest.writeTypedList(mPortList, flags);
dest.writeBoolean(mIccIdAccessRestricted);
} }
@Override @Override
@@ -71,20 +84,34 @@ public final class UiccCardInfo implements Parcelable {
} }
/** /**
* Construct a UiccCardInfo.
*
* @param isEuicc is a flag to check is eUICC or not
* @param cardId is unique ID used to identify a UiccCard.
* @param eid is unique eUICC Identifier
* @param physicalSlotIndex is unique index referring to a physical SIM slot.
* @param isRemovable is a flag to check is removable or embedded
* @param isMultipleEnabledProfilesSupported is a flag to check is MEP enabled or not
* @param portList has the information regarding port, ICCID and its active status
*
* @hide * @hide
*/ */
public UiccCardInfo(boolean isEuicc, int cardId, String eid, String iccId, int slotIndex, public UiccCardInfo(boolean isEuicc, int cardId, String eid, int physicalSlotIndex,
boolean isRemovable) { boolean isRemovable, boolean isMultipleEnabledProfilesSupported,
@NonNull List<UiccPortInfo> portList) {
this.mIsEuicc = isEuicc; this.mIsEuicc = isEuicc;
this.mCardId = cardId; this.mCardId = cardId;
this.mEid = eid; this.mEid = eid;
this.mIccId = iccId; this.mIccId = null;
this.mSlotIndex = slotIndex; this.mPhysicalSlotIndex = physicalSlotIndex;
this.mIsRemovable = isRemovable; this.mIsRemovable = isRemovable;
this.mIsMultipleEnabledProfilesSupported = isMultipleEnabledProfilesSupported;
this.mPortList = portList;
} }
/** /**
* Return whether the UICC is an eUICC. * Return whether the UICC is an eUICC.
*
* @return true if the UICC is an eUICC. * @return true if the UICC is an eUICC.
*/ */
public boolean isEuicc() { public boolean isEuicc() {
@@ -119,40 +146,83 @@ public final class UiccCardInfo implements Parcelable {
* <p> * <p>
* Note that this field may be omitted if the caller does not have the correct permissions * Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}). * (see {@link TelephonyManager#getUiccCardsInfo()}).
*
* @deprecated with support for MEP(multiple enabled profile), a SIM card can have more than one
* ICCID active at the same time.Instead use {@link UiccPortInfo#getIccId()} to retrieve ICCID.
* To find {@link UiccPortInfo} use {@link UiccCardInfo#getPorts()}
*
* @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
*/ */
@Nullable @Nullable
@Deprecated
public String getIccId() { public String getIccId() {
return mIccId; if (mIccIdAccessRestricted) {
throw new UnsupportedOperationException("getIccId from UiccPortInfo");
}
//always return ICCID from first port.
return getPorts().stream().findFirst().get().getIccId();
} }
/** /**
* Gets the slot index for the slot that the UICC is currently inserted in. * Gets the slot index for the slot that the UICC is currently inserted in.
*
* @deprecated use {@link #getPhysicalSlotIndex()}
*/ */
@Deprecated
public int getSlotIndex() { public int getSlotIndex() {
return mSlotIndex; return mPhysicalSlotIndex;
} }
/** /**
* Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are * Gets the physical slot index for the slot that the UICC is currently inserted in.
* generally private and require carrier privileges to view.
*
* @hide
*/ */
@NonNull public int getPhysicalSlotIndex() {
public UiccCardInfo getUnprivileged() { return mPhysicalSlotIndex;
return new UiccCardInfo(mIsEuicc, mCardId, null, null, mSlotIndex, mIsRemovable);
} }
/** /**
* Return whether the UICC or eUICC is removable. * Return whether the UICC or eUICC is removable.
* <p> * <p>
* UICCs are generally removable, but eUICCs may be removable or built in to the device. * UICCs are generally removable, but eUICCs may be removable or built in to the device.
*
* @return true if the UICC or eUICC is removable * @return true if the UICC or eUICC is removable
*/ */
public boolean isRemovable() { public boolean isRemovable() {
return mIsRemovable; return mIsRemovable;
} }
/*
* Whether the UICC card supports multiple enable profile(MEP)
* UICCs are generally MEP disabled, there can be only one active profile on the physical
* sim card.
*
* @return {@code true} if the eUICC is supporting multiple enabled profile(MEP).
*/
public boolean isMultipleEnabledProfilesSupported() {
return mIsMultipleEnabledProfilesSupported;
}
/**
* Get information regarding port, ICCID and its active status.
*
* @return Collection of {@link UiccPortInfo}
*/
public @NonNull Collection<UiccPortInfo> getPorts() {
return Collections.unmodifiableList(mPortList);
}
/**
* if the flag is set to {@code true} the calling app is not allowed to access deprecated
* {@link #getIccId()}
* @param iccIdAccessRestricted is the flag to check if app is allowed to access ICCID
*
* @hide
*/
public void setIccIdAccessRestricted(boolean iccIdAccessRestricted) {
this.mIccIdAccessRestricted = iccIdAccessRestricted;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
@@ -167,13 +237,16 @@ public final class UiccCardInfo implements Parcelable {
&& (mCardId == that.mCardId) && (mCardId == that.mCardId)
&& (Objects.equals(mEid, that.mEid)) && (Objects.equals(mEid, that.mEid))
&& (Objects.equals(mIccId, that.mIccId)) && (Objects.equals(mIccId, that.mIccId))
&& (mSlotIndex == that.mSlotIndex) && (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
&& (mIsRemovable == that.mIsRemovable)); && (mIsRemovable == that.mIsRemovable)
&& (mIsMultipleEnabledProfilesSupported == that.mIsMultipleEnabledProfilesSupported)
&& (Objects.equals(mPortList, that.mPortList)));
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mSlotIndex, mIsRemovable); return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mPhysicalSlotIndex, mIsRemovable,
mIsMultipleEnabledProfilesSupported, mPortList);
} }
@Override @Override
@@ -185,11 +258,17 @@ public final class UiccCardInfo implements Parcelable {
+ ", mEid=" + ", mEid="
+ mEid + mEid
+ ", mIccId=" + ", mIccId="
+ mIccId + SubscriptionInfo.givePrintableIccid(mIccId)
+ ", mSlotIndex=" + ", mPhysicalSlotIndex="
+ mSlotIndex + mPhysicalSlotIndex
+ ", mIsRemovable=" + ", mIsRemovable="
+ mIsRemovable + mIsRemovable
+ ", mIsMultipleEnabledProfilesSupported="
+ mIsMultipleEnabledProfilesSupported
+ ", mPortList="
+ mPortList
+ ", mIccIdAccessRestricted="
+ mIccIdAccessRestricted
+ ")"; + ")";
} }
} }

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2018 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 android.telephony;
parcelable UiccPortInfo;

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2021 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 android.telephony;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* UiccPortInfo class represents information about a single port contained on {@link UiccCardInfo}.
* Per GSMA SGP.22 V3.0, a port is a logical entity to which an active UICC profile can be bound on
* a UICC card. If UICC supports 2 ports, then the port index is numbered 0,1.
* Each port index is unique within an UICC, but not necessarily unique across UICC’s.
* For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
*/
public final class UiccPortInfo implements Parcelable{
private final String mIccId;
private final int mPortIndex;
private final int mLogicalSlotIndex;
private final boolean mIsActive;
/**
* A redacted String if caller does not have permission to read ICCID.
*/
public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
public static final @NonNull Creator<UiccPortInfo> CREATOR =
new Creator<UiccPortInfo>() {
@Override
public UiccPortInfo createFromParcel(Parcel in) {
return new UiccPortInfo(in);
}
@Override
public UiccPortInfo[] newArray(int size) {
return new UiccPortInfo[size];
}
};
private UiccPortInfo(Parcel in) {
mIccId = in.readString8();
mPortIndex = in.readInt();
mLogicalSlotIndex = in.readInt();
mIsActive = in.readBoolean();
}
@Override
public void writeToParcel(@Nullable Parcel dest, int flags) {
dest.writeString8(mIccId);
dest.writeInt(mPortIndex);
dest.writeInt(mLogicalSlotIndex);
dest.writeBoolean(mIsActive);
}
@Override
public int describeContents() {
return 0;
}
/**
* Construct a UiccPortInfo.
*
* @param iccId The ICCID of the profile.
* @param portIndex The port index is an enumeration of the ports available on the UICC.
* @param logicalSlotIndex is unique index referring to a logical SIM slot.
* @param isActive is flag to check if port was tied to a modem stack.
*
* @hide
*/
public UiccPortInfo(String iccId, int portIndex, int logicalSlotIndex, boolean isActive) {
this.mIccId = iccId;
this.mPortIndex = portIndex;
this.mLogicalSlotIndex = logicalSlotIndex;
this.mIsActive = isActive;
}
/**
* Get the ICCID of the profile associated with this port.
* If this port is not {@link #isActive()}, returns {@code null}.
* If the caller does not have access to the ICCID for this port, it will be redacted and
* {@link #ICCID_REDACTED} will be returned.
*/
public @Nullable String getIccId() {
return mIccId;
}
/**
* The port index is an enumeration of the ports available on the UICC.
* Example: if eUICC1 supports 2 ports, then the port index is numbered 0,1.
* Each port index is unique within an UICC, but not necessarily unique across UICC’s.
* For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
*/
@IntRange(from = 0)
public int getPortIndex() {
return mPortIndex;
}
/**
* @return {@code true} if port was tied to a modem stack.
*/
public boolean isActive() {
return mIsActive;
}
/**
* Gets logical slot index for the slot that the UICC is currently attached.
* Logical slot index or ID: unique index referring to a logical SIM slot.
* Logical slot IDs start at 0 and go up depending on the number of supported active slots on
* a device.
* For example, a dual-SIM device typically has slot 0 and slot 1.
* If a device has multiple physical slots but only supports one active slot,
* it will have only the logical slot ID 0.
*
* @return the logical slot index for UICC port, if there is no logical slot index it returns
* {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX}
*/
@IntRange(from = 0)
public int getLogicalSlotIndex() {
return mLogicalSlotIndex;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
UiccPortInfo that = (UiccPortInfo) obj;
return (Objects.equals(mIccId, that.mIccId))
&& (mPortIndex == that.mPortIndex)
&& (mLogicalSlotIndex == that.mLogicalSlotIndex)
&& (mIsActive == that.mIsActive);
}
@Override
public int hashCode() {
return Objects.hash(mIccId, mPortIndex, mLogicalSlotIndex, mIsActive);
}
@NonNull
@Override
public String toString() {
return "UiccPortInfo (isActive="
+ mIsActive
+ ", iccId="
+ SubscriptionInfo.givePrintableIccid(mIccId)
+ ", portIndex="
+ mPortIndex
+ ", mLogicalSlotIndex="
+ mLogicalSlotIndex
+ ")";
}
}

View File

@@ -24,6 +24,10 @@ import android.os.Parcelable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
@@ -64,8 +68,10 @@ public class UiccSlotInfo implements Parcelable {
private final int mLogicalSlotIdx; private final int mLogicalSlotIdx;
private final boolean mIsExtendedApduSupported; private final boolean mIsExtendedApduSupported;
private final boolean mIsRemovable; private final boolean mIsRemovable;
private final List<UiccPortInfo> mPortList;
private boolean mLogicalSlotAccessRestricted = false;
public static final @android.annotation.NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() { public static final @NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
@Override @Override
public UiccSlotInfo createFromParcel(Parcel in) { public UiccSlotInfo createFromParcel(Parcel in) {
return new UiccSlotInfo(in); return new UiccSlotInfo(in);
@@ -78,24 +84,29 @@ public class UiccSlotInfo implements Parcelable {
}; };
private UiccSlotInfo(Parcel in) { private UiccSlotInfo(Parcel in) {
mIsActive = in.readByte() != 0; mIsActive = in.readBoolean();
mIsEuicc = in.readByte() != 0; mIsEuicc = in.readBoolean();
mCardId = in.readString(); mCardId = in.readString8();
mCardStateInfo = in.readInt(); mCardStateInfo = in.readInt();
mLogicalSlotIdx = in.readInt(); mLogicalSlotIdx = in.readInt();
mIsExtendedApduSupported = in.readByte() != 0; mIsExtendedApduSupported = in.readBoolean();
mIsRemovable = in.readByte() != 0; mIsRemovable = in.readBoolean();
mPortList = new ArrayList<UiccPortInfo>();
in.readTypedList(mPortList, UiccPortInfo.CREATOR);
mLogicalSlotAccessRestricted = in.readBoolean();
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsActive ? 1 : 0)); dest.writeBoolean(mIsActive);
dest.writeByte((byte) (mIsEuicc ? 1 : 0)); dest.writeBoolean(mIsEuicc);
dest.writeString(mCardId); dest.writeString8(mCardId);
dest.writeInt(mCardStateInfo); dest.writeInt(mCardStateInfo);
dest.writeInt(mLogicalSlotIdx); dest.writeInt(mLogicalSlotIdx);
dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0)); dest.writeBoolean(mIsExtendedApduSupported);
dest.writeByte((byte) (mIsRemovable ? 1 : 0)); dest.writeBoolean(mIsRemovable);
dest.writeTypedList(mPortList, flags);
dest.writeBoolean(mLogicalSlotAccessRestricted);
} }
@Override @Override
@@ -117,25 +128,42 @@ public class UiccSlotInfo implements Parcelable {
this.mLogicalSlotIdx = logicalSlotIdx; this.mLogicalSlotIdx = logicalSlotIdx;
this.mIsExtendedApduSupported = isExtendedApduSupported; this.mIsExtendedApduSupported = isExtendedApduSupported;
this.mIsRemovable = false; this.mIsRemovable = false;
this.mPortList = null;
} }
/** /**
* Construct a UiccSlotInfo.
* @hide * @hide
*/ */
public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId, public UiccSlotInfo(boolean isEuicc, String cardId,
@CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported, @CardStateInfo int cardStateInfo, boolean isExtendedApduSupported,
boolean isRemovable) { boolean isRemovable, @NonNull List<UiccPortInfo> portList) {
this.mIsActive = isActive; this.mIsActive = portList.get(0).isActive();
this.mIsEuicc = isEuicc; this.mIsEuicc = isEuicc;
this.mCardId = cardId; this.mCardId = cardId;
this.mCardStateInfo = cardStateInfo; this.mCardStateInfo = cardStateInfo;
this.mLogicalSlotIdx = logicalSlotIdx; this.mLogicalSlotIdx = portList.get(0).getLogicalSlotIndex();
this.mIsExtendedApduSupported = isExtendedApduSupported; this.mIsExtendedApduSupported = isExtendedApduSupported;
this.mIsRemovable = isRemovable; this.mIsRemovable = isRemovable;
this.mPortList = portList;
} }
/**
* @deprecated There is no longer isActive state for each slot because ports belonging
* to the physical slot could have different states
* we instead use {@link UiccPortInfo#isActive()}
* To get UiccPortInfo use {@link UiccSlotInfo#getPorts()}
*
* @return {@code true} if status is active.
* @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
*/
@Deprecated
public boolean getIsActive() { public boolean getIsActive() {
return mIsActive; if (mLogicalSlotAccessRestricted) {
throw new UnsupportedOperationException("get port status from UiccPortInfo");
}
//always return status from first port.
return getPorts().stream().findFirst().get().isActive();
} }
public boolean getIsEuicc() { public boolean getIsEuicc() {
@@ -159,8 +187,21 @@ public class UiccSlotInfo implements Parcelable {
return mCardStateInfo; return mCardStateInfo;
} }
/**
* @deprecated There is no longer getLogicalSlotIndex
* There is no longer getLogicalSlotIdx as each port belonging to this physical slot could have
* different logical slot index. Use {@link UiccPortInfo#getLogicalSlotIndex()} instead
*
* @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
*/
@Deprecated
public int getLogicalSlotIdx() { public int getLogicalSlotIdx() {
return mLogicalSlotIdx; if (mLogicalSlotAccessRestricted) {
throw new UnsupportedOperationException("get logical slot index from UiccPortInfo");
}
//always return logical slot index from first port.
//portList always have at least one element.
return getPorts().stream().findFirst().get().getLogicalSlotIndex();
} }
/** /**
@@ -170,16 +211,37 @@ public class UiccSlotInfo implements Parcelable {
return mIsExtendedApduSupported; return mIsExtendedApduSupported;
} }
/** /**
* Return whether the UICC slot is for a removable UICC. * Return whether the UICC slot is for a removable UICC.
* <p> * <p>
* UICCs are generally removable, but eUICCs may be removable or built in to the device. * UICCs are generally removable, but eUICCs may be removable or built in to the device.
*
* @return true if the slot is for removable UICCs * @return true if the slot is for removable UICCs
*/ */
public boolean isRemovable() { public boolean isRemovable() {
return mIsRemovable; return mIsRemovable;
} }
/**
* Get Information regarding port, iccid and its active status.
*
* @return Collection of {@link UiccPortInfo}
*/
public @NonNull Collection<UiccPortInfo> getPorts() {
return Collections.unmodifiableList(mPortList);
}
/**
* Set the flag to check compatibility of the calling app's target SDK is T and beyond.
*
* @param logicalSlotAccessRestricted is the flag to check compatibility.
*
* @hide
*/
public void setLogicalSlotAccessRestricted(boolean logicalSlotAccessRestricted) {
this.mLogicalSlotAccessRestricted = logicalSlotAccessRestricted;
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
if (this == obj) { if (this == obj) {
@@ -196,20 +258,14 @@ public class UiccSlotInfo implements Parcelable {
&& (mCardStateInfo == that.mCardStateInfo) && (mCardStateInfo == that.mCardStateInfo)
&& (mLogicalSlotIdx == that.mLogicalSlotIdx) && (mLogicalSlotIdx == that.mLogicalSlotIdx)
&& (mIsExtendedApduSupported == that.mIsExtendedApduSupported) && (mIsExtendedApduSupported == that.mIsExtendedApduSupported)
&& (mIsRemovable == that.mIsRemovable); && (mIsRemovable == that.mIsRemovable)
&& (Objects.equals(mPortList, that.mPortList));
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = 1; return Objects.hash(mIsActive, mIsEuicc, mCardId, mCardStateInfo, mLogicalSlotIdx,
result = 31 * result + (mIsActive ? 1 : 0); mIsExtendedApduSupported, mIsRemovable, mPortList);
result = 31 * result + (mIsEuicc ? 1 : 0);
result = 31 * result + Objects.hashCode(mCardId);
result = 31 * result + mCardStateInfo;
result = 31 * result + mLogicalSlotIdx;
result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
result = 31 * result + (mIsRemovable ? 1 : 0);
return result;
} }
@NonNull @NonNull
@@ -229,6 +285,10 @@ public class UiccSlotInfo implements Parcelable {
+ mIsExtendedApduSupported + mIsExtendedApduSupported
+ ", mIsRemovable=" + ", mIsRemovable="
+ mIsRemovable + mIsRemovable
+ ", mPortList="
+ mPortList
+ ", mLogicalSlotAccessRestricted="
+ mLogicalSlotAccessRestricted
+ ")"; + ")";
} }
} }

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2018 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 android.telephony;
parcelable UiccSlotMapping;

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2021 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 android.telephony;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* <p>Provides information for a SIM slot mapping, which establishes a unique mapping between a
* logical SIM slot and a physical SIM slot and port index. A logical SIM slot represents a
* potentially active SIM slot, where a physical SIM slot and port index represent a hardware SIM
* slot and port (capable of having an active profile) which can be mapped to a logical sim slot.
* <p>It contains the following parameters:
* <ul>
* <li>Port index: unique index referring to a port belonging to the physical SIM slot.
* If the SIM does not support multiple enabled profiles, the port index is default index 0.</li>
* <li>Physical slot index: unique index referring to a physical SIM slot. Physical slot IDs start
* at 0 and go up depending on the number of physical slots on the device.
* This differs from the number of logical slots a device has, which corresponds to the number of
* active slots a device is capable of using. For example, a device which switches between dual-SIM
* and single-SIM mode may always have two physical slots, but in single-SIM mode it will have only
* one logical slot.</li>
* <li>Logical slot index: unique index referring to a logical SIM slot, Logical slot IDs start at 0
* and go up depending on the number of supported active slots on a device.
* For example, a dual-SIM device typically has slot 0 and slot 1. If a device has multiple physical
* slots but only supports one active slot, it will have only the logical slot ID 0</li>
* </ul>
*
* <p> This configurations tells a specific logical slot is mapped to a port from an actual physical
* sim slot @see <a href="https://developer.android.com/guide/topics/connectivity/telecom/telephony-ids">the Android Developer Site</a>
* for more information.
* @hide
*/
@SystemApi
public final class UiccSlotMapping implements Parcelable {
private final int mPortIndex;
private final int mPhysicalSlotIndex;
private final int mLogicalSlotIndex;
public static final @NonNull Creator<UiccSlotMapping> CREATOR =
new Creator<UiccSlotMapping>() {
@Override
public UiccSlotMapping createFromParcel(Parcel in) {
return new UiccSlotMapping(in);
}
@Override
public UiccSlotMapping[] newArray(int size) {
return new UiccSlotMapping[size];
}
};
private UiccSlotMapping(Parcel in) {
mPortIndex = in.readInt();
mPhysicalSlotIndex = in.readInt();
mLogicalSlotIndex = in.readInt();
}
@Override
public void writeToParcel(@Nullable Parcel dest, int flags) {
dest.writeInt(mPortIndex);
dest.writeInt(mPhysicalSlotIndex);
dest.writeInt(mLogicalSlotIndex);
}
@Override
public int describeContents() {
return 0;
}
/**
*
* @param portIndex The port index is an enumeration of the ports available on the UICC.
* @param physicalSlotIndex is unique index referring to a physical SIM slot.
* @param logicalSlotIndex is unique index referring to a logical SIM slot.
*
* @hide
*/
public UiccSlotMapping(int portIndex, int physicalSlotIndex, int logicalSlotIndex) {
this.mPortIndex = portIndex;
this.mPhysicalSlotIndex = physicalSlotIndex;
this.mLogicalSlotIndex = logicalSlotIndex;
}
/**
* Port index is the unique index referring to a port belonging to the physical SIM slot.
* If the SIM does not support multiple enabled profiles, the port index is default index 0.
*
* @return port index.
*/
@IntRange(from = 0)
public int getPortIndex() {
return mPortIndex;
}
/**
* Gets the physical slot index for the slot that the UICC is currently inserted in.
*
* @return physical slot index which is the index of actual physical UICC slot.
*/
@IntRange(from = 0)
public int getPhysicalSlotIndex() {
return mPhysicalSlotIndex;
}
/**
* Gets logical slot index for the slot that the UICC is currently attached.
* Logical slot index is the unique index referring to a logical slot(logical modem stack).
*
* @return logical slot index;
*/
@IntRange(from = 0)
public int getLogicalSlotIndex() {
return mLogicalSlotIndex;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
UiccSlotMapping that = (UiccSlotMapping) obj;
return (mPortIndex == that.mPortIndex)
&& (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
&& (mLogicalSlotIndex == that.mLogicalSlotIndex);
}
@Override
public int hashCode() {
return Objects.hash(mPortIndex, mPhysicalSlotIndex, mLogicalSlotIndex);
}
@NonNull
@Override
public String toString() {
return "UiccSlotMapping (mPortIndex="
+ mPortIndex
+ ", mPhysicalSlotIndex="
+ mPhysicalSlotIndex
+ ", mLogicalSlotIndex="
+ mLogicalSlotIndex
+ ")";
}
}

View File

@@ -17,6 +17,7 @@ package android.telephony.euicc;
import android.annotation.CallbackExecutor; import android.annotation.CallbackExecutor;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.content.Context; import android.content.Context;
@@ -24,6 +25,7 @@ import android.os.Binder;
import android.os.RemoteException; import android.os.RemoteException;
import android.service.euicc.EuiccProfileInfo; import android.service.euicc.EuiccProfileInfo;
import android.telephony.TelephonyFrameworkInitializer; import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import com.android.internal.telephony.euicc.IAuthenticateServerCallback; import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
@@ -122,7 +124,6 @@ public class EuiccCardManager {
/** Result code indicating the caller is not the active LPA. */ /** Result code indicating the caller is not the active LPA. */
public static final int RESULT_CALLER_NOT_ALLOWED = -3; public static final int RESULT_CALLER_NOT_ALLOWED = -3;
/** /**
* Callback to receive the result of an eUICC card API. * Callback to receive the result of an eUICC card API.
* *
@@ -220,12 +221,48 @@ public class EuiccCardManager {
* @param refresh Whether sending the REFRESH command to modem. * @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked. * @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code. * @param callback The callback to get the result code.
*
* @deprecated instead use {@link #disableProfile(String, String, int, boolean, Executor,
* ResultCallback)}
*/ */
@Deprecated
public void disableProfile(String cardId, String iccid, boolean refresh, public void disableProfile(String cardId, String iccid, boolean refresh,
@CallbackExecutor Executor executor, ResultCallback<Void> callback) { @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
try { try {
getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid, getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
refresh, new IDisableProfileCallback.Stub() { TelephonyManager.DEFAULT_PORT_INDEX, refresh,
new IDisableProfileCallback.Stub() {
@Override
public void onComplete(int resultCode) {
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> callback.onComplete(resultCode, null));
} finally {
Binder.restoreCallingIdentity(token);
}
}
});
} catch (RemoteException e) {
Log.e(TAG, "Error calling disableProfile", e);
throw e.rethrowFromSystemServer();
}
}
/**
* Disables the profile of the given ICCID.
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile.
* @param portIndex the Port index is the unique index referring to a port.
* @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code.
*/
public void disableProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
boolean refresh, @NonNull @CallbackExecutor Executor executor,
@NonNull ResultCallback<Void> callback) {
try {
getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
portIndex, refresh, new IDisableProfileCallback.Stub() {
@Override @Override
public void onComplete(int resultCode) { public void onComplete(int resultCode) {
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
@@ -251,12 +288,51 @@ public class EuiccCardManager {
* @param refresh Whether sending the REFRESH command to modem. * @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked. * @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code and the EuiccProfileInfo enabled. * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
*
* @deprecated instead use {@link #switchToProfile(String, String, int, boolean, Executor,
* ResultCallback)}
*/ */
@Deprecated
public void switchToProfile(String cardId, String iccid, boolean refresh, public void switchToProfile(String cardId, String iccid, boolean refresh,
@CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) { @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
try { try {
getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid, getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
refresh, new ISwitchToProfileCallback.Stub() { TelephonyManager.DEFAULT_PORT_INDEX, refresh,
new ISwitchToProfileCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo profile) {
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> callback.onComplete(resultCode, profile));
} finally {
Binder.restoreCallingIdentity(token);
}
}
});
} catch (RemoteException e) {
Log.e(TAG, "Error calling switchToProfile", e);
throw e.rethrowFromSystemServer();
}
}
/**
* Switches from the current profile to another profile. The current profile will be disabled
* and the specified profile will be enabled. Here portIndex specifies on which port the
* profile is to be enabled.
*
* @param cardId The Id of the eUICC.
* @param iccid The iccid of the profile to switch to.
* @param portIndex The Port index is the unique index referring to a port.
* @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code and the EuiccProfileInfo enabled.
*/
public void switchToProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
boolean refresh, @NonNull @CallbackExecutor Executor executor,
@NonNull ResultCallback<EuiccProfileInfo> callback) {
try {
getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
portIndex, refresh, new ISwitchToProfileCallback.Stub() {
@Override @Override
public void onComplete(int resultCode, EuiccProfileInfo profile) { public void onComplete(int resultCode, EuiccProfileInfo profile) {
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();

View File

@@ -1418,4 +1418,22 @@ public class EuiccManager {
.getEuiccControllerService() .getEuiccControllerService()
.get()); .get());
} }
/**
* Returns whether the passing portIndex is available.
* A port is available if it has no profiles enabled on it or calling app has carrier privilege
* over the profile installed on the selected port.
* Always returns false if the cardId is a physical card.
*
* @param portIndex is an enumeration of the ports available on the UICC.
* @return {@code true} if port is available
*/
public boolean isSimPortAvailable(int portIndex) {
try {
return getIEuiccController().isSimPortAvailable(mCardId, portIndex,
mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
} }

View File

@@ -77,6 +77,7 @@ import java.util.Map;
import android.telephony.UiccCardInfo; import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo; import android.telephony.UiccSlotInfo;
import android.telephony.UiccSlotMapping;
/** /**
* Interface used to interact with the phone. Mostly this is used by the * Interface used to interact with the phone. Mostly this is used by the
@@ -1742,16 +1743,34 @@ interface ITelephony {
* @return UiccSlotInfo array. * @return UiccSlotInfo array.
* @hide * @hide
*/ */
UiccSlotInfo[] getUiccSlotsInfo(); UiccSlotInfo[] getUiccSlotsInfo(String callingPackage);
/** /**
* Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive. * Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive.
* @param physicalSlots Index i in the array representing physical slot for phone i. The array * @param physicalSlots Index i in the array representing physical slot for phone i. The array
* size should be same as getPhoneCount(). * size should be same as getPhoneCount().
* @deprecated Use {@link #setSimSlotMapping(in List<UiccSlotMapping> slotMapping)} instead.
* @return boolean Return true if the switch succeeds, false if the switch fails. * @return boolean Return true if the switch succeeds, false if the switch fails.
*/ */
boolean switchSlots(in int[] physicalSlots); boolean switchSlots(in int[] physicalSlots);
/**
* Maps the logical slots to the SlotPortMapping which consist of both physical slot index and
* port index. Logical slot is the slot that is seen by modem. Physical slot is the actual
* physical slot. Port index is the index (enumerated value) for the associated port available
* on the SIM. Each physical slot can have multiple ports which enables multi-enabled profile
* (MEP). If eUICC physical slot supports 2 ports, then the port index is numbered 0,1 and if
* eUICC2 supports 4 ports then the port index is numbered 0,1,2,3. Each portId is unique within
* a UICC physical slot but not necessarily unique across UICC’s. SEP(Single enabled profile)
* eUICC and non-eUICC will only have port Index 0.
*
* Logical slots that are already mapped to the requested SlotPortMapping are not impacted.
* @param slotMapping Index i in the list representing slot mapping for phone i.
*
* @return {@code true} if the switch succeeds, {@code false} if the switch fails.
*/
boolean setSimSlotMapping(in List<UiccSlotMapping> slotMapping);
/** /**
* Returns whether mobile data roaming is enabled on the subscription with id {@code subId}. * Returns whether mobile data roaming is enabled on the subscription with id {@code subId}.
* *
@@ -2130,7 +2149,7 @@ interface ITelephony {
/** /**
* Get the mapping from logical slots to physical slots. * Get the mapping from logical slots to physical slots.
*/ */
int[] getSlotsMapping(); int[] getSlotsMapping(String callingPackage);
/** /**
* Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown * Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown

View File

@@ -171,6 +171,8 @@ public class PhoneConstants {
public static final String SLOT_KEY = "slot"; public static final String SLOT_KEY = "slot";
public static final String PORT_KEY = "port";
// FIXME: This is used to pass a subId via intents, we need to look at its usage, which is // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
// FIXME: extensive, and see if this should be an array of all active subId's or ...? // FIXME: extensive, and see if this should be an array of all active subId's or ...?
/** /**

View File

@@ -45,10 +45,10 @@ interface IEuiccCardController {
in IGetAllProfilesCallback callback); in IGetAllProfilesCallback callback);
oneway void getProfile(String callingPackage, String cardId, String iccid, oneway void getProfile(String callingPackage, String cardId, String iccid,
in IGetProfileCallback callback); in IGetProfileCallback callback);
oneway void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh, oneway void disableProfile(String callingPackage, String cardId, String iccid, int portIndex,
in IDisableProfileCallback callback); boolean refresh, in IDisableProfileCallback callback);
oneway void switchToProfile(String callingPackage, String cardId, String iccid, boolean refresh, oneway void switchToProfile(String callingPackage, String cardId, String iccid, int portIndex,
in ISwitchToProfileCallback callback); boolean refresh, in ISwitchToProfileCallback callback);
oneway void setNickname(String callingPackage, String cardId, String iccid, String nickname, oneway void setNickname(String callingPackage, String cardId, String iccid, String nickname,
in ISetNicknameCallback callback); in ISetNicknameCallback callback);
oneway void deleteProfile(String callingPackage, String cardId, String iccid, oneway void deleteProfile(String callingPackage, String cardId, String iccid,

View File

@@ -51,4 +51,5 @@ interface IEuiccController {
void setSupportedCountries(boolean isSupported, in List<String> countriesList); void setSupportedCountries(boolean isSupported, in List<String> countriesList);
List<String> getSupportedCountries(boolean isSupported); List<String> getSupportedCountries(boolean isSupported);
boolean isSupportedCountry(String countryIso); boolean isSupportedCountry(String countryIso);
boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage);
} }

View File

@@ -23,6 +23,7 @@ import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.telephony.UiccPortInfo;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.GsmAlphabet;
@@ -44,8 +45,7 @@ public class IccUtils {
static final int FPLMN_BYTE_SIZE = 3; static final int FPLMN_BYTE_SIZE = 3;
// ICCID used for tests by some OEMs // ICCID used for tests by some OEMs
// TODO(b/159354974): Replace the constant here with UiccPortInfo.ICCID_REDACTED once ready public static final String TEST_ICCID = UiccPortInfo.ICCID_REDACTED;
private static final String TEST_ICCID = "FFFFFFFFFFFFFFFFFFFF";
// A table mapping from a number to a hex character for fast encoding hex strings. // A table mapping from a number to a hex character for fast encoding hex strings.
private static final char[] HEX_CHARS = { private static final char[] HEX_CHARS = {