Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae0c9780 authored by Nikhil Kumar's avatar Nikhil Kumar
Browse files

Redirect incoming messages broadcasts to the MAIN user.

InboundSMSHandler broadcasts incoming SMS messages to interested apps after storing them in the SmsProvider raw table and ACKing them to the SMSC.

In the existing implementation all the default SMS app broadcast like SMS_DELIVER_ACTION, WAP_PUSH_DELIVER_ACTION are only sent to the SYSTEM user's default SMS app.

In HSUM, when we intend to assign the bugle process to the MAIN user, we need to refactor the framework module. This will involve redirecting all the specialized broadcasts and actions from the SYSTEM user to the Subscription User.

Refactor InboundSMSHander to start sending these broadcast to the MAIN user while maintaining the backward compatibility.

For more info follow design doc: go/messages-hsum-design-doc

Bug: 335820374
Test: Manually verfied below features on HSUM and non-HSUM mode devices aftter the change and with flag enabled. (1) Incoming and Outgoing Messages (2) Incoming and outgoing calls (3) Full RCS functionality
Test:  atest FrameworksTelephonyTests:WapPushOverSmsTest -c
Test:  atest FrameworksTelephonyTests:GsmInboundSmsHandlerTest -c

Flag: com.android.internal.telephony.flags.sms_mms_deliver_broadcasts_redirect_to_main_user
Change-Id: I016ec42d076dda7ca074a28846142b3a2a3f367a
parent a5a01e46
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -73,6 +74,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SmsConstants.MessageClass;
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.internal.telephony.util.NotificationChannelController;
@@ -284,6 +286,8 @@ public abstract class InboundSmsHandler extends StateMachine {

    private List<SmsFilter> mSmsFilters;

    protected final @NonNull FeatureFlags mFeatureFlags;

    /**
     * Create a new SMS broadcast helper.
     * @param name the class name for logging
@@ -291,14 +295,15 @@ public abstract class InboundSmsHandler extends StateMachine {
     * @param storageMonitor the SmsStorageMonitor to check for storage availability
     */
    protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
            Phone phone, Looper looper) {
            Phone phone, Looper looper, FeatureFlags featureFlags) {
        super(name, looper);

        mFeatureFlags = featureFlags;
        mContext = context;
        mStorageMonitor = storageMonitor;
        mPhone = phone;
        mResolver = context.getContentResolver();
        mWapPush = new WapPushOverSms(context);
        mWapPush = new WapPushOverSms(context, mFeatureFlags);

        boolean smsCapable = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_sms_capable);
