Loading api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -9215,6 +9215,7 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(); services/core/java/com/android/server/TelephonyRegistry.java +3 −2 Original line number Diff line number Diff line Loading @@ -1293,7 +1293,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // only CarrierService with carrier privilege rule should have the permission int[] subIds = Arrays.stream(SubscriptionManager.from(mContext) .getActiveSubscriptionIdList(false)) .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i)).toArray(); .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, i)).toArray(); if (ArrayUtils.isEmpty(subIds)) { loge("notifyCarrierNetworkChange without carrier privilege"); // the active subId does not have carrier privilege. Loading Loading @@ -2301,7 +2302,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege( TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, SubscriptionManager.getDefaultSubscriptionId(), method); } Loading telephony/common/com/android/internal/telephony/TelephonyPermissions.java +36 −116 Original line number Diff line number Diff line Loading @@ -27,8 +27,6 @@ import android.content.pm.PackageManager; import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading @@ -41,7 +39,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Supplier; /** Utility class for Telephony permission enforcement. */ public final class TelephonyPermissions { Loading @@ -49,9 +46,6 @@ public final class TelephonyPermissions { private static final boolean DBG = false; private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () -> ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); /** * Whether to disable the new device identifier access restrictions. */ Loading Loading @@ -137,49 +131,6 @@ public final class TelephonyPermissions { public static boolean checkReadPhoneState( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneState( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId, message); } /** * Check whether the calling packages has carrier privileges for the passing subscription. * @return {@code true} if the caller has carrier privileges, {@false} otherwise. */ public static boolean checkCarrierPrivilegeForSubId(int subId) { if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid()) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } return false; } /** * Check whether the app with the given pid/uid can read phone state. * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId. * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for * apps which support runtime permissions, if the caller does not currently have any of * these permissions. * <li>return false: if the caller lacks all of these permissions and doesn't support runtime * permissions. This implies that the user revoked the ability to read phone state * manually (via AppOps). In this case we can't throw as it would break app compatibility, * so we return false to indicate that the calling function should return dummy data. * </ul> * * <p>Note: for simplicity, this method always returns false for callers using legacy * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged. * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+ * devices. */ @VisibleForTesting public static boolean checkReadPhoneState( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { try { context.enforcePermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message); Loading @@ -194,7 +145,7 @@ public final class TelephonyPermissions { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for reading phone state. if (SubscriptionManager.isValidSubscriptionId(subId)) { enforceCarrierPrivilege(telephonySupplier, subId, uid, message); enforceCarrierPrivilege(context, subId, uid, message); return true; } throw phoneStateException; Loading @@ -209,23 +160,16 @@ public final class TelephonyPermissions { } /** * Check whether the app with the given pid/uid can read phone state, or has carrier * privileges on any active subscription. * * <p>If the app does not have carrier privilege, this method will return {@code false} instead * of throwing a SecurityException. Therefore, the callers cannot tell the difference * between M+ apps which declare the runtime permission but do not have it, and pre-M apps * which declare the static permission but had access revoked via AppOps. Apps in the former * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for * use only if the behavior in both scenarios is meant to be identical. * * @return {@code true} if the app can read phone state or has carrier privilege; * {@code false} otherwise. * Check whether the calling packages has carrier privileges for the passing subscription. * @return {@code true} if the caller has carrier privileges, {@false} otherwise. */ public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid, callingPackage, callingFeatureId, message); public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) { if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid()) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } return false; } /** Loading @@ -242,9 +186,7 @@ public final class TelephonyPermissions { * @return {@code true} if the app can read phone state or has carrier privilege; * {@code false} otherwise. */ @VisibleForTesting public static boolean checkReadPhoneStateOnAnyActiveSub( Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid, public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { try { context.enforcePermission( Loading @@ -259,7 +201,7 @@ public final class TelephonyPermissions { } catch (SecurityException phoneStateException) { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for reading phone state. return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid); return checkCarrierPrivilegeForAnySubId(context, uid); } } Loading Loading @@ -374,12 +316,11 @@ public final class TelephonyPermissions { } // If the calling package has carrier privileges for specified sub, then allow access. if (checkCarrierPrivilegeForSubId(subId)) return true; if (checkCarrierPrivilegeForSubId(context, subId)) return true; // If the calling package has carrier privileges for any subscription // and allowCarrierPrivilegeOnAnySub is set true, then allow access. if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId( context, TELEPHONY_SUPPLIER, uid)) { if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) { return true; } Loading Loading @@ -471,7 +412,7 @@ public final class TelephonyPermissions { uid) == PackageManager.PERMISSION_GRANTED) { return false; } if (checkCarrierPrivilegeForSubId(subId)) { if (checkCarrierPrivilegeForSubId(context, subId)) { return false; } } Loading @@ -487,26 +428,12 @@ public final class TelephonyPermissions { public static boolean checkReadCallLog( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingPackageName) { return checkReadCallLog( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName); } /** * Check whether the app with the given pid/uid can read the call log. * @return {@code true} if the specified app has the read call log permission and AppOpp granted * to it, {@code false} otherwise. */ @VisibleForTesting public static boolean checkReadCallLog( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId) { if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid) != PERMISSION_GRANTED) { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for being able to see the call phone numbers. if (SubscriptionManager.isValidSubscriptionId(subId)) { enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog"); enforceCarrierPrivilege(context, subId, uid, "readCallLog"); return true; } return false; Loading @@ -529,7 +456,7 @@ public final class TelephonyPermissions { Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneNumber( context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(), context, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, message); } Loading @@ -541,7 +468,7 @@ public final class TelephonyPermissions { */ @VisibleForTesting public static boolean checkReadPhoneNumber( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { // Default SMS app can always read it. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); Loading @@ -556,7 +483,7 @@ public final class TelephonyPermissions { // First, check if we can read the phone state. try { return checkReadPhoneState( context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId, context, subId, pid, uid, callingPackage, callingFeatureId, message); } catch (SecurityException readPhoneStateSecurityException) { } Loading Loading @@ -598,7 +525,7 @@ public final class TelephonyPermissions { } if (DBG) Log.d(LOG_TAG, "No modify permission, check carrier privilege next."); enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -618,7 +545,7 @@ public final class TelephonyPermissions { Log.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next."); } enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -639,7 +566,7 @@ public final class TelephonyPermissions { + "check carrier privilege next."); } enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -647,21 +574,18 @@ public final class TelephonyPermissions { * * @throws SecurityException if the caller does not have the required privileges */ public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) { public static void enforceCallingOrSelfCarrierPrivilege( Context context, int subId, String message) { // NOTE: It's critical that we explicitly pass the calling UID here rather than call // TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from // the phone process. When called from another process, it will check whether that process // has carrier privileges instead. enforceCarrierPrivilege(subId, Binder.getCallingUid(), message); } private static void enforceCarrierPrivilege(int subId, int uid, String message) { enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message); enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message); } private static void enforceCarrierPrivilege( Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) Context context, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(context, subId, uid) != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { if (DBG) Log.e(LOG_TAG, "No Carrier Privilege."); throw new SecurityException(message); Loading @@ -669,13 +593,12 @@ public final class TelephonyPermissions { } /** Returns whether the provided uid has carrier privileges for any active subscription ID. */ private static boolean checkCarrierPrivilegeForAnySubId( Context context, Supplier<ITelephony> telephonySupplier, int uid) { private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) { SubscriptionManager sm = (SubscriptionManager) context.getSystemService( Context.TELEPHONY_SUBSCRIPTION_SERVICE); int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false); for (int activeSubId : activeSubIds) { if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid) if (getCarrierPrivilegeStatus(context, activeSubId, uid) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } Loading @@ -683,18 +606,15 @@ public final class TelephonyPermissions { return false; } private static int getCarrierPrivilegeStatus( Supplier<ITelephony> telephonySupplier, int subId, int uid) { ITelephony telephony = telephonySupplier.get(); private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) { final long identity = Binder.clearCallingIdentity(); try { if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(subId, uid); } } catch (RemoteException e) { // Fallback below. TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid); } finally { Binder.restoreCallingIdentity(identity); } Log.e(LOG_TAG, "Phone process is down, cannot check carrier privileges"); return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; } /** Loading telephony/java/android/telephony/TelephonyManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -11749,6 +11749,32 @@ public class TelephonyManager { return new Pair<Integer, Integer>(-1, -1); } /** * Get the calling application status about carrier privileges for the subscription created * in TelephonyManager. Used by Telephony Module for permission checking. * * @param uid Uid to check. * @return any value of {@link #CARRIER_PRIVILEGE_STATUS_HAS_ACCESS}, * {@link #CARRIER_PRIVILEGE_STATUS_NO_ACCESS}, * {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or * {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES} * * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int uid) { try { ITelephony telephony = getITelephony(); if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(getSubId(), uid); } } catch (RemoteException ex) { Log.e(TAG, "getCarrierPrivilegeStatus RemoteException", ex); } return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; } /** * Returns a list of APNs set as overrides by the device policy manager via * {@link #addDevicePolicyOverrideApn}. Loading Loading
api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -9215,6 +9215,7 @@ package android.telephony { method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
services/core/java/com/android/server/TelephonyRegistry.java +3 −2 Original line number Diff line number Diff line Loading @@ -1293,7 +1293,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // only CarrierService with carrier privilege rule should have the permission int[] subIds = Arrays.stream(SubscriptionManager.from(mContext) .getActiveSubscriptionIdList(false)) .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i)).toArray(); .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, i)).toArray(); if (ArrayUtils.isEmpty(subIds)) { loge("notifyCarrierNetworkChange without carrier privilege"); // the active subId does not have carrier privilege. Loading Loading @@ -2301,7 +2302,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege( TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext, SubscriptionManager.getDefaultSubscriptionId(), method); } Loading
telephony/common/com/android/internal/telephony/TelephonyPermissions.java +36 −116 Original line number Diff line number Diff line Loading @@ -27,8 +27,6 @@ import android.content.pm.PackageManager; import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading @@ -41,7 +39,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Supplier; /** Utility class for Telephony permission enforcement. */ public final class TelephonyPermissions { Loading @@ -49,9 +46,6 @@ public final class TelephonyPermissions { private static final boolean DBG = false; private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () -> ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); /** * Whether to disable the new device identifier access restrictions. */ Loading Loading @@ -137,49 +131,6 @@ public final class TelephonyPermissions { public static boolean checkReadPhoneState( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneState( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId, message); } /** * Check whether the calling packages has carrier privileges for the passing subscription. * @return {@code true} if the caller has carrier privileges, {@false} otherwise. */ public static boolean checkCarrierPrivilegeForSubId(int subId) { if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid()) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } return false; } /** * Check whether the app with the given pid/uid can read phone state. * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the * READ_PHONE_STATE runtime permission, or carrier privileges on the given subId. * <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for * apps which support runtime permissions, if the caller does not currently have any of * these permissions. * <li>return false: if the caller lacks all of these permissions and doesn't support runtime * permissions. This implies that the user revoked the ability to read phone state * manually (via AppOps). In this case we can't throw as it would break app compatibility, * so we return false to indicate that the calling function should return dummy data. * </ul> * * <p>Note: for simplicity, this method always returns false for callers using legacy * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged. * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+ * devices. */ @VisibleForTesting public static boolean checkReadPhoneState( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { try { context.enforcePermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message); Loading @@ -194,7 +145,7 @@ public final class TelephonyPermissions { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for reading phone state. if (SubscriptionManager.isValidSubscriptionId(subId)) { enforceCarrierPrivilege(telephonySupplier, subId, uid, message); enforceCarrierPrivilege(context, subId, uid, message); return true; } throw phoneStateException; Loading @@ -209,23 +160,16 @@ public final class TelephonyPermissions { } /** * Check whether the app with the given pid/uid can read phone state, or has carrier * privileges on any active subscription. * * <p>If the app does not have carrier privilege, this method will return {@code false} instead * of throwing a SecurityException. Therefore, the callers cannot tell the difference * between M+ apps which declare the runtime permission but do not have it, and pre-M apps * which declare the static permission but had access revoked via AppOps. Apps in the former * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for * use only if the behavior in both scenarios is meant to be identical. * * @return {@code true} if the app can read phone state or has carrier privilege; * {@code false} otherwise. * Check whether the calling packages has carrier privileges for the passing subscription. * @return {@code true} if the caller has carrier privileges, {@false} otherwise. */ public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid, callingPackage, callingFeatureId, message); public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) { if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid()) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } return false; } /** Loading @@ -242,9 +186,7 @@ public final class TelephonyPermissions { * @return {@code true} if the app can read phone state or has carrier privilege; * {@code false} otherwise. */ @VisibleForTesting public static boolean checkReadPhoneStateOnAnyActiveSub( Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid, public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { try { context.enforcePermission( Loading @@ -259,7 +201,7 @@ public final class TelephonyPermissions { } catch (SecurityException phoneStateException) { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for reading phone state. return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid); return checkCarrierPrivilegeForAnySubId(context, uid); } } Loading Loading @@ -374,12 +316,11 @@ public final class TelephonyPermissions { } // If the calling package has carrier privileges for specified sub, then allow access. if (checkCarrierPrivilegeForSubId(subId)) return true; if (checkCarrierPrivilegeForSubId(context, subId)) return true; // If the calling package has carrier privileges for any subscription // and allowCarrierPrivilegeOnAnySub is set true, then allow access. if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId( context, TELEPHONY_SUPPLIER, uid)) { if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) { return true; } Loading Loading @@ -471,7 +412,7 @@ public final class TelephonyPermissions { uid) == PackageManager.PERMISSION_GRANTED) { return false; } if (checkCarrierPrivilegeForSubId(subId)) { if (checkCarrierPrivilegeForSubId(context, subId)) { return false; } } Loading @@ -487,26 +428,12 @@ public final class TelephonyPermissions { public static boolean checkReadCallLog( Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingPackageName) { return checkReadCallLog( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName); } /** * Check whether the app with the given pid/uid can read the call log. * @return {@code true} if the specified app has the read call log permission and AppOpp granted * to it, {@code false} otherwise. */ @VisibleForTesting public static boolean checkReadCallLog( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId) { if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid) != PERMISSION_GRANTED) { // If we don't have the runtime permission, but do have carrier privileges, that // suffices for being able to see the call phone numbers. if (SubscriptionManager.isValidSubscriptionId(subId)) { enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog"); enforceCarrierPrivilege(context, subId, uid, "readCallLog"); return true; } return false; Loading @@ -529,7 +456,7 @@ public final class TelephonyPermissions { Context context, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { return checkReadPhoneNumber( context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(), context, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, message); } Loading @@ -541,7 +468,7 @@ public final class TelephonyPermissions { */ @VisibleForTesting public static boolean checkReadPhoneNumber( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, Context context, int subId, int pid, int uid, String callingPackage, @Nullable String callingFeatureId, String message) { // Default SMS app can always read it. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); Loading @@ -556,7 +483,7 @@ public final class TelephonyPermissions { // First, check if we can read the phone state. try { return checkReadPhoneState( context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId, context, subId, pid, uid, callingPackage, callingFeatureId, message); } catch (SecurityException readPhoneStateSecurityException) { } Loading Loading @@ -598,7 +525,7 @@ public final class TelephonyPermissions { } if (DBG) Log.d(LOG_TAG, "No modify permission, check carrier privilege next."); enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -618,7 +545,7 @@ public final class TelephonyPermissions { Log.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next."); } enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -639,7 +566,7 @@ public final class TelephonyPermissions { + "check carrier privilege next."); } enforceCallingOrSelfCarrierPrivilege(subId, message); enforceCallingOrSelfCarrierPrivilege(context, subId, message); } /** Loading @@ -647,21 +574,18 @@ public final class TelephonyPermissions { * * @throws SecurityException if the caller does not have the required privileges */ public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) { public static void enforceCallingOrSelfCarrierPrivilege( Context context, int subId, String message) { // NOTE: It's critical that we explicitly pass the calling UID here rather than call // TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from // the phone process. When called from another process, it will check whether that process // has carrier privileges instead. enforceCarrierPrivilege(subId, Binder.getCallingUid(), message); } private static void enforceCarrierPrivilege(int subId, int uid, String message) { enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message); enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message); } private static void enforceCarrierPrivilege( Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) Context context, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(context, subId, uid) != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { if (DBG) Log.e(LOG_TAG, "No Carrier Privilege."); throw new SecurityException(message); Loading @@ -669,13 +593,12 @@ public final class TelephonyPermissions { } /** Returns whether the provided uid has carrier privileges for any active subscription ID. */ private static boolean checkCarrierPrivilegeForAnySubId( Context context, Supplier<ITelephony> telephonySupplier, int uid) { private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) { SubscriptionManager sm = (SubscriptionManager) context.getSystemService( Context.TELEPHONY_SUBSCRIPTION_SERVICE); int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false); for (int activeSubId : activeSubIds) { if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid) if (getCarrierPrivilegeStatus(context, activeSubId, uid) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { return true; } Loading @@ -683,18 +606,15 @@ public final class TelephonyPermissions { return false; } private static int getCarrierPrivilegeStatus( Supplier<ITelephony> telephonySupplier, int subId, int uid) { ITelephony telephony = telephonySupplier.get(); private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) { final long identity = Binder.clearCallingIdentity(); try { if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(subId, uid); } } catch (RemoteException e) { // Fallback below. TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid); } finally { Binder.restoreCallingIdentity(identity); } Log.e(LOG_TAG, "Phone process is down, cannot check carrier privileges"); return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; } /** Loading
telephony/java/android/telephony/TelephonyManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -11749,6 +11749,32 @@ public class TelephonyManager { return new Pair<Integer, Integer>(-1, -1); } /** * Get the calling application status about carrier privileges for the subscription created * in TelephonyManager. Used by Telephony Module for permission checking. * * @param uid Uid to check. * @return any value of {@link #CARRIER_PRIVILEGE_STATUS_HAS_ACCESS}, * {@link #CARRIER_PRIVILEGE_STATUS_NO_ACCESS}, * {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or * {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES} * * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int uid) { try { ITelephony telephony = getITelephony(); if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(getSubId(), uid); } } catch (RemoteException ex) { Log.e(TAG, "getCarrierPrivilegeStatus RemoteException", ex); } return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; } /** * Returns a list of APNs set as overrides by the device policy manager via * {@link #addDevicePolicyOverrideApn}. Loading