Loading services/core/java/com/android/server/TelephonyRegistry.java +8 −4 Original line number Diff line number Diff line Loading @@ -394,8 +394,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { + " callback.asBinder=" + callback.asBinder()); } // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, "addOnSubscriptionsChangedListener")) { mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, "addOnSubscriptionsChangedListener")) { return; } Loading Loading @@ -686,8 +688,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private boolean canReadPhoneState(String callingPackage, String message) { try { // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. return TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, message); mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message); } catch (SecurityException e) { return false; } Loading Loading @@ -1735,8 +1738,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) { if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, message)) { // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message)) { return false; } } Loading telephony/java/android/telephony/SubscriptionManager.java +31 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.BroadcastOptions; Loading @@ -42,7 +43,6 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.DisplayMetrics; import com.android.internal.telephony.IOnSubscriptionsChangedListener; Loading @@ -59,9 +59,6 @@ import java.util.concurrent.TimeUnit; /** * SubscriptionManager is the application interface to SubscriptionController * and provides information about the current Telephony Subscriptions. * <p> * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise * specified. */ @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) public class SubscriptionManager { Loading Loading @@ -612,6 +609,8 @@ public class SubscriptionManager { * @param listener an instance of {@link OnSubscriptionsChangedListener} with * onSubscriptionsChanged overridden. */ // TODO(b/70041899): Find a way to extend this to carrier-privileged apps. @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { Loading Loading @@ -660,9 +659,15 @@ public class SubscriptionManager { /** * Get the active SubscriptionInfo with the input subId. * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * * @param subId The unique SubscriptionInfo key in database. * @return SubscriptionInfo, maybe null if its not active. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public SubscriptionInfo getActiveSubscriptionInfo(int subId) { if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId); if (!isValidSubscriptionId(subId)) { Loading Loading @@ -716,9 +721,16 @@ public class SubscriptionManager { /** * Get the active SubscriptionInfo associated with the slotIndex * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * * @param slotIndex the slot which the subscription is inserted * @return SubscriptionInfo, maybe null if its not active */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) { if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex); if (!isValidSlotIndex(slotIndex)) { Loading Loading @@ -770,6 +782,11 @@ public class SubscriptionManager { * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}. * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible * to the calling app are returned. * * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. * <ul> * <li> Loading @@ -786,6 +803,8 @@ public class SubscriptionManager { * </li> * </ul> */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public List<SubscriptionInfo> getActiveSubscriptionInfoList() { List<SubscriptionInfo> result = null; Loading Loading @@ -928,10 +947,18 @@ public class SubscriptionManager { } /** * * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include * only those subscriptions accessible to the caller. * * @return the current number of active subscriptions. There is no guarantee the value * returned by this method will be the same as the length of the list returned by * {@link #getActiveSubscriptionInfoList}. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount() { int result = 0; Loading telephony/java/android/telephony/TelephonyManager.java +197 −146 File changed.Preview size limit exceeded, changes collapsed. Show changes telephony/java/com/android/internal/telephony/TelephonyPermissions.java +64 −19 Original line number Diff line number Diff line Loading @@ -26,7 +26,8 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.ITelephony; import java.util.function.Supplier; /** Utility class for Telephony permission enforcement. */ public final class TelephonyPermissions { Loading @@ -34,6 +35,9 @@ 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)); private TelephonyPermissions() {} /** Loading @@ -41,8 +45,8 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the * READ_PHONE_STATE runtime permission. * <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. Loading @@ -51,10 +55,20 @@ public final class TelephonyPermissions { * 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. * * @param subId the subId of the relevant subscription; used to check carrier privileges. May be * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases * where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave * inaccesible to carrier-privileged apps). */ public static boolean checkCallingOrSelfReadPhoneState( Context context, String callingPackage, String message) { return checkReadPhoneState(context, Binder.getCallingPid(), Binder.getCallingUid(), Context context, int subId, String callingPackage, String message) { return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } Loading @@ -63,8 +77,8 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the * READ_PHONE_STATE runtime permission. * <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. Loading @@ -73,9 +87,22 @@ public final class TelephonyPermissions { * 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. */ public static boolean checkReadPhoneState( Context context, int pid, int uid, String callingPackage, String message) { Context context, int subId, int pid, int uid, String callingPackage, String message) { return checkReadPhoneState( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message); } @VisibleForTesting public static boolean checkReadPhoneState( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, String message) { try { context.enforcePermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message); Loading @@ -83,8 +110,18 @@ public final class TelephonyPermissions { // SKIP checking for run-time permission since caller has PRIVILEGED permission return true; } catch (SecurityException privilegedPhoneStateException) { try { context.enforcePermission( android.Manifest.permission.READ_PHONE_STATE, pid, uid, message); } catch (SecurityException phoneStateException) { // 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); return true; } throw phoneStateException; } } // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been Loading @@ -101,14 +138,16 @@ public final class TelephonyPermissions { * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers. */ public static boolean checkCallingOrSelfReadPhoneNumber( Context context, String callingPackage, String message) { Context context, int subId, String callingPackage, String message) { return checkReadPhoneNumber( context, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } @VisibleForTesting public static boolean checkReadPhoneNumber( Context context, int pid, int uid, String callingPackage, String message) { Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, String message) { // Default SMS app can always read it. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) == Loading @@ -121,7 +160,8 @@ public final class TelephonyPermissions { // First, check if we can read the phone state. try { return checkReadPhoneState(context, pid, uid, callingPackage, message); return checkReadPhoneState( context, telephonySupplier, subId, pid, uid, callingPackage, message); } catch (SecurityException readPhoneStateSecurityException) { } // Can be read with READ_SMS too. Loading Loading @@ -186,16 +226,21 @@ public final class TelephonyPermissions { } private static void enforceCarrierPrivilege(int subId, int uid, String message) { if (getCarrierPrivilegeStatus(subId, uid) != enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message); } private static void enforceCarrierPrivilege( Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege."); throw new SecurityException(message); } } private static int getCarrierPrivilegeStatus(int subId, int uid) { ITelephony telephony = ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); private static int getCarrierPrivilegeStatus( Supplier<ITelephony> telephonySupplier, int subId, int uid) { ITelephony telephony = telephonySupplier.get(); try { if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(subId, uid); Loading Loading
services/core/java/com/android/server/TelephonyRegistry.java +8 −4 Original line number Diff line number Diff line Loading @@ -394,8 +394,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { + " callback.asBinder=" + callback.asBinder()); } // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, "addOnSubscriptionsChangedListener")) { mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, "addOnSubscriptionsChangedListener")) { return; } Loading Loading @@ -686,8 +688,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private boolean canReadPhoneState(String callingPackage, String message) { try { // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. return TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, message); mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message); } catch (SecurityException e) { return false; } Loading Loading @@ -1735,8 +1738,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) { if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, callingPackage, message)) { // TODO(b/70041899): Find a way to make this work for carrier-privileged callers. if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message)) { return false; } } Loading
telephony/java/android/telephony/SubscriptionManager.java +31 −4 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressAutoDoc; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.BroadcastOptions; Loading @@ -42,7 +43,6 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.DisplayMetrics; import com.android.internal.telephony.IOnSubscriptionsChangedListener; Loading @@ -59,9 +59,6 @@ import java.util.concurrent.TimeUnit; /** * SubscriptionManager is the application interface to SubscriptionController * and provides information about the current Telephony Subscriptions. * <p> * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise * specified. */ @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) public class SubscriptionManager { Loading Loading @@ -612,6 +609,8 @@ public class SubscriptionManager { * @param listener an instance of {@link OnSubscriptionsChangedListener} with * onSubscriptionsChanged overridden. */ // TODO(b/70041899): Find a way to extend this to carrier-privileged apps. @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; if (DBG) { Loading Loading @@ -660,9 +659,15 @@ public class SubscriptionManager { /** * Get the active SubscriptionInfo with the input subId. * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * * @param subId The unique SubscriptionInfo key in database. * @return SubscriptionInfo, maybe null if its not active. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public SubscriptionInfo getActiveSubscriptionInfo(int subId) { if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId); if (!isValidSubscriptionId(subId)) { Loading Loading @@ -716,9 +721,16 @@ public class SubscriptionManager { /** * Get the active SubscriptionInfo associated with the slotIndex * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * * @param slotIndex the slot which the subscription is inserted * @return SubscriptionInfo, maybe null if its not active */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) { if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex); if (!isValidSlotIndex(slotIndex)) { Loading Loading @@ -770,6 +782,11 @@ public class SubscriptionManager { * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}. * * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible * to the calling app are returned. * * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. * <ul> * <li> Loading @@ -786,6 +803,8 @@ public class SubscriptionManager { * </li> * </ul> */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public List<SubscriptionInfo> getActiveSubscriptionInfoList() { List<SubscriptionInfo> result = null; Loading Loading @@ -928,10 +947,18 @@ public class SubscriptionManager { } /** * * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include * only those subscriptions accessible to the caller. * * @return the current number of active subscriptions. There is no guarantee the value * returned by this method will be the same as the length of the list returned by * {@link #getActiveSubscriptionInfoList}. */ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount() { int result = 0; Loading
telephony/java/android/telephony/TelephonyManager.java +197 −146 File changed.Preview size limit exceeded, changes collapsed. Show changes
telephony/java/com/android/internal/telephony/TelephonyPermissions.java +64 −19 Original line number Diff line number Diff line Loading @@ -26,7 +26,8 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.ITelephony; import java.util.function.Supplier; /** Utility class for Telephony permission enforcement. */ public final class TelephonyPermissions { Loading @@ -34,6 +35,9 @@ 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)); private TelephonyPermissions() {} /** Loading @@ -41,8 +45,8 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the * READ_PHONE_STATE runtime permission. * <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. Loading @@ -51,10 +55,20 @@ public final class TelephonyPermissions { * 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. * * @param subId the subId of the relevant subscription; used to check carrier privileges. May be * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases * where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave * inaccesible to carrier-privileged apps). */ public static boolean checkCallingOrSelfReadPhoneState( Context context, String callingPackage, String message) { return checkReadPhoneState(context, Binder.getCallingPid(), Binder.getCallingUid(), Context context, int subId, String callingPackage, String message) { return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } Loading @@ -63,8 +77,8 @@ public final class TelephonyPermissions { * * <p>This method behaves in one of the following ways: * <ul> * <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the * READ_PHONE_STATE runtime permission. * <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. Loading @@ -73,9 +87,22 @@ public final class TelephonyPermissions { * 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. */ public static boolean checkReadPhoneState( Context context, int pid, int uid, String callingPackage, String message) { Context context, int subId, int pid, int uid, String callingPackage, String message) { return checkReadPhoneState( context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message); } @VisibleForTesting public static boolean checkReadPhoneState( Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, String message) { try { context.enforcePermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message); Loading @@ -83,8 +110,18 @@ public final class TelephonyPermissions { // SKIP checking for run-time permission since caller has PRIVILEGED permission return true; } catch (SecurityException privilegedPhoneStateException) { try { context.enforcePermission( android.Manifest.permission.READ_PHONE_STATE, pid, uid, message); } catch (SecurityException phoneStateException) { // 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); return true; } throw phoneStateException; } } // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been Loading @@ -101,14 +138,16 @@ public final class TelephonyPermissions { * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers. */ public static boolean checkCallingOrSelfReadPhoneNumber( Context context, String callingPackage, String message) { Context context, int subId, String callingPackage, String message) { return checkReadPhoneNumber( context, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message); } @VisibleForTesting public static boolean checkReadPhoneNumber( Context context, int pid, int uid, String callingPackage, String message) { Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid, String callingPackage, String message) { // Default SMS app can always read it. AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) == Loading @@ -121,7 +160,8 @@ public final class TelephonyPermissions { // First, check if we can read the phone state. try { return checkReadPhoneState(context, pid, uid, callingPackage, message); return checkReadPhoneState( context, telephonySupplier, subId, pid, uid, callingPackage, message); } catch (SecurityException readPhoneStateSecurityException) { } // Can be read with READ_SMS too. Loading Loading @@ -186,16 +226,21 @@ public final class TelephonyPermissions { } private static void enforceCarrierPrivilege(int subId, int uid, String message) { if (getCarrierPrivilegeStatus(subId, uid) != enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message); } private static void enforceCarrierPrivilege( Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) { if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege."); throw new SecurityException(message); } } private static int getCarrierPrivilegeStatus(int subId, int uid) { ITelephony telephony = ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); private static int getCarrierPrivilegeStatus( Supplier<ITelephony> telephonySupplier, int subId, int uid) { ITelephony telephony = telephonySupplier.get(); try { if (telephony != null) { return telephony.getCarrierPrivilegeStatusForUid(subId, uid); Loading