From 27070e9705d0f0dae9ad888b2ec17074cbeb5b98 Mon Sep 17 00:00:00 2001 From: Junho Date: Tue, 10 Sep 2024 04:58:15 +0000 Subject: Add interface to get the value loaded from ISIM record This CL modifies the interfaces to allow the IMS service to get the value loaded from the ISIM record. 1. Allow access to the interface to privileged apps by adding @SystemApi annotation. 2. Add interface to get P-CSCF from the ISIM record instead of getIsimPcscf. 3. Add interface to get SIM Service Table that return byte array type. Bug: 365488868 Test: atest TelephonyManagerTest Flag: com.android.internal.telephony.flags.support_isim_record Change-Id: I6db5ffa73337bc1448726db72ca30e85bf6d07d8 --- core/api/system-current.txt | 4 + .../internal/telephony/TelephonyPermissions.java | 23 ----- .../java/android/telephony/TelephonyManager.java | 111 +++++++++++++++++++-- .../android/internal/telephony/IPhoneSubInfo.aidl | 21 +++- 4 files changed, 124 insertions(+), 35 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 48fcdb478846..b42ad0033ffc 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -15702,6 +15702,9 @@ package android.telephony { method @FlaggedApi("android.permission.flags.get_emergency_role_holder_api_enabled") @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getEmergencyAssistancePackageName(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion(); + method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @NonNull @RequiresPermission(value=android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional=true) public java.util.List getImsPcscfAddresses(); + method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @Nullable @RequiresPermission(android.Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER) public String getImsPrivateUserIdentity(); + method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @NonNull @RequiresPermission(value=android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional=true) public java.util.List getImsPublicUserIdentities(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst(); method @FlaggedApi("com.android.server.telecom.flags.get_last_known_cell_identity") @Nullable @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_LAST_KNOWN_CELL_ID}) public android.telephony.CellIdentity getLastKnownCellIdentity(); @@ -15720,6 +15723,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale(); + method @FlaggedApi("com.android.internal.telephony.flags.support_isim_record") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getSimServiceTable(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Collection getSimSlotMapping(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List getSystemSelectionChannels(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List getTelephonyHistograms(); diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 4ccbc32c4b54..66d75f780fbe 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -906,29 +906,6 @@ 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)); - } - /** * @return true if the specified {@code uid} is for a system or phone process, no matter if runs * as system user or not. diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fad59f8bb37b..6f2c8623fd71 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -133,6 +133,7 @@ import com.android.internal.telephony.OperatorInfo; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.flags.Flags; +import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.telephony.util.TelephonyUtils; import com.android.telephony.Rlog; @@ -6282,14 +6283,17 @@ public class TelephonyManager { * The contents of the file is a Ip Multimedia Service Private User Identity of the user * as defined in the section 4.2.2 of 3GPP TS 131 103. * - * @return IMPI (IMS private user identity) of type string. + * @return IMPI (IMS private user identity) of type string or null if the IMPI isn't present + * on the ISIM. * @throws IllegalStateException in case the ISIM has’t been loaded * @throws SecurityException if the caller does not have the required permission/privileges * @hide */ - @NonNull + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) + @SystemApi @RequiresPermission(android.Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @Nullable public String getImsPrivateUserIdentity() { try { IPhoneSubInfo info = getSubscriberInfoService(); @@ -6370,6 +6374,9 @@ public class TelephonyManager { * 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. * + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission or carrier + * privileges. + * * @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 @@ -6378,18 +6385,18 @@ public class TelephonyManager { * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. * @hide */ - @NonNull - @RequiresPermission(anyOf = {android.Manifest.permission.READ_PHONE_NUMBERS, - android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}) + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) + @SystemApi + @RequiresPermission(value = Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional = true) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @NonNull 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()); + return info.getImsPublicUserIdentities(getSubId(), getOpPackageName()); } catch (IllegalArgumentException | NullPointerException ex) { Rlog.e(TAG, "getImsPublicUserIdentities Exception = " + ex); } catch (RemoteException ex) { @@ -8684,7 +8691,10 @@ public class TelephonyManager { * @return an array of PCSCF strings with one PCSCF per string, or null if * not present or not loaded * @hide + * @deprecated use {@link #getImsPcscfAddresses()} instead. */ + @Deprecated + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) @UnsupportedAppUsage public String[] getIsimPcscf() { try { @@ -8701,6 +8711,40 @@ public class TelephonyManager { } } + /** + * Returns the IMS Proxy Call Session Control Function(P-CSCF) that were loaded from the ISIM. + * + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission or carrier + * privileges. + * + * @return List of P-CSCF address strings or empty list if not available. + * @throws IllegalStateException in case the ISIM hasn’t been loaded + * @throws SecurityException if the caller does not have the required permission/privilege + * @throws UnsupportedOperationException If the device does not have + * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) + @SystemApi + @RequiresPermission(value = Manifest.permission.READ_PRIVILEGED_PHONE_STATE, conditional = true) + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + @NonNull + public List getImsPcscfAddresses() { + try { + IPhoneSubInfo info = getSubscriberInfoService(); + if (info == null) { + throw new RuntimeException("P-CSCF error: Subscriber Info is null"); + } + return info.getImsPcscfAddresses(getSubId(), getOpPackageName()); + } catch (IllegalArgumentException | NullPointerException ex) { + Rlog.e(TAG, "getImsPcscfAddresses Exception = " + ex); + } catch (RemoteException ex) { + Rlog.e(TAG, "getImsPcscfAddresses Exception = " + ex); + ex.rethrowAsRuntimeException(); + } + return Collections.EMPTY_LIST; + } + /** UICC application type is unknown or not specified */ public static final int APPTYPE_UNKNOWN = PhoneConstants.APPTYPE_UNKNOWN; /** UICC application type is SIM */ @@ -8934,8 +8978,10 @@ public class TelephonyManager { * @throws UnsupportedOperationException If the device does not have * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. * @hide + * @deprecated Use {@link #getSimServiceTable(int, Executor, OutcomeReceiver)} instead. */ - + @Deprecated + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) @@ -8962,6 +9008,55 @@ public class TelephonyManager { return null; } + /** + * Fetches the sim service table from the EFUST/EFIST based on the application type + * {@link #APPTYPE_USIM} or {@link #APPTYPE_ISIM}. + * The USIM service table EF is described in as per Section 4.2.8 of 3GPP TS 31.102. + * The ISIM service table EF is described in as per Section 4.2.7 of 3GPP TS 31.103. + * + * @param appType of type int of either {@link #APPTYPE_USIM} or {@link #APPTYPE_ISIM}. + * @param executor executor to run the callback on. + * @param callback callback object to which the result will be delivered. + * @hide + */ + @FlaggedApi(Flags.FLAG_SUPPORT_ISIM_RECORD) + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION) + public void getSimServiceTable(@UiccAppType int appType, + @NonNull @CallbackExecutor Executor executor, + @NonNull OutcomeReceiver callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + IPhoneSubInfo info = getSubscriberInfoService(); + if (info == null) { + executor.execute(() -> callback.onError( + new RuntimeException("getSimServiceTable: Subscriber Info is null"))); + return; + } + + try { + String serviceTable; + if (appType == APPTYPE_ISIM) { + serviceTable = info.getIsimIst(getSubId()); + } else if ((appType == APPTYPE_USIM)) { + serviceTable = info.getSimServiceTable(getSubId(), APPTYPE_USIM); + } else { + serviceTable = null; + } + + if (serviceTable == null) { + executor.execute(() -> callback.onResult(new byte[0])); + } else { + byte[] simServiceTable = IccUtils.hexStringToBytes(serviceTable); + executor.execute(() -> callback.onResult(simServiceTable)); + } + } catch (Exception ex) { + executor.execute(() -> callback.onError(ex)); + } + } + /** * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot. * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl index b4d93fddd7aa..974cc14ae444 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl @@ -208,10 +208,9 @@ interface IPhoneSubInfo { /** * 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); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)") + List getImsPublicUserIdentities(int subId, String callingPackage); /** * Returns the IMS Service Table (IST) that was loaded from the ISIM. @@ -226,6 +225,20 @@ interface IPhoneSubInfo { */ String[] getIsimPcscf(int subId); + /** + * Fetches IMS Proxy Call Session Control Function(P-CSCF) based on the subscription. + * + * @param subId subscriptionId + * @param callingPackage package name of the caller + * @return List of IMS Proxy Call Session Control Function strings. + * @throws IllegalArgumentException if the subscriptionId is not valid + * @throws IllegalStateException in case the ISIM hasn’t been loaded. + * @throws SecurityException if the caller does not have the required permission + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)") + List getImsPcscfAddresses(int subId, String callingPackage); + /** * Returns the response of the SIM application on the UICC to authentication * challenge/response algorithm. The data string and challenge response are -- cgit v1.2.3-59-g8ed1b