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

Commit 56dfb3de authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Handle SMS status reports over CS and IMS in common"

parents 3f8bfc7a 38a91764
Loading
Loading
Loading
Loading
+14 −30
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.telephony.ims.stub.ImsSmsImplBase.SendStatusResult;
import android.util.Pair;

import com.android.ims.FeatureConnector;
import com.android.ims.ImsException;
@@ -130,11 +129,12 @@ public class ImsSmsDispatcher extends SMSDispatcher {
            tracker.mMessageRef = messageRef;
            switch(status) {
                case ImsSmsImplBase.SEND_STATUS_OK:
                    if (tracker.mDeliveryIntent == null) {
                        // Remove the tracker here if a status report is not requested.
                        mTrackers.remove(token);
                    if (tracker.mDeliveryIntent != null) {
                        // Expecting a status report. Put this tracker to the map.
                        mSmsDispatchersController.putDeliveryPendingTracker(tracker);
                    }
                    tracker.onSent(mContext);
                    mTrackers.remove(token);
                    mPhone.notifySmsSent(tracker.mDestAddress);
                    break;
                case ImsSmsImplBase.SEND_STATUS_ERROR:
@@ -147,7 +147,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                    break;
                case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
                    tracker.mRetryCount += 1;
                    fallbackToPstn(token, tracker);
                    mTrackers.remove(token);
                    fallbackToPstn(tracker);
                    break;
                default:
            }
@@ -164,35 +165,18 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                        "Status report received with a PDU that could not be parsed.");
            }
            int messageRef = message.mWrappedSmsMessage.mMessageRef;
            SmsTracker tracker = null;
            int key = 0;
            for (Map.Entry<Integer, SmsTracker> entry : mTrackers.entrySet()) {
                if (messageRef == ((SmsTracker) entry.getValue()).mMessageRef) {
                    tracker = entry.getValue();
                    key = entry.getKey();
                    break;
                }
            boolean handled = mSmsDispatchersController.handleSmsStatusReport(format, pdu);
            if (!handled) {
                loge("Can not handle the status report for messageRef " + messageRef);
            }

            if (tracker == null) {
                throw new RemoteException("No tracker for messageRef " + messageRef);
            }
            Pair<Boolean, Boolean> result = mSmsDispatchersController.handleSmsStatusReport(
                    tracker, format, pdu);
            logd("Status report handle result, success: " + result.first
                    + " complete: " + result.second);
            try {
                getImsManager().acknowledgeSmsReport(
                        token,
                        messageRef,
                        result.first ? ImsSmsImplBase.STATUS_REPORT_STATUS_OK
                        handled ? ImsSmsImplBase.STATUS_REPORT_STATUS_OK
                                : ImsSmsImplBase.STATUS_REPORT_STATUS_ERROR);
            } catch (ImsException e) {
                loge("Failed to acknowledgeSmsReport(). Error: "
                        + e.getMessage());
            }
            if (result.second) {
                mTrackers.remove(key);
                loge("Failed to acknowledgeSmsReport(). Error: " + e.getMessage());
            }
        }

@@ -407,7 +391,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                    ImsSmsImplBase.SEND_STATUS_OK);
        } catch (ImsException e) {
            loge("sendSms failed. Falling back to PSTN. Error: " + e.getMessage());
            fallbackToPstn(token, tracker);
            mTrackers.remove(token);
            fallbackToPstn(tracker);
            mMetrics.writeImsServiceSendSms(mPhone.getPhoneId(), format,
                    ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK);
        }
