diff options
| -rw-r--r-- | core/api/current.txt | 6 | ||||
| -rw-r--r-- | telephony/java/android/telephony/SubscriptionManager.java | 174 | ||||
| -rwxr-xr-x | telephony/java/com/android/internal/telephony/ISub.aidl | 9 |
3 files changed, 189 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index b42d6aaf9386..230689dda0c9 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -42613,6 +42613,8 @@ package android.telephony { method @NonNull public java.util.List<android.net.Uri> getDeviceToDeviceStatusSharingContacts(int); method public int getDeviceToDeviceStatusSharingPreference(int); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int, int); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int); method public static int getSlotIndex(int); method @Nullable public int[] getSubscriptionIds(int); method @NonNull public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int); @@ -42624,6 +42626,7 @@ package android.telephony { 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 void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); + method public void setCarrierPhoneNumber(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingContacts(int, @NonNull java.util.List<android.net.Uri>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingPreference(int, int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int); @@ -42650,6 +42653,9 @@ package android.telephony { field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; field public static final int INVALID_SIM_SLOT_INDEX = -1; // 0xffffffff field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff + field public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; // 0x2 + field public static final int PHONE_NUMBER_SOURCE_IMS = 3; // 0x3 + field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1 field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0 field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1 } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index d5315acf60d5..1fab89e51416 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1128,6 +1128,52 @@ public class SubscriptionManager { */ public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; + /** + * A source of phone number: the EF-MSISDN (see 3GPP TS 31.102), + * or EF-MDN for CDMA (see 3GPP2 C.P0065-B), from UICC application. + * + * <p>The availability and a of the number depends on the carrier. + * The number may be updated by over-the-air update to UICC applications + * from the carrier, or by other means with physical access to the SIM. + */ + public static final int PHONE_NUMBER_SOURCE_UICC = 1; + + /** + * A source of phone number: provided by an app that has carrier privilege. + * + * <p>The number is intended to be set by a carrier app knowing the correct number + * which is, for example, different from the number in {@link #PHONE_NUMBER_SOURCE_UICC UICC} + * for some reason. + * The number is not available until a carrier app sets one via + * {@link #setCarrierPhoneNumber(int, String)}. + * The app can update the number with the same API should the number change. + */ + public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; + + /** + * A source of phone number: provided by IMS (IP Multimedia Subsystem) implementation. + * When IMS service is registered (as indicated by + * {@link android.telephony.ims.RegistrationManager.RegistrationCallback#onRegistered(int)}) + * the IMS implementation may return P-Associated-Uri SIP headers (RFC 3455). The URIs + * are the user’s public user identities known to the network (see 3GPP TS 24.229 5.4.1.2), + * and the phone number is typically one of them (see “global number” in 3GPP TS 23.003 13.4). + * + * <p>This source provides the phone number from the last IMS registration. + * IMS registration may happen on every device reboot or other network condition changes. + * The number will be updated should the associated URI change after an IMS registration. + */ + public static final int PHONE_NUMBER_SOURCE_IMS = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"PHONE_NUMBER_SOURCE"}, + value = { + PHONE_NUMBER_SOURCE_UICC, + PHONE_NUMBER_SOURCE_CARRIER, + PHONE_NUMBER_SOURCE_IMS, + }) + public @interface PhoneNumberSource {} + private final Context mContext; // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing @@ -3763,4 +3809,132 @@ public class SubscriptionManager { RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, bundle); } + + /** + * Returns the phone number for the given {@code subId} and {@code source}, + * or an empty string if not available. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or + * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device), + * or that the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID} + * for the default one. + * @param source the source of the phone number, one of the PHONE_NUMBER_SOURCE_* constants. + * @return the phone number, or an empty string if not available. + * @throws IllegalArgumentException if {@code source} is invalid. + * @throws IllegalStateException if the telephony process is not currently available. + * @throws SecurityException if the caller doesn't have permissions required. + * @see #PHONE_NUMBER_SOURCE_UICC + * @see #PHONE_NUMBER_SOURCE_CARRIER + * @see #PHONE_NUMBER_SOURCE_IMS + */ + @SuppressAutoDoc // No support for carrier privileges (b/72967236) + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PHONE_NUMBERS, + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + }) + @NonNull + public String getPhoneNumber(int subscriptionId, @PhoneNumberSource int source) { + if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) { + subscriptionId = getDefaultSubscriptionId(); + } + if (source != PHONE_NUMBER_SOURCE_UICC + && source != PHONE_NUMBER_SOURCE_CARRIER + && source != PHONE_NUMBER_SOURCE_IMS) { + throw new IllegalArgumentException("invalid source " + source); + } + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + return iSub.getPhoneNumber(subscriptionId, source, + mContext.getOpPackageName(), mContext.getAttributionTag()); + } else { + throw new IllegalStateException("subscription service unavailable."); + } + } catch (RemoteException ex) { + throw ex.rethrowAsRuntimeException(); + } + } + + /** + * Returns the phone number for the given {@code subId}, or an empty string if + * not available. + * + * <p>This API is built up on {@link #getPhoneNumber(int, int)}, but picks + * from available sources in the following order: {@link #PHONE_NUMBER_SOURCE_CARRIER} + * > {@link #PHONE_NUMBER_SOURCE_UICC} > {@link #PHONE_NUMBER_SOURCE_IMS}. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or + * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device), + * or that the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID} + * for the default one. + * @return the phone number, or an empty string if not available. + * @throws IllegalStateException if the telephony process is not currently available. + * @throws SecurityException if the caller doesn't have permissions required. + * @see #getPhoneNumber(int, int) + */ + @SuppressAutoDoc // No support for carrier privileges (b/72967236) + @RequiresPermission(anyOf = { + android.Manifest.permission.READ_PHONE_NUMBERS, + android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + }) + @NonNull + public String getPhoneNumber(int subscriptionId) { + if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) { + subscriptionId = getDefaultSubscriptionId(); + } + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + return iSub.getPhoneNumberFromFirstAvailableSource(subscriptionId, + mContext.getOpPackageName(), mContext.getAttributionTag()); + } else { + throw new IllegalStateException("subscription service unavailable."); + } + } catch (RemoteException ex) { + throw ex.rethrowAsRuntimeException(); + } + } + + /** + * Sets the phone number for the given {@code subId} for source + * {@link #PHONE_NUMBER_SOURCE_CARRIER carrier}. + * Sets an empty string to remove the previously set phone number. + * + * <p>Requires Permission: the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). + * + * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID} + * for the default one. + * @param number the phone number, or an empty string to remove the previously set number. + * @throws IllegalStateException if the telephony process is not currently available. + * @throws NullPointerException if {@code number} is {@code null}. + * @throws SecurityException if the caller doesn't have permissions required. + */ + public void setCarrierPhoneNumber(int subscriptionId, @NonNull String number) { + if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) { + subscriptionId = getDefaultSubscriptionId(); + } + if (number == null) { + throw new NullPointerException("invalid number null"); + } + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + iSub.setPhoneNumber(subscriptionId, PHONE_NUMBER_SOURCE_CARRIER, number, + mContext.getOpPackageName(), mContext.getAttributionTag()); + } else { + throw new IllegalStateException("subscription service unavailable."); + } + } catch (RemoteException ex) { + throw ex.rethrowAsRuntimeException(); + } + } } diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 6493772039e6..a900c84c1819 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -304,4 +304,13 @@ interface ISub { int setDeviceToDeviceStatusSharing(int sharing, int subId); int setDeviceToDeviceStatusSharingContacts(String contacts, int subscriptionId); + + String getPhoneNumber(int subId, int source, + String callingPackage, String callingFeatureId); + + String getPhoneNumberFromFirstAvailableSource(int subId, + String callingPackage, String callingFeatureId); + + void setPhoneNumber(int subId, int source, String number, + String callingPackage, String callingFeatureId); } |