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

Commit ae5e4668 authored by Sungcheol Ahn's avatar Sungcheol Ahn Committed by Android (Google) Code Review
Browse files

Merge "Implemented MT SMS polling The codes related to resources can be...

Merge "Implemented MT SMS polling The codes related to resources can be replaced when Google implements carrier configs for this feature" into main
parents d4e89077 f73776b4
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;

@@ -759,6 +760,11 @@ public abstract class InboundSmsHandler extends StateMachine {
            return Intents.RESULT_SMS_HANDLED;
        }

        if (isMtSmsPollingMessage(smsb)) {
            log("Received MT SMS polling message. Ignored.");
            return Intents.RESULT_SMS_HANDLED;
        }

        int result = dispatchMessageRadioSpecific(smsb, smsSource, token);

        // In case of error, add to metrics. This is not required in case of success, as the
@@ -1982,6 +1988,17 @@ public abstract class InboundSmsHandler extends StateMachine {
        sendMessage(EVENT_BROADCAST_COMPLETE);
    }

    private boolean isMtSmsPollingMessage(@NonNull SmsMessageBase smsb) {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()
                || !mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling)) {
            return false;
        }
        String mtSmsPollingText = mContext.getResources()
                .getString(R.string.config_mt_sms_polling_text);
        return !TextUtils.isEmpty(mtSmsPollingText)
                && mtSmsPollingText.equals(smsb.getMessageBody());
    }

    /** Checks whether the flag to skip new message notification is set in the bitmask returned
     *  from the carrier app.
     */
+48 −6
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Binder;
@@ -46,6 +47,7 @@ import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.SubscriptionManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
@@ -65,6 +67,7 @@ import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
import com.android.internal.telephony.gsm.GsmSMSDispatcher;
import com.android.internal.telephony.satellite.DatagramDispatcher;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.R;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
@@ -245,13 +248,15 @@ public class SmsDispatchersController extends Handler {
        public final long messageId;
        public final boolean skipShortCodeCheck;
        public final long uniqueMessageId;
        public final boolean isMtSmsPolling;

        public PendingRequest(int type, SMSDispatcher.SmsTracker tracker, String callingPackage,
                int callingUser, String destAddr, String scAddr,
                ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
                boolean isForVvm, byte[] data, int destPort, ArrayList<String> texts,
                Uri messageUri, boolean persistMessage, int priority, boolean expectMore,
                int validityPeriod, long messageId, boolean skipShortCodeCheck) {
                int validityPeriod, long messageId, boolean skipShortCodeCheck,
                boolean isMtSmsPolling) {
            this.type = type;
            this.tracker = tracker;
            this.callingPackage = callingPackage;
@@ -278,6 +283,7 @@ public class SmsDispatchersController extends Handler {
            } else {
                this.uniqueMessageId = getNextUniqueMessageId();
            }
            this.isMtSmsPolling = isMtSmsPolling;
        }

        public static long getNextUniqueMessageId() {
@@ -834,7 +840,7 @@ public class SmsDispatchersController extends Handler {
                        null, UserHandle.USER_NULL, null, null,
                        null, null, false, null, 0,
                        null, null, false,
                        0, false, 0, 0L, false);
                        0, false, 0, 0L, false, false);
                args.arg3 = "sendRetrySms";
                sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
                return;
@@ -1622,7 +1628,7 @@ public class SmsDispatchersController extends Handler {
                            destAddr, scAddr, asArrayList(sentIntent),
                            asArrayList(deliveryIntent), isForVvm, data, destPort, null,
                            null, false, 0, false, 0,
                            0L, false),
                            0L, false, false),
                    "sendData");
            return;
        }
@@ -1858,7 +1864,7 @@ public class SmsDispatchersController extends Handler {
                callingPkg, callingUser, destAddr, scAddr, asArrayList(sentIntent),
                asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
                messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
                skipShortCodeCheck);
                skipShortCodeCheck, false);

        if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
            // Send P2P SMS using carrier roaming NB IOT NTN
@@ -2023,7 +2029,7 @@ public class SmsDispatchersController extends Handler {
        PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
                callingPkg, callingUser, destAddr, scAddr, sentIntents, deliveryIntents, false,
                null, 0, parts, messageUri, persistMessage, priority, expectMore,
                validityPeriod, messageId, false);
                validityPeriod, messageId, false, false);

        if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
            // Send multipart P2P SMS using carrier roaming NB IOT NTN
