diff options
| -rwxr-xr-x | api/current.txt | 9 | ||||
| -rw-r--r-- | telephony/java/android/telephony/SubscriptionInfo.java | 13 | ||||
| -rw-r--r-- | telephony/java/android/telephony/SubscriptionManager.java | 158 | ||||
| -rwxr-xr-x | telephony/java/com/android/internal/telephony/ISub.aidl | 11 |
4 files changed, 145 insertions, 46 deletions
diff --git a/api/current.txt b/api/current.txt index 6560459e5f4c..09a0ef176168 100755 --- a/api/current.txt +++ b/api/current.txt @@ -42976,7 +42976,7 @@ package android.telephony { method public String getCountryIso(); method public int getDataRoaming(); method public CharSequence getDisplayName(); - method @Nullable public String getGroupUuid(); + method @Nullable public android.os.ParcelUuid getGroupUuid(); method public String getIccId(); method public int getIconTint(); method @Deprecated public int getMcc(); @@ -42996,7 +42996,9 @@ package android.telephony { public class SubscriptionManager { method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); method public boolean canManageSubscription(android.telephony.SubscriptionInfo); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>); method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context); method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); @@ -43012,16 +43014,15 @@ package android.telephony { method public static int getSlotIndex(int); method @Nullable public int[] getSubscriptionIds(int); method @NonNull public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int); - method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getSubscriptionsInGroup(int); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getSubscriptionsInGroup(@NonNull android.os.ParcelUuid); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isActiveSubscriptionId(int); method public boolean isNetworkRoaming(int); method public static boolean isUsableSubscriptionId(int); method public static boolean isValidSubscriptionId(int); method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener); method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean removeSubscriptionsFromGroup(@NonNull int[]); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int); - method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String setSubscriptionGroup(@NonNull int[]); method public void setSubscriptionOverrideCongested(int, boolean, long); method public void setSubscriptionOverrideUnmetered(int, boolean, long); method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>); diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index a404ad8d3dae..d636918d87a2 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -32,6 +32,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.Build; import android.os.Parcel; +import android.os.ParcelUuid; import android.os.Parcelable; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -154,11 +155,11 @@ public class SubscriptionInfo implements Parcelable { private boolean mIsOpportunistic; /** - * A UUID assigned to the subscription group. It returns - * null if not assigned. + * A UUID assigned to the subscription group. It returns null if not assigned. + * Check {@link SubscriptionManager#createSubscriptionGroup(List)} for more details. */ @Nullable - private String mGroupUUID; + private ParcelUuid mGroupUUID; /** * Whether group of the subscription is disabled. @@ -237,7 +238,7 @@ public class SubscriptionInfo implements Parcelable { this.mCardString = cardString; this.mCardId = cardId; this.mIsOpportunistic = isOpportunistic; - this.mGroupUUID = groupUUID; + this.mGroupUUID = groupUUID == null ? null : ParcelUuid.fromString(groupUUID); this.mIsGroupDisabled = isGroupDisabled; this.mCarrierId = carrierId; this.mProfileClass = profileClass; @@ -461,7 +462,7 @@ public class SubscriptionInfo implements Parcelable { * @return group UUID a String of group UUID if it belongs to a group. Otherwise * it will return null. */ - public @Nullable String getGroupUuid() { + public @Nullable ParcelUuid getGroupUuid() { return mGroupUUID; } @@ -642,7 +643,7 @@ public class SubscriptionInfo implements Parcelable { dest.writeString(mCardString); dest.writeInt(mCardId); dest.writeBoolean(mIsOpportunistic); - dest.writeString(mGroupUUID); + dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString()); dest.writeBoolean(mIsGroupDisabled); dest.writeInt(mCarrierId); dest.writeInt(mProfileClass); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 92ac61972697..1f9f32df83c7 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -50,11 +50,12 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.ParcelUuid; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; -import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; @@ -1753,6 +1754,10 @@ public class SubscriptionManager { Rlog.d(LOG_TAG, msg); } + private static void loge(String msg) { + Rlog.e(LOG_TAG, msg); + } + /** * Returns the system's default subscription id. * @@ -2723,11 +2728,20 @@ public class SubscriptionManager { /** * Inform SubscriptionManager that subscriptions in the list are bundled - * as a group. Typically it's a primary subscription and an opportunistic - * subscription. It should only affect multi-SIM scenarios where primary - * and opportunistic subscriptions can be activated together. - * Being in the same group means they might be activated or deactivated - * together, some of them may be invisible to the users, etc. + * as a group. It can be multiple primary (non-opportunistic) subscriptions, + * or one or more primary plus one or more opportunistic subscriptions. + * + * This API will always create a new immutable group and assign group UUID to all the + * subscriptions, regardless whether they are in a group already or not. + * + * Grouped subscriptions will have below behaviors: + * 1) They will share the same user settings. + * 2) The opportunistic subscriptions in the group is considered invisible and will not + * return from {@link #getActiveSubscriptionInfoList()}, unless caller has carrier + * privilege permission of the subscriptions. + * 3) The opportunistic subscriptions in the group can't be active by itself. If all other + * non-opportunistic ones are deactivated (unplugged or disabled in Settings), + * the opportunistic ones will be deactivated automatically. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: @@ -2738,34 +2752,94 @@ public class SubscriptionManager { * outlined above. * * @param subIdList list of subId that will be in the same group - * @return groupUUID a UUID assigned to the subscription group. It returns - * null if fails. + * @return groupUUID a UUID assigned to the subscription group. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) - public @Nullable String setSubscriptionGroup(@NonNull int[] subIdList) { + public @NonNull ParcelUuid createSubscriptionGroup(@NonNull List<Integer> subIdList) { + Preconditions.checkNotNull(subIdList, "can't create group for null subId list"); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[setSubscriptionGroup]+ subIdList:" + Arrays.toString(subIdList)); + logd("[createSubscriptionGroup]"); } - String groupUUID = null; + ParcelUuid groupUuid = null; + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - groupUUID = iSub.setSubscriptionGroup(subIdList, pkgForDebug); + groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("createSubscriptionGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } - return groupUUID; + return groupUuid; + } + + /** + * Add a list of subscriptions into a group. + * See {@link #createSubscriptionGroup(List)} for more details. + * + * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * permission or had carrier privilege permission on the subscriptions: + * {@link TelephonyManager#hasCarrierPrivileges()} or + * {@link #canManageSubscription(SubscriptionInfo)} + * + * @throws SecurityException if the caller doesn't meet the requirements + * outlined above. + * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist, + * or the groupUuid doesn't exist. + * + * @param subIdList list of subId that need adding into the group + * @param groupUuid the groupUuid the subscriptions are being added to. + * + */ + @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void addSubscriptionsIntoGroup(@NonNull List<Integer> subIdList, + @NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(subIdList, "subIdList can't be null."); + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); + String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; + if (VDBG) { + logd("[addSubscriptionsIntoGroup]"); + } + + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); + + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } + } + } catch (RemoteException ex) { + loge("addSubscriptionsIntoGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } + } + } + + private boolean isSystemProcess() { + return Process.myUid() == Process.SYSTEM_UID; } /** * Remove a list of subscriptions from their subscription group. - * See {@link #setSubscriptionGroup(int[])} for more details. + * See {@link #createSubscriptionGroup(List)} for more details. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: @@ -2774,34 +2848,45 @@ public class SubscriptionManager { * * @throws SecurityException if the caller doesn't meet the requirements * outlined above. + * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong + * the specified group. * * @param subIdList list of subId that need removing from their groups. - * @return whether the operation succeeds. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) - public boolean removeSubscriptionsFromGroup(@NonNull int[] subIdList) { + public void removeSubscriptionsFromGroup(@NonNull List<Integer> subIdList, + @NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(subIdList, "subIdList can't be null."); + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[removeSubscriptionsFromGroup]+ subIdList:" + Arrays.toString(subIdList)); + logd("[removeSubscriptionsFromGroup]"); } + int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); + try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - return iSub.removeSubscriptionsFromGroup(subIdList, pkgForDebug); + iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("removeSubscriptionsFromGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } - - return false; } /** * Get subscriptionInfo list of subscriptions that are in the same group of given subId. - * See {@link #setSubscriptionGroup(int[])} for more details. + * See {@link #createSubscriptionGroup(List)} for more details. * * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} * permission or had carrier privilege permission on the subscription. @@ -2810,28 +2895,35 @@ public class SubscriptionManager { * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * - * @param subId of which list of subInfo from the same group will be returned. + * @param groupUuid of which list of subInfo will be returned. * @return list of subscriptionInfo that belong to the same group, including the given - * subscription itself. It will return null if the subscription doesn't exist or it - * doesn't belong to any group. + * subscription itself. It will return an empty list if no subscription belongs to the group. * */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(Manifest.permission.READ_PHONE_STATE) - public @Nullable List<SubscriptionInfo> getSubscriptionsInGroup(int subId) { + public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) { + Preconditions.checkNotNull(groupUuid, "groupUuid can't be null"); String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (VDBG) { - logd("[getSubscriptionsInGroup]+ subId:" + subId); + logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid); } List<SubscriptionInfo> result = null; try { ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); if (iSub != null) { - result = iSub.getSubscriptionsInGroup(subId, pkgForDebug); + result = iSub.getSubscriptionsInGroup(groupUuid, pkgForDebug); + } else { + if (!isSystemProcess()) { + throw new IllegalStateException("telephony service is null."); + } } } catch (RemoteException ex) { - // ignore it + loge("removeSubscriptionsFromGroup RemoteException " + ex); + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } } return result; @@ -2851,7 +2943,7 @@ public class SubscriptionManager { if (info == null) return false; // If subscription is NOT grouped opportunistic subscription, it's visible. - if (TextUtils.isEmpty(info.getGroupUuid()) || !info.isOpportunistic()) return true; + if (info.getGroupUuid() == null || !info.isOpportunistic()) return true; // If the caller is the carrier app and owns the subscription, it should be visible // to the caller. @@ -2881,14 +2973,14 @@ public class SubscriptionManager { // It should be the current active primary subscription if any, or any // primary subscription. List<SubscriptionInfo> selectableList = new ArrayList<>(); - Map<String, SubscriptionInfo> groupMap = new HashMap<>(); + Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>(); for (SubscriptionInfo info : availableList) { // Opportunistic subscriptions are considered invisible // to users so they should never be returned. if (!isSubscriptionVisible(info)) continue; - String groupUuid = info.getGroupUuid(); + ParcelUuid groupUuid = info.getGroupUuid(); if (groupUuid == null) { // Doesn't belong to any group. Add in the list. selectableList.add(info); diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index daea9d5c63d6..d7ac4525b6a4 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -17,6 +17,7 @@ package com.android.internal.telephony; import android.telephony.SubscriptionInfo; +import android.os.ParcelUuid; import com.android.internal.telephony.ISetOpportunisticDataCallback; interface ISub { @@ -202,7 +203,7 @@ interface ISub { * null if fails. * */ - String setSubscriptionGroup(in int[] subIdList, String callingPackage); + ParcelUuid createSubscriptionGroup(in int[] subIdList, String callingPackage); /** * Set which subscription is preferred for cellular data. It's @@ -234,9 +235,13 @@ interface ISub { */ List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage); - boolean removeSubscriptionsFromGroup(in int[] subIdList, String callingPackage); + void removeSubscriptionsFromGroup(in int[] subIdList, in ParcelUuid groupUuid, + String callingPackage); - List<SubscriptionInfo> getSubscriptionsInGroup(int subId, String callingPackage); + void addSubscriptionsIntoGroup(in int[] subIdList, in ParcelUuid groupUuid, + String callingPackage); + + List<SubscriptionInfo> getSubscriptionsInGroup(in ParcelUuid groupUuid, String callingPackage); int getSlotIndex(int subId); |