@@ -418,9 +403,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
    }

    @VisibleForTesting
    public void fallbackToPstn(int token, SmsTracker tracker) {
    public void fallbackToPstn(SmsTracker tracker) {
        mSmsDispatchersController.sendRetrySms(tracker);
        mTrackers.remove(token);
    }

    @Override
+2 −11
Original line number Diff line number Diff line
@@ -259,15 +259,6 @@ public abstract class SMSDispatcher extends Handler {
        Rlog.d(TAG, "handleStatusReport() called with no subclass.");
    }

    /* TODO: Need to figure out how to keep track of status report routing in a
     *       persistent manner. If the phone process restarts (reboot or crash),
     *       we will lose this list and any status reports that come in after
     *       will be dropped.
     */
    /** Sent messages awaiting a delivery status report. */
    @UnsupportedAppUsage
    protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();

    /**
     * Handles events coming from the phone stack. Overridden from handler.
     *
@@ -758,8 +749,8 @@ public abstract class SMSDispatcher extends Handler {
            if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);

            if (tracker.mDeliveryIntent != null) {
                // Expecting a status report.  Add it to the list.
                deliveryPendingList.add(tracker);
                // Expecting a status report. Put this tracker to the map.
                mSmsDispatchersController.putDeliveryPendingTracker(tracker);
            }
            tracker.onSent(mContext);
            mPhone.notifySmsSent(tracker.mDestAddress);
+63 −73
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.provider.Telephony.Sms.Intents;
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
@@ -52,7 +51,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

/**
 *
@@ -110,6 +108,26 @@ public class SmsDispatchersController extends Handler {
    private boolean mIms = false;
    private String mImsSmsFormat = SmsConstants.FORMAT_UNKNOWN;

    /** 3GPP format sent messages awaiting a delivery status report. */
    private HashMap<Integer, SMSDispatcher.SmsTracker> mDeliveryPendingMapFor3GPP = new HashMap<>();

    /** 3GPP2 format sent messages awaiting a delivery status report. */
    private HashMap<Integer, SMSDispatcher.SmsTracker> mDeliveryPendingMapFor3GPP2 =
            new HashMap<>();

    /**
     * Puts a delivery pending tracker to the map based on the format.
     *
     * @param tracker the tracker awaiting a delivery status report.
     */
    public void putDeliveryPendingTracker(SMSDispatcher.SmsTracker tracker) {
        if (isCdmaFormat(tracker.mFormat)) {
            mDeliveryPendingMapFor3GPP2.put(tracker.mMessageRef, tracker);
        } else {
            mDeliveryPendingMapFor3GPP.put(tracker.mMessageRef, tracker);
        }
    }

    public SmsDispatchersController(Phone phone, SmsStorageMonitor storageMonitor,
            SmsUsageMonitor usageMonitor) {
        Rlog.d(TAG, "SmsDispatchersController created");
@@ -760,86 +778,58 @@ public class SmsDispatchersController extends Handler {
    }

    /**
     * Handles the sms status report for the sent sms through ImsSmsDispatcher. Carriers can send
     * the report over CS even if the previously submitted SMS-SUBMIT was sent over IMS. For this
     * case, finds a corresponding tracker from the tracker map in ImsSmsDispatcher and handles it.
     *
     * @param messageRef the TP-MR of the previously submitted SMS-SUBMIT in the report.
     * @param format the format.
     * @param pdu the pdu of the report.
     */
    public void handleSentOverImsStatusReport(int messageRef, String format, byte[] pdu) {
        for (Entry<Integer, SMSDispatcher.SmsTracker> entry :
                mImsSmsDispatcher.mTrackers.entrySet()) {
            int token = entry.getKey();
            SMSDispatcher.SmsTracker tracker = entry.getValue();
            if (tracker.mMessageRef == messageRef) {
                Pair<Boolean, Boolean> result = handleSmsStatusReport(tracker, format, pdu);
                if (result.second) {
                    mImsSmsDispatcher.mTrackers.remove(token);
                }
                return;
            }
        }
    }

    /**
     * Triggers the correct method for handling the sms status report based on the format.
     * Handles the sms status report based on the format.
     *
     * @param tracker the sms tracker.
     * @param format the format.
     * @param pdu the pdu of the report.
     * @return a Pair in which the first boolean is whether the report was handled successfully
     *          or not and the second boolean is whether processing the sms is complete and the
     *          tracker no longer need to be kept track of, false if we should expect more callbacks
     *          and the tracker should be kept.
     * @return true if the report is handled successfully, false Otherwise.
     */
    public Pair<Boolean, Boolean> handleSmsStatusReport(SMSDispatcher.SmsTracker tracker,
            String format, byte[] pdu) {
    public boolean handleSmsStatusReport(String format, byte[] pdu) {
        int messageRef;
        SMSDispatcher.SmsTracker tracker;
        boolean handled = false;
        if (isCdmaFormat(format)) {
            return handleCdmaStatusReport(tracker, format, pdu);
        } else {
            return handleGsmStatusReport(tracker, format, pdu);
        }
    }

    private Pair<Boolean, Boolean> handleCdmaStatusReport(SMSDispatcher.SmsTracker tracker,
            String format, byte[] pdu) {
            com.android.internal.telephony.cdma.SmsMessage sms =
                    com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
        boolean complete = false;
        boolean success = false;
            if (sms != null) {
            // The status is composed of an error class (bits 25-24) and a status code (bits 23-16).
                messageRef = sms.mMessageRef;
                tracker = mDeliveryPendingMapFor3GPP2.get(messageRef);
                if (tracker != null) {
                    // The status is composed of an error class (bits 25-24) and a status code
                    // (bits 23-16).
                    int errorClass = (sms.getStatus() >> 24) & 0x03;
                    if (errorClass != ERROR_TEMPORARY) {
                        // Update the message status (COMPLETE or FAILED)
                        tracker.updateSentMessageStatus(
                                mContext,
                        (errorClass == ERROR_NONE) ? Sms.STATUS_COMPLETE : Sms.STATUS_FAILED);
                complete = true;
                                (errorClass == ERROR_NONE)
                                        ? Sms.STATUS_COMPLETE
                                        : Sms.STATUS_FAILED);
                        // No longer need to be kept.
                        mDeliveryPendingMapFor3GPP2.remove(messageRef);
                    }
            success = triggerDeliveryIntent(tracker, format, pdu);
                    handled = triggerDeliveryIntent(tracker, format, pdu);
                }
        return new Pair(success, complete);
            }

    private Pair<Boolean, Boolean> handleGsmStatusReport(SMSDispatcher.SmsTracker tracker,
            String format, byte[] pdu) {
        } else {
            com.android.internal.telephony.gsm.SmsMessage sms =
                    com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
        boolean complete = false;
        boolean success = false;
            if (sms != null) {
                messageRef = sms.mMessageRef;
                tracker = mDeliveryPendingMapFor3GPP.get(messageRef);
                if (tracker != null) {
                    int tpStatus = sms.getStatus();
                    if (tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING) {
                        // Update the message status (COMPLETE or FAILED)
                        tracker.updateSentMessageStatus(mContext, tpStatus);
                complete = true;
                        // No longer need to be kept.
                        mDeliveryPendingMapFor3GPP.remove(messageRef);
                    }
                    handled = triggerDeliveryIntent(tracker, format, pdu);
                }
            }
            success = triggerDeliveryIntent(tracker, format, pdu);
        }
        return new Pair(success, complete);
        return handled;
    }

    private boolean triggerDeliveryIntent(SMSDispatcher.SmsTracker tracker, String format,
+3 −29
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.util.Pair;

import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.GsmCdmaPhone;
@@ -63,8 +62,9 @@ public class CdmaSMSDispatcher extends SMSDispatcher {
    @Override
    protected void handleStatusReport(Object o) {
        if (o instanceof SmsMessage) {
            if (VDBG) Rlog.d(TAG, "calling handleCdmaStatusReport()");
            handleCdmaStatusReport((SmsMessage) o);
            if (VDBG) Rlog.d(TAG, "calling handleSmsStatusReport()");
            byte[] pdu = ((SmsMessage) o).getPdu();
            mSmsDispatchersController.handleSmsStatusReport(SmsConstants.FORMAT_3GPP2, pdu);
        } else {
            Rlog.e(TAG, "handleStatusReport() called for object type " + o.getClass().getName());
        }
@@ -95,32 +95,6 @@ public class CdmaSMSDispatcher extends SMSDispatcher {
    protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
        return SMSDispatcherUtil.calculateLengthCdma(messageBody, use7bitOnly);
    }
    /**
     * Called from parent class to handle status report from {@code CdmaInboundSmsHandler}.
     * @param sms the CDMA SMS message to process
     */
    @UnsupportedAppUsage
    private void handleCdmaStatusReport(SmsMessage sms) {
        byte[] pdu = sms.getPdu();
        int messageRef = sms.mMessageRef;
        boolean handled = false;
        for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
            SmsTracker tracker = deliveryPendingList.get(i);
            if (tracker.mMessageRef == messageRef) {
                Pair<Boolean, Boolean> result =
                        mSmsDispatchersController.handleSmsStatusReport(tracker, getFormat(), pdu);
                if (result.second) {
                    deliveryPendingList.remove(i);
                }
                handled = true;
                break; // Only expect to see one tracker matching this message.
            }
        }
        if (!handled) {
            // Try to find the sent SMS from the map in ImsSmsDispatcher.
            mSmsDispatchersController.handleSentOverImsStatusReport(messageRef, getFormat(), pdu);
        }
    }

    /** {@inheritDoc} */
    @Override
+1 −26
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.ServiceState;
import android.util.Pair;

import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.InboundSmsHandler;
@@ -139,31 +138,7 @@ public final class GsmSMSDispatcher extends SMSDispatcher {
     */
    private void handleStatusReport(AsyncResult ar) {
        byte[] pdu = (byte[]) ar.result;
        SmsMessage sms = SmsMessage.createFromPdu(pdu);
        boolean handled = false;

        if (sms != null) {
            int messageRef = sms.mMessageRef;
            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
                SmsTracker tracker = deliveryPendingList.get(i);
                if (tracker.mMessageRef == messageRef) {
                    Pair<Boolean, Boolean> result = mSmsDispatchersController.handleSmsStatusReport(
                            tracker,
                            getFormat(),
                            pdu);
                    if (result.second) {
                        deliveryPendingList.remove(i);
                    }
                    handled = true;
                    break; // Only expect to see one tracker matching this messageref
                }
            }
            if (!handled) {
                // Try to find the sent SMS from the map in ImsSmsDispatcher.
                mSmsDispatchersController.handleSentOverImsStatusReport(
                        messageRef, getFormat(), pdu);
            }
        }
        mSmsDispatchersController.handleSmsStatusReport(SmsConstants.FORMAT_3GPP, pdu);
        mCi.acknowledgeLastIncomingGsmSms(true, 0 /* cause */, null);
    }

Loading