@@ -2200,7 +2206,7 @@ public class SmsDispatchersController extends Handler {
     */
    public void sendCarrierRoamingNbIotNtnText(@NonNull PendingRequest request) {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
            logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
            logd("sendCarrierRoamingNbIotNtnText: carrier roaming nb iot ntn "
                    + "feature flag is disabled");
            return;
        }
@@ -2228,6 +2234,42 @@ public class SmsDispatchersController extends Handler {
        sendMessage(obtainMessage(EVENT_SEND_TEXT_OVER_NTN_ERROR, pendingRequest));
    }

    /**
     * This API should be used only by {@link DatagramDispatcher} to send MT SMS Polling message
     * over non-terrestrial network.
     * To enable users to receive incoming messages, the device needs to send an MO SMS to itself
     * to trigger SMSC to send all pending SMS to the particular subscription.
     */
    public void sendMtSmsPollingMessage() {
        if (!SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
            logd("sendMtSmsPollingMessage: not in roaming nb iot ntn");
            return;
        }

        SubscriptionManager subscriptionManager = (SubscriptionManager) mContext
                .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        String destAddr = subscriptionManager.getPhoneNumber(mPhone.getSubId());
        if (TextUtils.isEmpty(destAddr)) {
            logd("sendMtSmsPollingMessage: destAddr is null or empty.");
            return;
        }

        String mtSmsPollingText = mContext.getResources()
                .getString(R.string.config_mt_sms_polling_text);
        if (TextUtils.isEmpty(mtSmsPollingText)) {
            logd("sendMtSmsPollingMessage: mtSmsPollingText is null or empty.");
            return;
        }

        String callingPackage = mContext.getPackageName();
        PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_TEXT, null,
                callingPackage, Binder.getCallingUserHandle().getIdentifier(), destAddr,
                getSmscAddressFromUSIMWithPhoneIdentity(callingPackage), asArrayList(null),
                asArrayList(null), false, null, 0, asArrayList(mtSmsPollingText), null, false, 0,
                false, 5, 0L, true, true);

        DatagramDispatcher.getInstance().sendSms(pendingRequest);
    }

    public interface SmsInjectionCallback {
        void onSmsInjectedResult(int result);
+120 −8
Original line number Diff line number Diff line
@@ -16,9 +16,12 @@

package com.android.internal.telephony.satellite;

import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
@@ -75,6 +78,7 @@ public class DatagramDispatcher extends Handler {
    private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
    private static final int CMD_SEND_SMS = 8;
    private static final int EVENT_SEND_SMS_DONE = 9;
    private static final int EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT = 10;
    private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
    @NonNull private static DatagramDispatcher sInstance;
    @NonNull private final Context mContext;
@@ -130,6 +134,15 @@ public class DatagramDispatcher extends Handler {
    private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
    @Nullable private PersistentLogger mPersistentLogger = null;

    @GuardedBy("mLock")
    private int mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
    @GuardedBy("mLock")
    private boolean mHasEnteredConnectedState = false;
    @GuardedBy("mLock")
    private boolean mShouldPollMtSms = false;
    @GuardedBy("mLock")
    private boolean mIsMtSmsPollingThrottled = false;

    /**
     * Create the DatagramDispatcher singleton instance.
     * @param context The Context to use to create the DatagramDispatcher.
@@ -402,6 +415,16 @@ public class DatagramDispatcher extends Handler {
                break;
            }

            case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
                synchronized (mLock) {
                    mIsMtSmsPollingThrottled = false;
                    if (mIsAligned && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
                        sendMtSmsPollingMessage();
                    }
                }
                break;
            }

            default:
                plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
                break;
@@ -491,6 +514,10 @@ public class DatagramDispatcher extends Handler {
            mIsAligned = isAligned;
            plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
            if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
            if (isAligned && !mIsMtSmsPollingThrottled
                    && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
                sendMtSmsPollingMessage();
            }
        }
    }

@@ -759,6 +786,7 @@ public class DatagramDispatcher extends Handler {
     */
    public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
        synchronized (mLock) {
            mModemState = state;
            if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
                    || state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
                plogd("onSatelliteModemStateChanged: cleaning up resources");
@@ -767,11 +795,23 @@ public class DatagramDispatcher extends Handler {
                sendPendingMessages();
            }

            if (state == SATELLITE_MODEM_STATE_CONNECTED
                    && isDatagramWaitForConnectedStateTimerStarted()) {
            if (state == SATELLITE_MODEM_STATE_CONNECTED) {
                mHasEnteredConnectedState = true;
                if (isDatagramWaitForConnectedStateTimerStarted()) {
                    stopDatagramWaitForConnectedStateTimer();
                    sendPendingMessages();
                }
                if (mIsAligned && !mIsMtSmsPollingThrottled) {
                    sendMtSmsPollingMessage();
                }
            }

            if (state == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
                if (mHasEnteredConnectedState) {
                    mHasEnteredConnectedState = false;
                    mShouldPollMtSms = shouldPollMtSms();
                }
            }
        }
    }

@@ -803,6 +843,10 @@ public class DatagramDispatcher extends Handler {
        mSendSatelliteDatagramRequest = null;
        mIsAligned = false;
        mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
        mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
        mHasEnteredConnectedState = false;
        mShouldPollMtSms = false;
        stopMtSmsPollingThrottle();
    }

    /** @return {@code true} if already sent an emergency datagram during a session. */
@@ -1060,7 +1104,8 @@ public class DatagramDispatcher extends Handler {
        synchronized (mLock) {
            // Add SMS to pending list
            mPendingSmsMap.put(messageId, pendingSms);
            int datagramType = SatelliteManager.DATAGRAM_TYPE_SMS;
            int datagramType = pendingSms.isMtSmsPolling ?
                    DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
            mLastSendRequestDatagramType = datagramType;

            if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
@@ -1106,7 +1151,9 @@ public class DatagramDispatcher extends Handler {

            mSendingInProgress = true;
            PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
            mDatagramController.updateSendStatus(subId, DATAGRAM_TYPE_SMS,
            mDatagramController.updateSendStatus(subId,
                    pendingRequest.isMtSmsPolling ?
                            DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS,
                    SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
                    getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
            sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
@@ -1170,8 +1217,9 @@ public class DatagramDispatcher extends Handler {
    private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
        synchronized (mLock) {
            mSendingInProgress = false;
            mPendingSmsMap.remove(messageId);
            int datagramType = DATAGRAM_TYPE_SMS;
            PendingRequest pendingSms = mPendingSmsMap.remove(messageId);
            int datagramType = pendingSms != null && pendingSms.isMtSmsPolling
                    ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS  : DATAGRAM_TYPE_SMS;

            plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
                    + " success=" + success);
@@ -1180,6 +1228,9 @@ public class DatagramDispatcher extends Handler {
                mDatagramController.updateSendStatus(subId, datagramType,
                        SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
                        getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
                if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS) {
                    startMtSmsPollingThrottle();
                }
            } else {
                mDatagramController.updateSendStatus(subId, datagramType,
                        SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
@@ -1196,6 +1247,67 @@ public class DatagramDispatcher extends Handler {
        }
    }

    private boolean isEnabledMtSmsPolling() {
        return mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling);
    }

    private long getMtSmsPollingThrottleMillis() {
        return mContext.getResources().getInteger(
                R.integer.config_mt_sms_polling_throttle_millis);
    }

    private boolean shouldPollMtSms() {
        return isEnabledMtSmsPolling()
                && SatelliteController.getInstance().isInCarrierRoamingNbIotNtn();
    }

    @GuardedBy("mLock")
    private void sendMtSmsPollingMessage() {
        if (!mShouldPollMtSms) {
            return;
        }

        plogd("sendMtSmsPollingMessage");
        mShouldPollMtSms = false;

        for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
            PendingRequest pendingRequest = entry.getValue();
            if (pendingRequest.isMtSmsPolling) {
                plogd("sendMtSmsPollingMessage: mPendingSmsMap already has the polling message.");
                return;
            }
        }

        Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
        if (satellitePhone == null) {
            ploge("sendMtSmsPollingMessage: satellitePhone is null.");
            return;
        }

        SmsDispatchersController smsDispatchersController =
                satellitePhone.getSmsDispatchersController();
        if (smsDispatchersController == null) {
            ploge("sendMtSmsPollingMessage: smsDispatchersController is null.");
            return;
        }

        smsDispatchersController.sendMtSmsPollingMessage();
    }

    @GuardedBy("mLock")
    private void startMtSmsPollingThrottle() {
        plogd("startMtSmsPollingThrottle");
        mIsMtSmsPollingThrottled = true;
        sendMessageDelayed(obtainMessage(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT),
                getMtSmsPollingThrottleMillis());
    }

    @GuardedBy("mLock")
    private void stopMtSmsPollingThrottle() {
        mIsMtSmsPollingThrottled = false;
        removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
    }

    private static void logd(@NonNull String log) {
        Rlog.d(TAG, log);
    }
+1 −1
Original line number Diff line number Diff line
@@ -1391,6 +1391,6 @@ public class SmsDispatchersControllerTest extends TelephonyTest {
                SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
                mCallingUserId, "1111", "2222", asArrayList(mSentIntent), asArrayList(null),
                false, null, 0, asArrayList("text"), null,
                false, 0, false, 10, 100L, false);
                false, 0, false, 10, 100L, false, false);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -1204,6 +1204,6 @@ public class DatagramDispatcherTest extends TelephonyTest {
                SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
                Binder.getCallingUserHandle().getIdentifier(), "1111", "2222", asArrayList(null),
                asArrayList(null), false, null, 0, asArrayList("text"), null, false, 0, false,
                10, 100L, false);
                10, 100L, false, false);
    }
}