Add APIs in SubscriptionManager for opportunistic subscriptions
Bug: 92796390
Test: unittest
Change-Id: Id6d9454872e4d12a395cc568f7e2361c5b8c9a33
Merged-In: Id6d9454872e4d12a395cc568f7e2361c5b8c9a33
diff --git a/api/current.txt b/api/current.txt
index 4ec2265..f7ec2fb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -42408,9 +42408,11 @@
method public deprecated int getMnc();
method public java.lang.String getMncString();
method public java.lang.String getNumber();
+ method public int getParentSubId();
method public int getSimSlotIndex();
method public int getSubscriptionId();
method public boolean isEmbedded();
+ method public boolean isOpportunistic();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR;
}
@@ -42435,6 +42437,7 @@
method public void setSubscriptionOverrideCongested(int, boolean, long);
method public void setSubscriptionOverrideUnmetered(int, boolean, long);
method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
+ method public void switchToSubscription(int, android.app.PendingIntent);
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 667ad91..2bc43d4 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -135,12 +135,35 @@
private String mCardId;
/**
+ * Whether the subscription is opportunistic.
+ */
+ private boolean mIsOpportunistic;
+
+ /**
+ * SubId of the parent subscription, if there is one.
+ */
+ private int mParentSubId;
+
+ /**
* @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[] accessRules, String cardId) {
+ this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
+ false, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ /**
+ * @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[] accessRules, String cardId, boolean isOpportunistic,
+ int parentSubId) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -157,6 +180,8 @@
this.mIsEmbedded = isEmbedded;
this.mAccessRules = accessRules;
this.mCardId = cardId;
+ this.mIsOpportunistic = isOpportunistic;
+ this.mParentSubId = parentSubId;
}
/**
@@ -347,6 +372,29 @@
}
/**
+ * An opportunistic subscription connects to a network that is
+ * limited in functionality and / or coverage.
+ *
+ * @return whether subscription is opportunistic.
+ */
+ public boolean isOpportunistic() {
+ return mIsOpportunistic;
+ }
+
+ /**
+ * Used in scenarios where a child subscription is bundled with a primary parent subscription.
+ * The child subscription will typically be opportunistic (see {@link #isOpportunistic()})
+ * and will be used to provide data services where available, with the parent being the primary
+ * fallback subscription.
+ *
+ * @return subId of parent subscription if it’s bundled with a primary subscription.
+ * If there isn't one, {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+ */
+ public int getParentSubId() {
+ return mParentSubId;
+ }
+
+ /**
* Checks whether the app with the given context is authorized to manage this subscription
* according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded}
* returns true).
@@ -438,10 +486,12 @@
boolean isEmbedded = source.readBoolean();
UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardId = source.readString();
+ boolean isOpportunistic = source.readBoolean();
+ int parentSubId = source.readInt();
return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
- isEmbedded, accessRules, cardId);
+ isEmbedded, accessRules, cardId, isOpportunistic, parentSubId);
}
@Override
@@ -468,6 +518,8 @@
dest.writeBoolean(mIsEmbedded);
dest.writeTypedArray(mAccessRules, flags);
dest.writeString(mCardId);
+ dest.writeBoolean(mIsOpportunistic);
+ dest.writeInt(mParentSubId);
}
@Override
@@ -500,6 +552,7 @@
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
+ " mnc " + mMnc + " isEmbedded " + mIsEmbedded
+ " accessRules " + Arrays.toString(mAccessRules)
- + " cardId=" + cardIdToPrint + "}";
+ + " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
+ + " parentSubId=" + mParentSubId + "}";
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8aa5bf6..151b936 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -29,6 +29,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.BroadcastOptions;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -43,6 +44,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.telephony.euicc.EuiccManager;
import android.util.DisplayMetrics;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -433,6 +435,24 @@
public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
/**
+ * TelephonyProvider column name for whether a subscription is opportunistic, that is,
+ * whether the network it connects to is limited in functionality or coverage.
+ * For example, CBRS.
+ * IS_EMBEDDED should always be true.
+ * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic.
+ * @hide
+ */
+ public static final String IS_OPPORTUNISTIC = "is_opportunistic";
+
+ /**
+ * TelephonyProvider column name for subId of parent subscription of an opportunistic
+ * subscription.
+ * if the parent sub id is valid, then is_opportunistic should always to true.
+ * @hide
+ */
+ public static final String PARENT_SUB_ID = "parent_sub_id";
+
+ /**
* Broadcast Action: The user has changed one of the default subs related to
* data, phone calls, or sms</p>
*
@@ -1940,6 +1960,91 @@
return false;
}
+ /**
+ * Set preferred default data.
+ * Set on which slot default data will be on.
+ *
+ * @param slotId which slot is preferred to for cellular data.
+ * @hide
+ *
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setPreferredData(int slotId) {
+ if (VDBG) logd("[setPreferredData]+ slotId:" + slotId);
+ setSubscriptionPropertyHelper(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ "setPreferredData", (iSub)-> iSub.setPreferredData(slotId));
+ }
+
+ /**
+ * Get User downloaded Profiles.
+ *
+ * Provide all available user downloaded profile on the phone.
+ * @param slotId on which phone the switch will operate on
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId) {
+ String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ List<SubscriptionInfo> subInfoList = null;
+
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ if (iSub != null) {
+ subInfoList = iSub.getOpportunisticSubscriptions(slotId, pkgForDebug);
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ if (subInfoList == null) {
+ subInfoList = new ArrayList<>();
+ }
+
+ return subInfoList;
+ }
+
+ /**
+ * Switch to a certain subscription
+ *
+ * @param subId sub id
+ * @param callbackIntent pending intent that will be sent after operation is done.
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+ public void switchToSubscription(int subId, PendingIntent callbackIntent) {
+ EuiccManager euiccManager = new EuiccManager(mContext);
+ euiccManager.switchToSubscription(subId, callbackIntent);
+ }
+
+ /**
+ * Set opportunistic by simInfo index
+ *
+ * @param opportunistic whether it’s opportunistic subscription.
+ * @param subId the unique SubscriptionInfo index in database
+ * @return the number of records updated
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public int setOpportunistic(boolean opportunistic, int subId) {
+ if (VDBG) logd("[setOpportunistic]+ opportunistic:" + opportunistic + " subId:" + subId);
+ return setSubscriptionPropertyHelper(subId, "setOpportunistic",
+ (iSub)-> iSub.setOpportunistic(opportunistic, subId));
+ }
+
+ /**
+ * Set parent subId by simInfo index
+ *
+ * @param parentSubId subId of its parent subscription.
+ * @param subId the unique SubscriptionInfo index in database
+ * @return the number of records updated
+ * @hide
+ *
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public int setParentSubId(int parentSubId, int subId) {
+ if (VDBG) logd("[setParentSubId]+ parentSubId:" + parentSubId + " subId:" + subId);
+ return setSubscriptionPropertyHelper(subId, "parentSubId",
+ (iSub)-> iSub.setParentSubId(parentSubId, subId));
+ }
+
private interface CallISubMethodHelper {
int callMethod(ISub iSub) throws RemoteException;
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 5e015e0..6521f0b 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -156,6 +156,42 @@
*/
int setDataRoaming(int roaming, int subId);
+ /**
+ * Switch to a certain subscription
+ *
+ * @param opportunistic whether it’s opportunistic subscription.
+ * @param subId the unique SubscriptionInfo index in database
+ * @return the number of records updated
+ */
+ int setOpportunistic(boolean opportunistic, int subId);
+
+ /**
+ * Set parent subId by simInfo index
+ *
+ * @param parentSubId: subId of its parent subscription.
+ * @param subId the unique SubscriptionInfo index in database
+ * @return the number of records updated
+ */
+ int setParentSubId(int parentSubId, int subId);
+
+ /**
+ * Set preferred default data.
+ * Set on which slot default data will be on.
+ *
+ * @param slotId which slot is preferred to for cellular data.
+ * @hide
+ *
+ */
+ int setPreferredData(int slotId);
+
+ /**
+ * Get User downloaded Profiles.
+ *
+ * Provide all available user downloaded profile on the phone.
+ * @param slotId on which phone the switch will operate on
+ */
+ List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId, String callingPackage);
+
int getSlotIndex(int subId);
int[] getSubId(int slotIndex);
@@ -186,7 +222,7 @@
int[] getActiveSubIdList();
- void setSubscriptionProperty(int subId, String propKey, String propValue);
+ int setSubscriptionProperty(int subId, String propKey, String propValue);
String getSubscriptionProperty(int subId, String propKey, String callingPackage);
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 51369d0..5ecb43e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -15,7 +15,6 @@
*/
package com.android.internal.telephony;
-import android.content.Intent;
import android.content.Intent;
import android.telephony.SubscriptionManager;