diff options
5 files changed, 144 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 59db68691223..f149fda7a043 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -45,6 +45,7 @@ import android.telephony.TelephonyManager; import android.util.Slog; import com.android.internal.telephony.IMms; +import com.android.internal.telephony.TelephonyPermissions; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriGrantsManagerInternal; @@ -337,6 +338,14 @@ public class MmsServiceBroker extends SystemService { throws RemoteException { Slog.d(TAG, "sendMessage() by " + callingPkg); mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message"); + + // Check if user is associated with the subscription + if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(mContext, subId, + Binder.getCallingUserHandle())) { + // TODO(b/258629881): Display error dialog. + return; + } + if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) { Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()"); diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index fdf694303dbc..f90eabc7175e 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -18,6 +18,7 @@ package com.android.internal.telephony; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import android.Manifest; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; @@ -822,4 +823,35 @@ public final class TelephonyPermissions { } return Integer.MAX_VALUE; } + + /** + * Check if calling user is associated with the given subscription. + * @param context Context + * @param subId subscription ID + * @param callerUserHandle caller user handle + * @return false if user is not associated with the subscription. + */ + public static boolean checkSubscriptionAssociatedWithUser(@NonNull Context context, int subId, + @NonNull UserHandle callerUserHandle) { + if (!SubscriptionManager.isValidSubscriptionId(subId)) { + // No subscription on device, return true. + return true; + } + + SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class); + final long token = Binder.clearCallingIdentity(); + try { + 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() + + "] is not associated with Subscription ID:" + subId); + return false; + + } + } finally { + Binder.restoreCallingIdentity(token); + } + return true; + } } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index d670e5592c42..1cf2969ea9b5 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2245,6 +2245,7 @@ public final class SmsManager { RESULT_SMS_SEND_RETRY_FAILED, RESULT_REMOTE_EXCEPTION, RESULT_NO_DEFAULT_SMS_APP, + RESULT_USER_NOT_ALLOWED, RESULT_RIL_RADIO_NOT_AVAILABLE, RESULT_RIL_SMS_SEND_FAIL_RETRY, RESULT_RIL_NETWORK_REJECT, @@ -2425,6 +2426,13 @@ public final class SmsManager { */ public static final int RESULT_NO_DEFAULT_SMS_APP = 32; + /** + * User is not associated with the subscription. + * TODO(b/263279115): Make this error code public. + * @hide + */ + public static final int RESULT_USER_NOT_ALLOWED = 33; + // Radio Error results /** diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 37bfa72f9394..b99f3d681585 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -4394,5 +4394,70 @@ public class SubscriptionManager { } return null; } + + /** + * Check if subscription and user are associated with each other. + * + * @param subscriptionId the subId of the subscription + * @param userHandle user handle of the user + * @return {@code true} if subscription is associated with user + * {code true} if there are no subscriptions on device + * else {@code false} if subscription is not associated with user. + * + * @throws IllegalArgumentException if subscription is invalid. + * @throws SecurityException if the caller doesn't have permissions required. + * @throws IllegalStateException if subscription service is not available. + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) + public boolean isSubscriptionAssociatedWithUser(int subscriptionId, + @NonNull UserHandle userHandle) { + if (!isValidSubscriptionId(subscriptionId)) { + throw new IllegalArgumentException("[isSubscriptionAssociatedWithUser]: " + + "Invalid subscriptionId: " + subscriptionId); + } + + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + return iSub.isSubscriptionAssociatedWithUser(subscriptionId, userHandle); + } else { + throw new IllegalStateException("[isSubscriptionAssociatedWithUser]: " + + "subscription service unavailable"); + } + } catch (RemoteException ex) { + ex.rethrowAsRuntimeException(); + } + return false; + } + + /** + * Get list of subscriptions associated with user. + * + * @param userHandle user handle of the user + * @return list of subscriptionInfo associated with the user. + * + * @throws SecurityException if the caller doesn't have permissions required. + * @throws IllegalStateException if subscription service is not available. + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) + public @NonNull List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser( + @NonNull UserHandle userHandle) { + try { + ISub iSub = TelephonyManager.getSubscriptionService(); + if (iSub != null) { + return iSub.getSubscriptionInfoListAssociatedWithUser(userHandle); + } else { + throw new IllegalStateException("[getSubscriptionInfoListAssociatedWithUser]: " + + "subscription service unavailable"); + } + } catch (RemoteException ex) { + ex.rethrowAsRuntimeException(); + } + return new ArrayList<>(); + } } diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index c5f6902062ff..25a714a4bb81 100644 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -326,4 +326,34 @@ interface ISub { * @throws IllegalArgumentException if subId is invalid. */ UserHandle getSubscriptionUserHandle(int subId); + + /** + * Check if subscription and user are associated with each other. + * + * @param subscriptionId the subId of the subscription + * @param userHandle user handle of the user + * @return {@code true} if subscription is associated with user + * {code true} if there are no subscriptions on device + * else {@code false} if subscription is not associated with user. + * + * @throws IllegalArgumentException if subscription is invalid. + * @throws SecurityException if the caller doesn't have permissions required. + * @throws IllegalStateException if subscription service is not available. + * + * @hide + */ + boolean isSubscriptionAssociatedWithUser(int subscriptionId, in UserHandle userHandle); + + /** + * Get list of subscriptions associated with user. + * + * @param userHandle user handle of the user + * @return list of subscriptionInfo associated with the user. + * + * @throws SecurityException if the caller doesn't have permissions required. + * @throws IllegalStateException if subscription service is not available. + * + * @hide + */ + List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle); } |