@@ -1324,6 +1329,7 @@ public abstract class InboundSmsHandler extends StateMachine {
     * @param user user to deliver the intent to
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    @SuppressLint("MissingPermission")
    public void dispatchIntent(Intent intent, String permission, String appOp,
            Bundle opts, SmsBroadcastReceiver resultReceiver, UserHandle user, int subId) {
        intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
@@ -1352,12 +1358,17 @@ public abstract class InboundSmsHandler extends StateMachine {
            // Get a list of currently started users.
            int[] users = null;
            final List<UserHandle> userHandles = mUserManager.getUserHandles(false);
            final UserHandle mainUser = mUserManager.getMainUser();
            final List<UserHandle> runningUserHandles = new ArrayList();
            for (UserHandle handle : userHandles) {
                if (mUserManager.isUserRunning(handle)) {
                    runningUserHandles.add(handle);
                } else {
                    if (handle.equals(UserHandle.SYSTEM)) {
                    if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()
                            && handle.equals(mainUser)) {
                        logeWithLocalLog("dispatchIntent: MAIN user is not running",
                                resultReceiver.mInboundSmsTracker.getMessageId());
                    } else if (handle.equals(UserHandle.SYSTEM)) {
                        logeWithLocalLog("dispatchIntent: SYSTEM user is not running",
                                resultReceiver.mInboundSmsTracker.getMessageId());
                    }
@@ -1375,7 +1386,7 @@ public abstract class InboundSmsHandler extends StateMachine {
            // by user policy.
            for (int i = users.length - 1; i >= 0; i--) {
                UserHandle targetUser = UserHandle.of(users[i]);
                if (users[i] != UserHandle.SYSTEM.getIdentifier()) {
                if (!isMainUser(users[i])) {
                    // Is the user not allowed to use SMS?
                    if (hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
                        continue;
@@ -1385,14 +1396,14 @@ public abstract class InboundSmsHandler extends StateMachine {
                        continue;
                    }
                }
                // Only pass in the resultReceiver when the user SYSTEM is processed.
                // Only pass in the resultReceiver when the MAIN user is processed.
                try {
                    if (users[i] == UserHandle.SYSTEM.getIdentifier()) {
                    if (isMainUser(users[i])) {
                        resultReceiver.setWaitingForIntent(intent);
                    }
                    mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
                            .sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp,
                                    users[i] == UserHandle.SYSTEM.getIdentifier()
                                    isMainUser(users[i])
                                            ? resultReceiver : null, getHandler(),
                                    null /* initialData */, null /* initialExtras */, opts);
                } catch (PackageManager.NameNotFoundException ignored) {
@@ -1416,6 +1427,15 @@ public abstract class InboundSmsHandler extends StateMachine {
        return (sources != null && !sources.isEmpty());
    }

    @SuppressLint("MissingPermission")
    private  boolean isMainUser(int userId) {
        if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
            return userId == mUserManager.getMainUser().getIdentifier();
        } else {
            return userId == UserHandle.SYSTEM.getIdentifier();
        }
    }

    /**
     * Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table.
     */
@@ -1511,8 +1531,12 @@ public abstract class InboundSmsHandler extends StateMachine {
        }

        if (userHandle == null) {
            if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
                userHandle = mUserManager.getMainUser();
            } else {
                userHandle = UserHandle.SYSTEM;
            }
        }
        Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
        dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
                AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, userHandle, subId);
@@ -1739,6 +1763,7 @@ public abstract class InboundSmsHandler extends StateMachine {
            handleAction(intent, true);
        }

        @SuppressLint("MissingPermission")
        private synchronized void handleAction(@NonNull Intent intent, boolean onReceive) {
            String action = intent.getAction();
            if (mWaitingForIntent == null || !mWaitingForIntent.getAction().equals(action)) {
@@ -1795,9 +1820,15 @@ public abstract class InboundSmsHandler extends StateMachine {
                String mimeType = intent.getType();

                setWaitingForIntent(intent);
                if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
                    dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
                        WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
                        UserHandle.SYSTEM, subId);
                            WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options,
                            this, mUserManager.getMainUser(), subId);
                } else {
                    dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
                            WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options,
                            this, UserHandle.SYSTEM, subId);
                }
            } else {
                // Now that the intents have been deleted we can clean up the PDU data.
                if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
+2 −2
Original line number Diff line number Diff line
@@ -381,9 +381,9 @@ public class SmsDispatchersController extends Handler {
        mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, ImsManager::getConnector);
        mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
        mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
                storageMonitor, phone, looper);
                storageMonitor, phone, looper, mFeatureFlags);
        mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
                storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper);
                storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper, mFeatureFlags);
        mGsmDispatcher = new GsmSMSDispatcher(phone, this, mGsmInboundSmsHandler);
        SmsBroadcastUndelivered.initialize(phone.getContext(),
                mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+17 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.google.android.mms.pdu.PduHeaders.MESSAGE_TYPE_NOTIFICATION_IN

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -45,6 +46,7 @@ import android.telephony.SmsManager;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;

import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.telephony.Rlog;
@@ -67,8 +69,14 @@ public class WapPushOverSms implements ServiceConnection {

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private final Context mContext;

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private UserManager mUserManager;

    PowerWhitelistManager mPowerWhitelistManager;

    protected final @NonNull FeatureFlags mFeatureFlags;

    private String mWapPushManagerPackage;

    /** Assigned from ServiceConnection callback on main threaad. */
@@ -128,11 +136,11 @@ public class WapPushOverSms implements ServiceConnection {
        if (DBG) Rlog.v(TAG, "wappush manager disconnected.");
    }

    public WapPushOverSms(Context context) {
    public WapPushOverSms(Context context, FeatureFlags featureFlags) {
        mFeatureFlags = featureFlags;
        mContext = context;
        mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class);

        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mUserManager = mContext.getSystemService(UserManager.class);

        bindWapPushManagerService(mContext);
    }
@@ -325,6 +333,7 @@ public class WapPushOverSms implements ServiceConnection {
     *         {@link Activity#RESULT_OK} if the message has been broadcast
     *         to applications
     */
    @SuppressLint("MissingPermission")
    public int dispatchWapPdu(byte[] pdu, InboundSmsHandler.SmsBroadcastReceiver receiver,
            InboundSmsHandler handler, String address, int subId, long messageId) {
        DecodedResult result = decodeWapPdu(pdu, handler);
@@ -422,8 +431,12 @@ public class WapPushOverSms implements ServiceConnection {
        }

        if (userHandle == null) {
            if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
                userHandle = mUserManager.getMainUser();
            } else {
                userHandle = UserHandle.SYSTEM;
            }
        }
        handler.dispatchIntent(intent, getPermissionForType(result.mimeType),
                getAppOpsStringPermissionForIntent(result.mimeType), options, receiver,
                userHandle, subId);
+6 −4
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.internal.telephony.WspTypeDecoder;
import com.android.internal.telephony.cdma.sms.BearerData;
import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.HexDump;

import java.io.ByteArrayOutputStream;
@@ -78,8 +79,9 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
     * Create a new inbound SMS handler for CDMA.
     */
    private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
            Phone phone, CdmaSMSDispatcher smsDispatcher, Looper looper) {
        super("CdmaInboundSmsHandler", context, storageMonitor, phone, looper);
            Phone phone, CdmaSMSDispatcher smsDispatcher, Looper looper,
            FeatureFlags featureFlags) {
        super("CdmaInboundSmsHandler", context, storageMonitor, phone, looper, featureFlags);
        mSmsDispatcher = smsDispatcher;
        phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);

@@ -171,9 +173,9 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
     */
    public static CdmaInboundSmsHandler makeInboundSmsHandler(Context context,
            SmsStorageMonitor storageMonitor, Phone phone, CdmaSMSDispatcher smsDispatcher,
            Looper looper) {
            Looper looper, FeatureFlags featureFlags) {
        CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
                phone, smsDispatcher, looper);
                phone, smsDispatcher, looper, featureFlags);
        handler.start();
        return handler;
    }
+6 −4
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsStorageMonitor;
import com.android.internal.telephony.VisualVoicemailSmsFilter;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.UsimServiceTable;

/**
@@ -58,8 +59,8 @@ public class GsmInboundSmsHandler extends InboundSmsHandler {
     * Create a new GSM inbound SMS handler.
     */
    private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
            Phone phone, Looper looper) {
        super("GsmInboundSmsHandler", context, storageMonitor, phone, looper);
            Phone phone, Looper looper, FeatureFlags featureFlags) {
        super("GsmInboundSmsHandler", context, storageMonitor, phone, looper, featureFlags);
        phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
        mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId());
        mCellBroadcastServiceManager.enable();
@@ -129,9 +130,10 @@ public class GsmInboundSmsHandler extends InboundSmsHandler {
     * Wait for state machine to enter startup state. We can't send any messages until then.
     */
    public static GsmInboundSmsHandler makeInboundSmsHandler(Context context,
            SmsStorageMonitor storageMonitor, Phone phone, Looper looper) {
            SmsStorageMonitor storageMonitor, Phone phone, Looper looper,
            FeatureFlags featureFlags) {
        GsmInboundSmsHandler handler =
                new GsmInboundSmsHandler(context, storageMonitor, phone, looper);
                new GsmInboundSmsHandler(context, storageMonitor, phone, looper, featureFlags);
        handler.start();
        return handler;
    }
Loading