diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index d4a8600b029ac..86623599d9848 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -859,7 +860,7 @@ public final class TelephonyPermissions {
if ((subManager != null) &&
(!subManager.isSubscriptionAssociatedWithUser(subId, callerUserHandle))) {
// If subId is not associated with calling user, return false.
- Log.e(LOG_TAG,"User[User ID:" + callerUserHandle.getIdentifier()
+ Log.e(LOG_TAG, "User[User ID:" + callerUserHandle.getIdentifier()
+ "] is not associated with Subscription ID:" + subId);
return false;
@@ -869,4 +870,27 @@ public final class TelephonyPermissions {
}
return true;
}
+
+ /**
+ * Ensure the caller (or self, if not processing an IPC) has
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS}.
+ *
+ * @throws SecurityException if the caller does not have the required permission/privileges
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PHONE_NUMBERS,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
+ })
+ public static boolean checkCallingOrSelfReadPrivilegedPhoneStatePermissionOrReadPhoneNumber(
+ Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
+ String message) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ return false;
+ }
+ return (context.checkCallingOrSelfPermission(
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PERMISSION_GRANTED
+ || checkCallingOrSelfReadPhoneNumber(context, subId, callingPackage,
+ callingFeatureId, message));
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 83b909852d8f3..4688f8328e9ce 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6050,6 +6050,7 @@ public class TelephonyManager {
* @return an array of IMPU strings, with one IMPU per string, or null if
* not present or not loaded
* @hide
+ * @deprecated use {@link #getImsPublicUserIdentities()}
*/
@UnsupportedAppUsage
@Nullable
@@ -6069,6 +6070,39 @@ public class TelephonyManager {
}
}
+ /**
+ * Returns the IMS public user identities (IMPU) of the subscription that was loaded from the
+ * ISIM records {@link #APPTYPE_ISIM}. This value is fetched from the Elementary file EF_IMPU.
+ * The contents of the file are Ip Multimedia Service Public User Identities of the user
+ * as defined in the section 4.2.4 of 3GPP TS 131 103. It contains one or more records.
+ *
+ * @return List of public user identities of type android.net.Uri or empty list if
+ * EF_IMPU is not available.
+ * @throws IllegalStateException in case the ISIM hasn’t been loaded
+ * @throws SecurityException if the caller does not have the required permission/privilege
+ * @hide
+ */
+ @NonNull
+ @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_NUMBERS,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+ public List getImsPublicUserIdentities() {
+ try {
+ IPhoneSubInfo info = getSubscriberInfoService();
+ if (info == null) {
+ throw new RuntimeException("IMPU error: Subscriber Info is null");
+ }
+ return info.getImsPublicUserIdentities(getSubId(), getOpPackageName(),
+ getAttributionTag());
+ } catch (IllegalArgumentException | NullPointerException ex) {
+ Rlog.e(TAG, "getImsPublicUserIdentities Exception = " + ex);
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getImsPublicUserIdentities Exception = " + ex);
+ ex.rethrowAsRuntimeException();
+ }
+ return Collections.EMPTY_LIST;
+ }
+
/**
* Device call state: No activity.
*/
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 3dfc81eafb77c..9782949fcd4eb 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -192,6 +192,14 @@ interface IPhoneSubInfo {
*/
String[] getIsimImpu(int subId);
+ /**
+ * Fetches the ISIM public user identities (EF_IMPU) from UICC based on subId
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" +
+ "anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})")
+ List getImsPublicUserIdentities(int subId, String callingPackage,
+ String callingFeatureId);
+
/**
* Returns the IMS Service Table (IST) that was loaded from the ISIM.
* @return IMS Service Table or null if not present or not loaded